From cb13939bc15bbb3d701baf071bf63183f7cc3426 Mon Sep 17 00:00:00 2001 From: martonp Date: Tue, 6 Feb 2024 09:59:37 -0500 Subject: [PATCH 1/6] Add ETHBondV0.sol contract This adds a solidity contract for managing ETH fidelity bonds. In addition to the usual functionalities of creating and refunding bonds, it also allows using funds locked in existing bonds to create a new bond. If a bond with more funds than the existing bonds is being created, the user has to send additional funds, and if a bond is being created with less funds than the existing bonds, a "change" bond is also created with the remainder that maintains the earliest lockTime of the existing bonds. This process will only allow the user to lock funds for a longer period than they were previously locked for, never less. A Hardhat project is also created for this contract to allow easy testing of the smart contract logic. To run the tests, go to the `dex/networks/eth/bondcontracts/v0` folder and run the following: `npm install` `npx hardhat test` --- dex/networks/eth/bond.go | 160 + dex/networks/eth/bond_test.go | 105 + .../eth/bondcontracts/updatecontract.sh | 47 + dex/networks/eth/bondcontracts/v0/.gitignore | 11 + .../eth/bondcontracts/v0/BinRuntimeV0.go | 6 + dex/networks/eth/bondcontracts/v0/contract.go | 425 + .../bondcontracts/v0/contracts/ETHBondV0.sol | 262 + .../eth/bondcontracts/v0/hardhat.config.ts | 9 + .../eth/bondcontracts/v0/package-lock.json | 12012 ++++++++++++++++ .../eth/bondcontracts/v0/package.json | 9 + .../bondcontracts/v0/test/ETHBondV0.test.ts | 202 + .../eth/bondcontracts/v0/tsconfig.json | 36 + dex/testing/dcrdex/genmarkets.sh | 4 +- dex/testing/eth/harness.sh | 54 +- 14 files changed, 13340 insertions(+), 2 deletions(-) create mode 100644 dex/networks/eth/bond.go create mode 100644 dex/networks/eth/bond_test.go create mode 100755 dex/networks/eth/bondcontracts/updatecontract.sh create mode 100644 dex/networks/eth/bondcontracts/v0/.gitignore create mode 100644 dex/networks/eth/bondcontracts/v0/BinRuntimeV0.go create mode 100644 dex/networks/eth/bondcontracts/v0/contract.go create mode 100644 dex/networks/eth/bondcontracts/v0/contracts/ETHBondV0.sol create mode 100644 dex/networks/eth/bondcontracts/v0/hardhat.config.ts create mode 100644 dex/networks/eth/bondcontracts/v0/package-lock.json create mode 100644 dex/networks/eth/bondcontracts/v0/package.json create mode 100644 dex/networks/eth/bondcontracts/v0/test/ETHBondV0.test.ts create mode 100644 dex/networks/eth/bondcontracts/v0/tsconfig.json diff --git a/dex/networks/eth/bond.go b/dex/networks/eth/bond.go new file mode 100644 index 0000000000..95fa38ba4f --- /dev/null +++ b/dex/networks/eth/bond.go @@ -0,0 +1,160 @@ +package eth + +import ( + "fmt" + "math/big" + "strings" + + "decred.org/dcrdex/dex" + bondContract "decred.org/dcrdex/dex/networks/eth/bondcontracts/v0" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" +) + +var ETHBondAddress map[dex.Network]common.Address = map[dex.Network]common.Address{ + dex.Simnet: common.HexToAddress("0x6b4368d3e41a60e20ff8539c843b3cdb38c8a507"), +} + +const ( + // actual = 115460 + NewBondGas uint64 = 200000 + + // actual = 59451 + UpdateBondGas uint64 = 400000 + + // actual = 39003, but this includes refund for clearing storage data. If + // even 50000 is set for the gas limit, the tx will fail. + RefundBondGas uint64 = 200000 +) + +var BondABI = initBondABI() + +func initBondABI() *abi.ABI { + abi, err := abi.JSON(strings.NewReader(bondContract.ETHBondABI)) + if err != nil { + panic(err) + } + return &abi +} + +func PackCreateBondTx(accountID [32]byte, bondID [32]byte, locktime uint64) ([]byte, error) { + return BondABI.Pack("createBond", accountID, bondID, locktime) +} + +func ParseCreateBondTx(data []byte) (accountID [32]byte, id [32]byte, locktime uint64, err error) { + decoded, err := ParseCallData(data, BondABI) + if err != nil { + return [32]byte{}, [32]byte{}, 0, err + } + + if decoded.Name != "createBond" { + return [32]byte{}, [32]byte{}, 0, fmt.Errorf("expected method 'newBond', got '%s'", decoded.Name) + } + + args := decoded.inputs + + const numArgs = 3 + if len(args) != numArgs { + return [32]byte{}, [32]byte{}, 0, fmt.Errorf("expected %d arguments, got %d", numArgs, len(args)) + } + + accountID, ok := args[0].value.([32]byte) + if !ok { + return [32]byte{}, [32]byte{}, 0, fmt.Errorf("expected [32]byte for accountID, got %T", args[0].value) + } + + id, ok = args[1].value.([32]byte) + if !ok { + return [32]byte{}, [32]byte{}, 0, fmt.Errorf("expected [32]byte for id, got %T", args[1].value) + } + + locktime, ok = args[2].value.(uint64) + if !ok { + return [32]byte{}, [32]byte{}, 0, fmt.Errorf("expected uint64 for locktime, got %T", args[2].value) + } + + return accountID, id, locktime, nil +} + +func PackUpdateBondsTx(accountID [32]byte, bondsToUpdate [][32]byte, newBondIDs [][32]byte, value *big.Int, locktime uint64) ([]byte, error) { + return BondABI.Pack("updateBonds", accountID, bondsToUpdate, newBondIDs, value, locktime) +} + +func ParseUpdateBondsTx(data []byte) (accountID [32]byte, bondsToUpdate [][32]byte, newBondIDs [][32]byte, value *big.Int, locktime uint64, err error) { + decoded, err := ParseCallData(data, BondABI) + if err != nil { + return [32]byte{}, nil, nil, nil, 0, err + } + + if decoded.Name != "updateBonds" { + return [32]byte{}, nil, nil, nil, 0, err + } + + args := decoded.inputs + + const numArgs = 5 + if len(args) != numArgs { + return [32]byte{}, nil, nil, nil, 0, err + } + + accountID, ok := args[0].value.([32]byte) + if !ok { + return [32]byte{}, nil, nil, nil, 0, fmt.Errorf("expected [32]byte for value, got %T", args[0].value) + } + + bondsToUpdate, ok = args[1].value.([][32]byte) + if !ok { + return [32]byte{}, nil, nil, nil, 0, fmt.Errorf("expected [][32]byte for value, got %T", args[1].value) + } + + newBondIDs, ok = args[2].value.([][32]byte) + if !ok { + return [32]byte{}, nil, nil, nil, 0, fmt.Errorf("expected [][32]byte for value, got %T", args[2].value) + } + + value, ok = args[3].value.(*big.Int) + if !ok { + return [32]byte{}, nil, nil, nil, 0, fmt.Errorf("expected *big.Int for value, got %T", args[3].value) + } + + locktime, ok = args[4].value.(uint64) + if !ok { + return [32]byte{}, nil, nil, nil, 0, fmt.Errorf("expected uint64 for value, got %T", args[4].value) + } + + return accountID, bondsToUpdate, newBondIDs, value, locktime, nil +} + +func PackRefundBondTx(accountID [32]byte, bondID [32]byte) ([]byte, error) { + return BondABI.Pack("refundBond", accountID, bondID) +} + +func ParseRefundBondTx(data []byte) (accountID [32]byte, bondID [32]byte, err error) { + decoded, err := ParseCallData(data, BondABI) + if err != nil { + return [32]byte{}, [32]byte{}, err + } + + if decoded.Name != "refundBond" { + return [32]byte{}, [32]byte{}, fmt.Errorf("expected method 'refundBond', got '%s'", decoded.Name) + } + + args := decoded.inputs + + const numArgs = 2 + if len(args) != numArgs { + return [32]byte{}, [32]byte{}, fmt.Errorf("expected %d arguments, got %d", numArgs, len(args)) + } + + accountID, ok := args[0].value.([32]byte) + if !ok { + return [32]byte{}, [32]byte{}, fmt.Errorf("expected [32]byte for accountID, got %T", args[0].value) + } + + bondID, ok = args[1].value.([32]byte) + if !ok { + return [32]byte{}, [32]byte{}, fmt.Errorf("expected [32]byte for bondID, got %T", args[1].value) + } + + return accountID, bondID, nil +} diff --git a/dex/networks/eth/bond_test.go b/dex/networks/eth/bond_test.go new file mode 100644 index 0000000000..17b91bb953 --- /dev/null +++ b/dex/networks/eth/bond_test.go @@ -0,0 +1,105 @@ +package eth + +import ( + "math/big" + "testing" + + "decred.org/dcrdex/dex/encode" +) + +func TestPackCreateBondTx(t *testing.T) { + var accountID, bondID [32]byte + copy(accountID[:], encode.RandomBytes(32)) + copy(bondID[:], encode.RandomBytes(32)) + + lockTime := uint64(1632112916) + + packedData, err := PackCreateBondTx(accountID, bondID, lockTime) + if err != nil { + t.Fatal(err) + } + + decodedAccountID, decodedBondID, decodedLockTime, err := ParseCreateBondTx(packedData) + if err != nil { + t.Fatal(err) + } + + if decodedAccountID != accountID { + t.Fatalf("expected accountID %x, got %x", accountID, decodedAccountID) + } + if decodedBondID != bondID { + t.Fatalf("expected bondID %x, got %x", bondID, decodedBondID) + } + if decodedLockTime != lockTime { + t.Fatalf("expected lockTime %d, got %d", lockTime, decodedLockTime) + } +} + +func TestPackUpdateBondsTx(t *testing.T) { + var accountID [32]byte + copy(accountID[:], encode.RandomBytes(32)) + + bondsToUpdate := make([][32]byte, 2) + newBondIDs := make([][32]byte, 2) + for i := 0; i < 2; i++ { + copy(bondsToUpdate[i][:], encode.RandomBytes(32)) + copy(newBondIDs[i][:], encode.RandomBytes(32)) + } + + value := big.NewInt(1000000000) + lockTime := uint64(1632112916) + + packedData, err := PackUpdateBondsTx(accountID, bondsToUpdate, newBondIDs, value, lockTime) + if err != nil { + t.Fatal(err) + } + + decodedAccountID, decodedBondsToUpdate, decodedNewBondIDs, decodedValue, decodedLockTime, err := ParseUpdateBondsTx(packedData) + if err != nil { + t.Fatal(err) + } + + if decodedAccountID != accountID { + t.Fatalf("expected accountID %x, got %x", accountID, decodedAccountID) + } + if len(decodedBondsToUpdate) != len(bondsToUpdate) || len(decodedNewBondIDs) != len(newBondIDs) { + t.Fatalf("expected same length of bondsToUpdate and newBondIDs, got different lengths") + } + for i := 0; i < len(bondsToUpdate); i++ { + if decodedBondsToUpdate[i] != bondsToUpdate[i] { + t.Fatalf("expected bondToUpdate %x, got %x", bondsToUpdate[i], decodedBondsToUpdate[i]) + } + if decodedNewBondIDs[i] != newBondIDs[i] { + t.Fatalf("expected newBondID %x, got %x", newBondIDs[i], decodedNewBondIDs[i]) + } + } + if decodedValue.Cmp(value) != 0 { + t.Fatalf("expected value %s, got %s", value, decodedValue) + } + if decodedLockTime != lockTime { + t.Fatalf("expected lockTime %d, got %d", lockTime, decodedLockTime) + } +} + +func TestPackRefundBondTx(t *testing.T) { + var accountID, bondID [32]byte + copy(accountID[:], encode.RandomBytes(32)) + copy(bondID[:], encode.RandomBytes(32)) + + packedData, err := PackRefundBondTx(accountID, bondID) + if err != nil { + t.Fatal(err) + } + + decodedAccountID, decodedBondID, err := ParseRefundBondTx(packedData) + if err != nil { + t.Fatal(err) + } + + if decodedAccountID != accountID { + t.Fatalf("expected accountID %x, got %x", accountID, decodedAccountID) + } + if decodedBondID != bondID { + t.Fatalf("expected bondID %x, got %x", bondID, decodedBondID) + } +} diff --git a/dex/networks/eth/bondcontracts/updatecontract.sh b/dex/networks/eth/bondcontracts/updatecontract.sh new file mode 100755 index 0000000000..6317b97cd2 --- /dev/null +++ b/dex/networks/eth/bondcontracts/updatecontract.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# This script does 3 things: +# +# 1. Updates contract.go to reflect updated solidity code. +# 2. Generates the runtime bytecoode. This is used to compare against the runtime +# bytecode on chain in order to verify that the expected contract is deployed. +# 3. Updates the bytecode in the harness test. + +if [ "$#" -ne 1 ] +then + echo "Usage: $0 version" >&2 + exit 1 +fi + +VERSION=$1 +PKG_NAME=v${VERSION} +CONTRACT_NAME=ETHBond +SOLIDITY_FILE=./v${VERSION}/contracts/${CONTRACT_NAME}V${VERSION}.sol +if [ ! -f ${SOLIDITY_FILE} ] +then + echo "${SOLIDITY_FILE} does not exist" >&2 + exit 1 +fi + +mkdir temp + +solc --abi --bin --bin-runtime --overwrite --optimize ${SOLIDITY_FILE} -o ./temp/ +BYTECODE=$(<./temp/${CONTRACT_NAME}.bin-runtime) + +cat > "./${PKG_NAME}/BinRuntimeV${VERSION}.go" < Bond) bonds; + } + + // Mapping from accountID => Account. + mapping(bytes32 => Account) accounts; + + // senderIsOrigin ensures that this contract cannot be used by other + // contracts, which reduces possible attack vectors. + modifier senderIsOrigin() { + require(tx.origin == msg.sender, "sender != origin"); + _; + } + + // BondInfo is used to return information about a bond. + struct BondInfo { + bytes32 bondID; + uint value; + uint initBlockNumber; + uint64 locktime; + address owner; + } + + // bondsForAccount returns all the bonds for an account. + function bondsForAccount(bytes32 accountID) external view returns (BondInfo[] memory) { + Account storage account = accounts[accountID]; + + // Arrays in memory cannot be dynamically allocated, so we need to first + // count the number of bonds. + uint numBonds = 0; + bytes32 bondID = account.firstBondID; + while (bondID != bytes32(0)) { + numBonds++; + bondID = account.bonds[bondID].nextBondID; + } + + BondInfo[] memory bonds = new BondInfo[](numBonds); + bondID = account.firstBondID; + for (uint i = 0; i < numBonds; i++) { + Bond storage bond = account.bonds[bondID]; + bonds[i] = BondInfo(bondID, bond.value, bond.initBlockNumber, bond.locktime, bond.owner); + bondID = bond.nextBondID; + } + + return bonds; + } + + // bondData looks up a bond by accountID and bondID and returns all the information + // about the bond. + function bondData(bytes32 accountID, bytes32 bondID) external view returns (uint value, uint initBlockNumber, uint64 locktime, address owner) { + Account storage account = accounts[accountID]; + Bond storage bond = account.bonds[bondID]; + return (bond.value, bond.initBlockNumber, bond.locktime, bond.owner); + } + + // insertBond is a helper function used to insert a new bond into the + // bonds map and also place it at the front of the doubly-linked list. + function insertBond(Account storage account, bytes32 bondID, uint64 locktime, uint value) internal { + Bond storage bond = account.bonds[bondID]; + bond.value = value; + bond.initBlockNumber = block.number; + bond.locktime = locktime; + bond.owner = msg.sender; + + if (account.firstBondID == bytes32(0)) { + account.firstBondID = bondID; + } else { + Bond storage firstBond = account.bonds[account.firstBondID]; + bond.nextBondID = account.firstBondID; + firstBond.prevBondID = bondID; + account.firstBondID = bondID; + } + } + + // createBond creates a new bond for the accountID. The bondID must be unique. + function createBond(bytes32 accountID, bytes32 bondID, uint64 locktime) external payable senderIsOrigin() { + Account storage account = accounts[accountID]; + Bond storage bond = account.bonds[bondID]; + require(bond.value == 0, "bond already exists"); + require(msg.value > 0, "value must be > 0"); + + insertBond(account, bondID, locktime, msg.value); + } + + // verifyBondLocktimesAndOwner checks that the bonds are sorted by locktime, + // the updated locktime, is greater than the locktime of the latest bond, + // and that the owner of all the bonds is the msg.sender. It also returns the + // total value of the bonds. + // A separate function is created for this to avoid a stack too deep error. + function verifyBondLocktimesAndOwner(mapping(bytes32 => Bond) storage accountBonds, bytes32[] memory bondsToUpdate, uint64 locktime) internal view returns (bool, uint, string memory){ + uint totalValue = 0; + uint64 previousLocktime = 0; + for (uint i = 0; i < bondsToUpdate.length; i++) { + bytes32 bondID = bondsToUpdate[i]; + Bond storage bond = accountBonds[bondID]; + if (bond.value == 0) { + return (false, 0, "bond does not exist"); + } + if (bond.owner != msg.sender) { + return (false, 0, "bond owner != msg.sender"); + } + if (bond.locktime < previousLocktime) { + return (false, 0, "bonds must be sorted by locktime"); + } + totalValue += bond.value; + previousLocktime = bond.locktime; + } + + Bond storage latestExpiringBond = accountBonds[bondsToUpdate[bondsToUpdate.length - 1]]; + if (latestExpiringBond.locktime >= locktime) { + return (false, 0, "locktime cannot decrease"); + } + + return (true, totalValue, ""); + } + + // verifyBondUpdate checks if the parameters for updateBond are valid, and if not, returns + // the reason. It also returns the total value of the bonds. + function verifyBondUpdate(bytes32 accountID, bytes32[] memory bondsToUpdate, bytes32[] calldata newBondIDs, uint value, uint64 locktime, uint msgValue) public view returns (bool, uint, string memory) { + mapping(bytes32 => Bond) storage accountBonds = accounts[accountID].bonds; + + (bool valid, uint totalValue, string memory reason) = verifyBondLocktimesAndOwner(accountBonds, bondsToUpdate, locktime); + if (!valid) { + return (false, locktime, reason); + } + + if (totalValue > value) { + Bond storage earliestExpiringBond = accountBonds[bondsToUpdate[0]]; + if (earliestExpiringBond.value < totalValue - value) { + return (false, totalValue, "earliest bond is too small"); + } + if (newBondIDs.length != 2) { + return (false, totalValue, "incorrect number of new bonds"); + } + if (msgValue != 0) { + return (false, totalValue, "no funds required"); + } + } else { + if (newBondIDs.length != 1) { + return (false, totalValue, "incorrect number of new bonds"); + } + if (msgValue + totalValue != value) { + return (false, totalValue, "insufficient funds"); + } + } + + for (uint i = 0; i < newBondIDs.length; i++) { + if (accountBonds[newBondIDs[i]].value != 0) { + return (false, totalValue, "new bond already exists"); + } + } + + return (true, totalValue, ""); + } + + // updateBond uses the funds locked in one or more bonds to create a new + // bond with a longer locktime. If the total value of the bonds is greater + // than the new bond, a "change" bond will be created with the remaining + // amount of value with a lockTime of the earliest expiring bond. + // + // Requirements: + // - bondsToUpdate must be sorted by locktime. + // - The locktime of the new bond must be greater than the locktime of the + // latest bond. + // - The owner of all the bonds must be the msg.sender. + // - If a "change" bond must be created, the value of the earliest expiring + // must be less than the total value of the bonds minus the value of the + // new bond. + // - newBondIDs must contain two IDs if a change is required, and one + // otherwise. + function updateBonds(bytes32 accountID, bytes32[] calldata bondsToUpdate, bytes32[] calldata newBondIDs, uint value, uint64 locktime) external payable senderIsOrigin() { + (bool valid, uint totalValue, string memory reason) = verifyBondUpdate(accountID, bondsToUpdate, newBondIDs, value, locktime, msg.value); + require(valid, reason); + + Account storage account = accounts[accountID]; + + if (totalValue > value) { + Bond storage earliestExpiringBond = account.bonds[bondsToUpdate[0]]; + insertBond(account, newBondIDs[0], earliestExpiringBond.locktime, totalValue - value); + insertBond(account, newBondIDs[1], locktime, value); + } else { + insertBond(account, newBondIDs[0], locktime, value); + } + + for (uint i = 0; i < bondsToUpdate.length; i++) { + removeBond(account, bondsToUpdate[i]); + } + } + + // bondRefundable checks if a bond is refundable. + function bondRefundable(bytes32 accountID, bytes32 bondID) public view returns (bool) { + Account storage account = accounts[accountID]; + Bond storage bond = account.bonds[bondID]; + return bond.value > 0 && bond.locktime < block.timestamp; + } + + // removeBond is a helper function used to remove a bond from an account. + // It removes the bond from the mapping and the doubly linked list. + function removeBond(Account storage account, bytes32 bondID) internal { + Bond storage bond = account.bonds[bondID]; + + if (bond.prevBondID != bytes32(0)) { + account.bonds[bond.prevBondID].nextBondID = bond.nextBondID; + } else { + account.firstBondID = bond.nextBondID; + } + + if (bond.nextBondID != bytes32(0)) { + account.bonds[bond.nextBondID].prevBondID = bond.prevBondID; + } + + delete account.bonds[bondID]; + } + + // refundBond refunds a bond to its owner and deletes it from the account. + function refundBond(bytes32 accountID, bytes32 bondID) external senderIsOrigin() { + require(bondRefundable(accountID, bondID), "bond is not refundable"); + + Account storage account = accounts[accountID]; + Bond storage bond = account.bonds[bondID]; + + uint256 value = bond.value; + address owner = bond.owner; + + removeBond(account, bondID); + + (bool ok, ) = payable(owner).call{value: value}(""); + require(ok == true, "transfer failed"); + } +} diff --git a/dex/networks/eth/bondcontracts/v0/hardhat.config.ts b/dex/networks/eth/bondcontracts/v0/hardhat.config.ts new file mode 100644 index 0000000000..34f65511c8 --- /dev/null +++ b/dex/networks/eth/bondcontracts/v0/hardhat.config.ts @@ -0,0 +1,9 @@ +import "@nomiclabs/hardhat-waffle"; +import "@typechain/hardhat"; +import "hardhat-deploy"; +import "solidity-coverage"; +import "@nomiclabs/hardhat-ethers"; + +module.exports = { + solidity: "0.8.18", +}; diff --git a/dex/networks/eth/bondcontracts/v0/package-lock.json b/dex/networks/eth/bondcontracts/v0/package-lock.json new file mode 100644 index 0000000000..4e592ecb1f --- /dev/null +++ b/dex/networks/eth/bondcontracts/v0/package-lock.json @@ -0,0 +1,12012 @@ +{ + "name": "hardhat-project", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "hardhat-project", + "devDependencies": { + "@nomicfoundation/hardhat-toolbox": "^2.0.2", + "@nomiclabs/hardhat-waffle": "^2.0.5", + "chai": "^4.3.7", + "hardhat-deploy": "^0.11.25" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@ensdomains/ens": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@ensdomains/ens/-/ens-0.4.5.tgz", + "integrity": "sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw==", + "deprecated": "Please use @ensdomains/ens-contracts", + "dev": true, + "peer": true, + "dependencies": { + "bluebird": "^3.5.2", + "eth-ens-namehash": "^2.0.8", + "solc": "^0.4.20", + "testrpc": "0.0.1", + "web3-utils": "^1.0.0-beta.31" + } + }, + "node_modules/@ensdomains/ens/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "dev": true, + "peer": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/@ensdomains/ens/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true, + "peer": true + }, + "node_modules/@ensdomains/ens/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "peer": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", + "dev": true, + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@ensdomains/ens/node_modules/require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", + "dev": true, + "peer": true + }, + "node_modules/@ensdomains/ens/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@ensdomains/ens/node_modules/solc": { + "version": "0.4.26", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.26.tgz", + "integrity": "sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA==", + "dev": true, + "peer": true, + "dependencies": { + "fs-extra": "^0.30.0", + "memorystream": "^0.3.1", + "require-from-string": "^1.1.0", + "semver": "^5.3.0", + "yargs": "^4.7.1" + }, + "bin": { + "solcjs": "solcjs" + } + }, + "node_modules/@ensdomains/ens/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dev": true, + "peer": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==", + "dev": true, + "peer": true + }, + "node_modules/@ensdomains/ens/node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "dev": true, + "peer": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ensdomains/ens/node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true, + "peer": true + }, + "node_modules/@ensdomains/ens/node_modules/yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha512-LqodLrnIDM3IFT+Hf/5sxBnEGECrfdC1uIbgZeJmESCSo4HoCAaKEus8MylXHAkdacGc0ye+Qa+dpkuom8uVYA==", + "dev": true, + "peer": true, + "dependencies": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + } + }, + "node_modules/@ensdomains/ens/node_modules/yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA==", + "dev": true, + "peer": true, + "dependencies": { + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" + } + }, + "node_modules/@ensdomains/resolver": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@ensdomains/resolver/-/resolver-0.2.4.tgz", + "integrity": "sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA==", + "deprecated": "Please use @ensdomains/ens-contracts", + "dev": true, + "peer": true + }, + "node_modules/@ethereum-waffle/chai": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/chai/-/chai-4.0.10.tgz", + "integrity": "sha512-X5RepE7Dn8KQLFO7HHAAe+KeGaX/by14hn90wePGBhzL54tq4Y8JscZFu+/LCwCl6TnkAAy5ebiMoqJ37sFtWw==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereum-waffle/provider": "4.0.5", + "debug": "^4.3.4", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=10.0" + }, + "peerDependencies": { + "ethers": "*" + } + }, + "node_modules/@ethereum-waffle/compiler": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/compiler/-/compiler-4.0.3.tgz", + "integrity": "sha512-5x5U52tSvEVJS6dpCeXXKvRKyf8GICDwiTwUvGD3/WD+DpvgvaoHOL82XqpTSUHgV3bBq6ma5/8gKUJUIAnJCw==", + "dev": true, + "peer": true, + "dependencies": { + "@resolver-engine/imports": "^0.3.3", + "@resolver-engine/imports-fs": "^0.3.3", + "@typechain/ethers-v5": "^10.0.0", + "@types/mkdirp": "^0.5.2", + "@types/node-fetch": "^2.6.1", + "mkdirp": "^0.5.1", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=10.0" + }, + "peerDependencies": { + "ethers": "*", + "solc": "*", + "typechain": "^8.0.0" + } + }, + "node_modules/@ethereum-waffle/ens": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-4.0.3.tgz", + "integrity": "sha512-PVLcdnTbaTfCrfSOrvtlA9Fih73EeDvFS28JQnT5M5P4JMplqmchhcZB1yg/fCtx4cvgHlZXa0+rOCAk2Jk0Jw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.0" + }, + "peerDependencies": { + "@ensdomains/ens": "^0.4.4", + "@ensdomains/resolver": "^0.2.4", + "ethers": "*" + } + }, + "node_modules/@ethereum-waffle/mock-contract": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/mock-contract/-/mock-contract-4.0.4.tgz", + "integrity": "sha512-LwEj5SIuEe9/gnrXgtqIkWbk2g15imM/qcJcxpLyAkOj981tQxXmtV4XmQMZsdedEsZ/D/rbUAOtZbgwqgUwQA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.0" + }, + "peerDependencies": { + "ethers": "*" + } + }, + "node_modules/@ethereum-waffle/provider": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-4.0.5.tgz", + "integrity": "sha512-40uzfyzcrPh+Gbdzv89JJTMBlZwzya1YLDyim8mVbEqYLP5VRYWoGp0JMyaizgV3hMoUFRqJKVmIUw4v7r3hYw==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereum-waffle/ens": "4.0.3", + "@ganache/ethereum-options": "0.1.4", + "debug": "^4.3.4", + "ganache": "7.4.3" + }, + "engines": { + "node": ">=10.0" + }, + "peerDependencies": { + "ethers": "*" + } + }, + "node_modules/@ethereumjs/block": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@ethereumjs/block/-/block-3.6.3.tgz", + "integrity": "sha512-CegDeryc2DVKnDkg5COQrE0bJfw/p0v3GBk2W5/Dj5dOVfEmb50Ux0GLnSPypooLnfqjwFaorGuT9FokWB3GRg==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereumjs/common": "^2.6.5", + "@ethereumjs/tx": "^3.5.2", + "ethereumjs-util": "^7.1.5", + "merkle-patricia-tree": "^4.2.4" + } + }, + "node_modules/@ethereumjs/block/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "dev": true, + "peer": true, + "dependencies": { + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@ethereumjs/block/node_modules/@ethereumjs/tx": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz", + "integrity": "sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereumjs/common": "^2.6.4", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@ethereumjs/blockchain": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@ethereumjs/blockchain/-/blockchain-5.5.3.tgz", + "integrity": "sha512-bi0wuNJ1gw4ByNCV56H0Z4Q7D+SxUbwyG12Wxzbvqc89PXLRNR20LBcSUZRKpN0+YCPo6m0XZL/JLio3B52LTw==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereumjs/block": "^3.6.2", + "@ethereumjs/common": "^2.6.4", + "@ethereumjs/ethash": "^1.1.0", + "debug": "^4.3.3", + "ethereumjs-util": "^7.1.5", + "level-mem": "^5.0.1", + "lru-cache": "^5.1.1", + "semaphore-async-await": "^1.5.1" + } + }, + "node_modules/@ethereumjs/blockchain/node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "dev": true, + "peer": true, + "dependencies": { + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@ethereumjs/common": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.0.tgz", + "integrity": "sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA==", + "dev": true, + "peer": true, + "dependencies": { + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.3" + } + }, + "node_modules/@ethereumjs/ethash": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/ethash/-/ethash-1.1.0.tgz", + "integrity": "sha512-/U7UOKW6BzpA+Vt+kISAoeDie1vAvY4Zy2KF5JJb+So7+1yKmJeJEHOGSnQIj330e9Zyl3L5Nae6VZyh2TJnAA==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereumjs/block": "^3.5.0", + "@types/levelup": "^4.3.0", + "buffer-xor": "^2.0.1", + "ethereumjs-util": "^7.1.1", + "miller-rabin": "^4.0.0" + } + }, + "node_modules/@ethereumjs/ethash/node_modules/buffer-xor": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", + "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.1" + } + }, + "node_modules/@ethereumjs/tx": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.4.0.tgz", + "integrity": "sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereumjs/common": "^2.6.0", + "ethereumjs-util": "^7.1.3" + } + }, + "node_modules/@ethereumjs/vm": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/vm/-/vm-5.6.0.tgz", + "integrity": "sha512-J2m/OgjjiGdWF2P9bj/4LnZQ1zRoZhY8mRNVw/N3tXliGI8ai1sI1mlDPkLpeUUM4vq54gH6n0ZlSpz8U/qlYQ==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereumjs/block": "^3.6.0", + "@ethereumjs/blockchain": "^5.5.0", + "@ethereumjs/common": "^2.6.0", + "@ethereumjs/tx": "^3.4.0", + "async-eventemitter": "^0.2.4", + "core-js-pure": "^3.0.1", + "debug": "^2.2.0", + "ethereumjs-util": "^7.1.3", + "functional-red-black-tree": "^1.0.1", + "mcl-wasm": "^0.7.1", + "merkle-patricia-tree": "^4.2.2", + "rustbn.js": "~0.2.0" + } + }, + "node_modules/@ethereumjs/vm/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@ethereumjs/vm/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "peer": true + }, + "node_modules/@ethersproject/abi": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0" + } + }, + "node_modules/@ethersproject/basex": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", + "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "node_modules/@ethersproject/contracts": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", + "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/hdnode": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", + "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/json-wallets": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", + "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ] + }, + "node_modules/@ethersproject/networks": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", + "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/pbkdf2": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", + "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/sha2": "^5.7.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/providers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", + "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, + "node_modules/@ethersproject/random": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", + "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/sha2": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", + "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/solidity": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", + "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "node_modules/@ethersproject/units": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", + "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", + "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/json-wallets": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", + "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", + "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ganache/ethereum-address": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@ganache/ethereum-address/-/ethereum-address-0.1.4.tgz", + "integrity": "sha512-sTkU0M9z2nZUzDeHRzzGlW724xhMLXo2LeX1hixbnjHWY1Zg1hkqORywVfl+g5uOO8ht8T0v+34IxNxAhmWlbw==", + "dev": true, + "peer": true, + "dependencies": { + "@ganache/utils": "0.1.4" + } + }, + "node_modules/@ganache/ethereum-options": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@ganache/ethereum-options/-/ethereum-options-0.1.4.tgz", + "integrity": "sha512-i4l46taoK2yC41FPkcoDlEVoqHS52wcbHPqJtYETRWqpOaoj9hAg/EJIHLb1t6Nhva2CdTO84bG+qlzlTxjAHw==", + "dev": true, + "peer": true, + "dependencies": { + "@ganache/ethereum-address": "0.1.4", + "@ganache/ethereum-utils": "0.1.4", + "@ganache/options": "0.1.4", + "@ganache/utils": "0.1.4", + "bip39": "3.0.4", + "seedrandom": "3.0.5" + } + }, + "node_modules/@ganache/ethereum-utils": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@ganache/ethereum-utils/-/ethereum-utils-0.1.4.tgz", + "integrity": "sha512-FKXF3zcdDrIoCqovJmHLKZLrJ43234Em2sde/3urUT/10gSgnwlpFmrv2LUMAmSbX3lgZhW/aSs8krGhDevDAg==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereumjs/common": "2.6.0", + "@ethereumjs/tx": "3.4.0", + "@ethereumjs/vm": "5.6.0", + "@ganache/ethereum-address": "0.1.4", + "@ganache/rlp": "0.1.4", + "@ganache/utils": "0.1.4", + "emittery": "0.10.0", + "ethereumjs-abi": "0.6.8", + "ethereumjs-util": "7.1.3" + } + }, + "node_modules/@ganache/ethereum-utils/node_modules/ethereumjs-util": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz", + "integrity": "sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@ganache/options": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@ganache/options/-/options-0.1.4.tgz", + "integrity": "sha512-zAe/craqNuPz512XQY33MOAG6Si1Xp0hCvfzkBfj2qkuPcbJCq6W/eQ5MB6SbXHrICsHrZOaelyqjuhSEmjXRw==", + "dev": true, + "peer": true, + "dependencies": { + "@ganache/utils": "0.1.4", + "bip39": "3.0.4", + "seedrandom": "3.0.5" + } + }, + "node_modules/@ganache/rlp": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@ganache/rlp/-/rlp-0.1.4.tgz", + "integrity": "sha512-Do3D1H6JmhikB+6rHviGqkrNywou/liVeFiKIpOBLynIpvZhRCgn3SEDxyy/JovcaozTo/BynHumfs5R085MFQ==", + "dev": true, + "peer": true, + "dependencies": { + "@ganache/utils": "0.1.4", + "rlp": "2.2.6" + } + }, + "node_modules/@ganache/rlp/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, + "node_modules/@ganache/rlp/node_modules/rlp": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", + "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^4.11.1" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/@ganache/utils": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@ganache/utils/-/utils-0.1.4.tgz", + "integrity": "sha512-oatUueU3XuXbUbUlkyxeLLH3LzFZ4y5aSkNbx6tjSIhVTPeh+AuBKYt4eQ73FFcTB3nj/gZoslgAh5CN7O369w==", + "dev": true, + "peer": true, + "dependencies": { + "emittery": "0.10.0", + "keccak": "3.0.1", + "seedrandom": "3.0.5" + }, + "optionalDependencies": { + "@trufflesuite/bigint-buffer": "1.1.9" + } + }, + "node_modules/@ganache/utils/node_modules/keccak": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", + "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", + "dev": true, + "hasInstallScript": true, + "peer": true, + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true, + "peer": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@metamask/eth-sig-util": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", + "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", + "dev": true, + "peer": true, + "dependencies": { + "ethereumjs-abi": "^0.6.8", + "ethereumjs-util": "^6.2.1", + "ethjs-util": "^0.1.6", + "tweetnacl": "^1.0.3", + "tweetnacl-util": "^0.15.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@metamask/eth-sig-util/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, + "node_modules/@metamask/eth-sig-util/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/@morgan-stanley/ts-mocking-bird": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@morgan-stanley/ts-mocking-bird/-/ts-mocking-bird-0.6.4.tgz", + "integrity": "sha512-57VJIflP8eR2xXa9cD1LUawh+Gh+BVQfVu0n6GALyg/AqV/Nz25kDRvws3i9kIe1PTrbsZZOYpsYp6bXPd6nVA==", + "dev": true, + "peer": true, + "dependencies": { + "lodash": "^4.17.16", + "uuid": "^7.0.3" + }, + "peerDependencies": { + "jasmine": "2.x || 3.x || 4.x", + "jest": "26.x || 27.x || 28.x", + "typescript": ">=4.2" + }, + "peerDependenciesMeta": { + "jasmine": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/@morgan-stanley/ts-mocking-bird/node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "dev": true, + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "peer": true + }, + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "peer": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "peer": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "peer": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nomicfoundation/ethereumjs-block": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.2.2.tgz", + "integrity": "sha512-atjpt4gc6ZGZUPHBAQaUJsm1l/VCo7FmyQ780tMGO8QStjLdhz09dXynmhwVTy5YbRr0FOh/uX3QaEM0yIB2Zg==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-trie": "5.0.5", + "@nomicfoundation/ethereumjs-tx": "4.1.2", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-blockchain": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.2.2.tgz", + "integrity": "sha512-6AIB2MoTEPZJLl6IRKcbd8mUmaBAQ/NMe3O7OsAOIiDjMNPPH5KaUQiLfbVlegT4wKIg/GOsFH7XlH2KDVoJNg==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ethereumjs-block": "4.2.2", + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-ethash": "2.0.5", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-trie": "5.0.5", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "abstract-level": "^1.0.3", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "level": "^8.0.0", + "lru-cache": "^5.1.1", + "memory-level": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-common": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.1.2.tgz", + "integrity": "sha512-JAEBpIua62dyObHM9KI2b4wHZcRQYYge9gxiygTWa3lNCr2zo+K0TbypDpgiNij5MCGNWP1eboNfNfx1a3vkvA==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ethereumjs-util": "8.0.6", + "crc-32": "^1.2.0" + } + }, + "node_modules/@nomicfoundation/ethereumjs-ethash": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.5.tgz", + "integrity": "sha512-xlLdcICGgAYyYmnI3r1t0R5fKGBJNDQSOQxXNjVO99JmxJIdXR5MgPo5CSJO1RpyzKOgzi3uIFn8agv564dZEQ==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ethereumjs-block": "4.2.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "abstract-level": "^1.0.3", + "bigint-crypto-utils": "^3.0.23", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-evm": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.3.2.tgz", + "integrity": "sha512-I00d4MwXuobyoqdPe/12dxUQxTYzX8OckSaWsMcWAfQhgVDvBx6ffPyP/w1aL0NW7MjyerySPcSVfDJAMHjilw==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "@types/async-eventemitter": "^0.2.1", + "async-eventemitter": "^0.2.4", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "mcl-wasm": "^0.7.1", + "rustbn.js": "~0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-rlp": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.3.tgz", + "integrity": "sha512-DZMzB/lqPK78T6MluyXqtlRmOMcsZbTTbbEyAjo0ncaff2mqu/k8a79PBcyvpgAhWD/R59Fjq/x3ro5Lof0AtA==", + "dev": true, + "peer": true, + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-statemanager": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.5.tgz", + "integrity": "sha512-CAhzpzTR5toh/qOJIZUUOnWekUXuRqkkzaGAQrVcF457VhtCmr+ddZjjK50KNZ524c1XP8cISguEVNqJ6ij1sA==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-trie": "5.0.5", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "functional-red-black-tree": "^1.0.1" + } + }, + "node_modules/@nomicfoundation/ethereumjs-trie": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.5.tgz", + "integrity": "sha512-+8sNZrXkzvA1NH5F4kz5RSYl1I6iaRz7mAZRsyxOm0IVY4UaP43Ofvfp/TwOalFunurQrYB5pRO40+8FBcxFMA==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "ethereum-cryptography": "0.1.3", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-tx": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.1.2.tgz", + "integrity": "sha512-emJBJZpmTdUa09cqxQqHaysbBI9Od353ZazeH7WgPb35miMgNY6mb7/3vBA98N5lUW/rgkiItjX0KZfIzihSoQ==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-util": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.6.tgz", + "integrity": "sha512-jOQfF44laa7xRfbfLXojdlcpkvxeHrE2Xu7tSeITsWFgoII163MzjOwFEzSNozHYieFysyoEMhCdP+NY5ikstw==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-vm": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.4.2.tgz", + "integrity": "sha512-PRTyxZMP6kx+OdAzBhuH1LD2Yw+hrSpaytftvaK//thDy2OI07S0nrTdbrdk7b8ZVPAc9H9oTwFBl3/wJ3w15g==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ethereumjs-block": "4.2.2", + "@nomicfoundation/ethereumjs-blockchain": "6.2.2", + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-evm": "1.3.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-statemanager": "1.0.5", + "@nomicfoundation/ethereumjs-trie": "5.0.5", + "@nomicfoundation/ethereumjs-tx": "4.1.2", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "@types/async-eventemitter": "^0.2.1", + "async-eventemitter": "^0.2.4", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "functional-red-black-tree": "^1.0.1", + "mcl-wasm": "^0.7.1", + "rustbn.js": "~0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/hardhat-chai-matchers": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-1.0.6.tgz", + "integrity": "sha512-f5ZMNmabZeZegEfuxn/0kW+mm7+yV7VNDxLpMOMGXWFJ2l/Ct3QShujzDRF9cOkK9Ui/hbDeOWGZqyQALDXVCQ==", + "dev": true, + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@types/chai-as-promised": "^7.1.3", + "chai-as-promised": "^7.1.1", + "deep-eql": "^4.0.1", + "ordinal": "^1.0.3" + }, + "peerDependencies": { + "@nomiclabs/hardhat-ethers": "^2.0.0", + "chai": "^4.2.0", + "ethers": "^5.0.0", + "hardhat": "^2.9.4" + } + }, + "node_modules/@nomicfoundation/hardhat-network-helpers": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.8.tgz", + "integrity": "sha512-MNqQbzUJZnCMIYvlniC3U+kcavz/PhhQSsY90tbEtUyMj/IQqsLwIRZa4ctjABh3Bz0KCh9OXUZ7Yk/d9hr45Q==", + "dev": true, + "peer": true, + "dependencies": { + "ethereumjs-util": "^7.1.4" + }, + "peerDependencies": { + "hardhat": "^2.9.5" + } + }, + "node_modules/@nomicfoundation/hardhat-toolbox": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-2.0.2.tgz", + "integrity": "sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg==", + "dev": true, + "peerDependencies": { + "@ethersproject/abi": "^5.4.7", + "@ethersproject/providers": "^5.4.7", + "@nomicfoundation/hardhat-chai-matchers": "^1.0.0", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomiclabs/hardhat-etherscan": "^3.0.0", + "@typechain/ethers-v5": "^10.1.0", + "@typechain/hardhat": "^6.1.2", + "@types/chai": "^4.2.0", + "@types/mocha": ">=9.1.0", + "@types/node": ">=12.0.0", + "chai": "^4.2.0", + "ethers": "^5.4.7", + "hardhat": "^2.11.0", + "hardhat-gas-reporter": "^1.0.8", + "solidity-coverage": "^0.8.1", + "ts-node": ">=8.0.0", + "typechain": "^8.1.0", + "typescript": ">=4.5.0" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", + "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 12" + }, + "optionalDependencies": { + "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.1", + "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.1", + "@nomicfoundation/solidity-analyzer-freebsd-x64": "0.1.1", + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.1", + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.1", + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.1", + "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.1", + "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": "0.1.1", + "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": "0.1.1", + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.1" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz", + "integrity": "sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.1.tgz", + "integrity": "sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-freebsd-x64": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.1.tgz", + "integrity": "sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.1.tgz", + "integrity": "sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.1.tgz", + "integrity": "sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.1.tgz", + "integrity": "sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.1.tgz", + "integrity": "sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-win32-arm64-msvc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.1.tgz", + "integrity": "sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-win32-ia32-msvc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.1.tgz", + "integrity": "sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.1.tgz", + "integrity": "sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomiclabs/hardhat-ethers": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.2.tgz", + "integrity": "sha512-NLDlDFL2us07C0jB/9wzvR0kuLivChJWCXTKcj3yqjZqMoYp7g7wwS157F70VHx/+9gHIBGzak5pKDwG8gEefA==", + "dev": true, + "peer": true, + "peerDependencies": { + "ethers": "^5.0.0", + "hardhat": "^2.0.0" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz", + "integrity": "sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==", + "dev": true, + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^8.1.0", + "chalk": "^2.4.2", + "debug": "^4.1.1", + "fs-extra": "^7.0.1", + "lodash": "^4.17.11", + "semver": "^6.3.0", + "table": "^6.8.0", + "undici": "^5.14.0" + }, + "peerDependencies": { + "hardhat": "^2.0.4" + } + }, + "node_modules/@nomiclabs/hardhat-waffle": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.5.tgz", + "integrity": "sha512-U1RH9OQ1mWYQfb+moX5aTgGjpVVlOcpiFI47wwnaGG4kLhcTy90cNiapoqZenxcRAITVbr0/+QSduINL5EsUIQ==", + "dev": true, + "peerDependencies": { + "@nomiclabs/hardhat-ethers": "^2.0.0", + "ethereum-waffle": "*", + "ethers": "^5.0.0", + "hardhat": "^2.0.0" + } + }, + "node_modules/@resolver-engine/core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz", + "integrity": "sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ==", + "dev": true, + "peer": true, + "dependencies": { + "debug": "^3.1.0", + "is-url": "^1.2.4", + "request": "^2.85.0" + } + }, + "node_modules/@resolver-engine/core/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@resolver-engine/fs": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.3.3.tgz", + "integrity": "sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ==", + "dev": true, + "peer": true, + "dependencies": { + "@resolver-engine/core": "^0.3.3", + "debug": "^3.1.0" + } + }, + "node_modules/@resolver-engine/fs/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@resolver-engine/imports": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.3.3.tgz", + "integrity": "sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q==", + "dev": true, + "peer": true, + "dependencies": { + "@resolver-engine/core": "^0.3.3", + "debug": "^3.1.0", + "hosted-git-info": "^2.6.0", + "path-browserify": "^1.0.0", + "url": "^0.11.0" + } + }, + "node_modules/@resolver-engine/imports-fs": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz", + "integrity": "sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA==", + "dev": true, + "peer": true, + "dependencies": { + "@resolver-engine/fs": "^0.3.3", + "@resolver-engine/imports": "^0.3.3", + "debug": "^3.1.0" + } + }, + "node_modules/@resolver-engine/imports-fs/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@resolver-engine/imports/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "peer": true + }, + "node_modules/@scure/bip32": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", + "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "peer": true, + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@scure/bip39": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", + "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "peer": true, + "dependencies": { + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@sentry/core": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", + "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", + "dev": true, + "peer": true, + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/hub": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", + "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "dev": true, + "peer": true, + "dependencies": { + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/minimal": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", + "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "dev": true, + "peer": true, + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/node": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", + "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", + "dev": true, + "peer": true, + "dependencies": { + "@sentry/core": "5.30.0", + "@sentry/hub": "5.30.0", + "@sentry/tracing": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/tracing": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", + "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", + "dev": true, + "peer": true, + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/types": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", + "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/utils": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", + "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "dev": true, + "peer": true, + "dependencies": { + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@solidity-parser/parser": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", + "integrity": "sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==", + "dev": true, + "peer": true, + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "node_modules/@trufflesuite/bigint-buffer": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.9.tgz", + "integrity": "sha512-bdM5cEGCOhDSwminryHJbRmXc1x7dPKg6Pqns3qyTwFlxsqUgxE29lsERS3PlIW1HTjoIGMUqsk1zQQwST1Yxw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "peer": true, + "dependencies": { + "node-gyp-build": "4.3.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@trufflesuite/bigint-buffer/node_modules/node-gyp-build": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true, + "peer": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "peer": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "peer": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true, + "peer": true + }, + "node_modules/@typechain/ethers-v5": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-10.2.0.tgz", + "integrity": "sha512-ikaq0N/w9fABM+G01OFmU3U3dNnyRwEahkdvi9mqy1a3XwKiPZaF/lu54OcNaEWnpvEYyhhS0N7buCtLQqC92w==", + "dev": true, + "peer": true, + "dependencies": { + "lodash": "^4.17.15", + "ts-essentials": "^7.0.1" + }, + "peerDependencies": { + "@ethersproject/abi": "^5.0.0", + "@ethersproject/bytes": "^5.0.0", + "@ethersproject/providers": "^5.0.0", + "ethers": "^5.1.3", + "typechain": "^8.1.1", + "typescript": ">=4.3.0" + } + }, + "node_modules/@typechain/hardhat": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-6.1.5.tgz", + "integrity": "sha512-lg7LW4qDZpxFMknp3Xool61Fg6Lays8F8TXdFGBG+MxyYcYU5795P1U2XdStuzGq9S2Dzdgh+1jGww9wvZ6r4Q==", + "dev": true, + "peer": true, + "dependencies": { + "fs-extra": "^9.1.0" + }, + "peerDependencies": { + "@ethersproject/abi": "^5.4.7", + "@ethersproject/providers": "^5.4.7", + "@typechain/ethers-v5": "^10.2.0", + "ethers": "^5.4.7", + "hardhat": "^2.9.9", + "typechain": "^8.1.1" + } + }, + "node_modules/@typechain/hardhat/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "peer": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typechain/hardhat/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@typechain/hardhat/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@types/abstract-leveldown": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@types/abstract-leveldown/-/abstract-leveldown-7.2.1.tgz", + "integrity": "sha512-YK8irIC+eMrrmtGx0H4ISn9GgzLd9dojZWJaMbjp1YHLl2VqqNFBNrL5Q3KjGf4VE3sf/4hmq6EhQZ7kZp1NoQ==", + "dev": true, + "peer": true + }, + "node_modules/@types/async-eventemitter": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz", + "integrity": "sha512-M2P4Ng26QbAeITiH7w1d7OxtldgfAe0wobpyJzVK/XOb0cUGKU2R4pfAhqcJBXAe2ife5ZOhSv4wk7p+ffURtg==", + "dev": true, + "peer": true + }, + "node_modules/@types/bn.js": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", + "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "dev": true, + "peer": true + }, + "node_modules/@types/chai-as-promised": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz", + "integrity": "sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==", + "dev": true, + "peer": true, + "dependencies": { + "@types/chai": "*" + } + }, + "node_modules/@types/concat-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", + "integrity": "sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/form-data": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", + "integrity": "sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/level-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/level-errors/-/level-errors-3.0.0.tgz", + "integrity": "sha512-/lMtoq/Cf/2DVOm6zE6ORyOM+3ZVm/BvzEZVxUhf6bgh8ZHglXlBqxbxSlJeVp8FCbD3IVvk/VbsaNmDjrQvqQ==", + "dev": true, + "peer": true + }, + "node_modules/@types/levelup": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@types/levelup/-/levelup-4.3.3.tgz", + "integrity": "sha512-K+OTIjJcZHVlZQN1HmU64VtrC0jC3dXWQozuEIR9zVvltIk90zaGPM2AgT+fIkChpzHhFE3YnvFLCbLtzAmexA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/abstract-leveldown": "*", + "@types/level-errors": "*", + "@types/node": "*" + } + }, + "node_modules/@types/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", + "dev": true, + "peer": true + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true, + "peer": true + }, + "node_modules/@types/mkdirp": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz", + "integrity": "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mocha": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", + "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "dev": true, + "peer": true + }, + "node_modules/@types/node": { + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", + "dev": true, + "peer": true + }, + "node_modules/@types/node-fetch": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", + "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/pbkdf2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", + "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/prettier": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", + "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", + "dev": true, + "peer": true + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/secp256k1": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz", + "integrity": "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", + "dev": true, + "peer": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "peer": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abstract-level": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz", + "integrity": "sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==", + "dev": true, + "peer": true, + "dependencies": { + "buffer": "^6.0.3", + "catering": "^2.1.0", + "is-buffer": "^2.0.5", + "level-supports": "^4.0.0", + "level-transcoder": "^1.0.1", + "module-error": "^1.0.1", + "queue-microtask": "^1.2.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/abstract-leveldown": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz", + "integrity": "sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==", + "dev": true, + "peer": true, + "dependencies": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/abstract-leveldown/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/abstract-leveldown/node_modules/level-supports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", + "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", + "dev": true, + "peer": true, + "dependencies": { + "xtend": "^4.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", + "dev": true + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "peer": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "peer": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/antlr4ts": { + "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", + "dev": true, + "peer": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "peer": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "peer": true + }, + "node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array.prototype.reduce": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", + "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "peer": true + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "peer": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "peer": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-eventemitter": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", + "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", + "dev": true, + "peer": true, + "dependencies": { + "async": "^2.4.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true, + "peer": true + }, + "node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "peer": true + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "peer": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "peer": true + }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "dev": true + }, + "node_modules/bigint-crypto-utils": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.1.8.tgz", + "integrity": "sha512-+VMV9Laq8pXLBKKKK49nOoq9bfR3j7NNQAtbA617a4nw9bVLo8rsqkKMBgM2AJWlNX9fEIyYaYX+d0laqYV4tw==", + "dev": true, + "peer": true, + "dependencies": { + "bigint-mod-arith": "^3.1.0" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/bigint-mod-arith": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bigint-mod-arith/-/bigint-mod-arith-3.1.2.tgz", + "integrity": "sha512-nx8J8bBeiRR+NlsROFH9jHswW5HO8mgfOSqW0AmjicMMvaONDa8AO+5ViKDUUNytBPWiwfvZP4/Bj4Y3lUfvgQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", + "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bip39": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", + "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "11.11.6", + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1" + } + }, + "node_modules/bip39/node_modules/@types/node": { + "version": "11.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", + "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==", + "dev": true, + "peer": true + }, + "node_modules/blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "dev": true, + "peer": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "peer": true + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true + }, + "node_modules/browser-level": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browser-level/-/browser-level-1.0.1.tgz", + "integrity": "sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==", + "dev": true, + "peer": true, + "dependencies": { + "abstract-level": "^1.0.2", + "catering": "^2.1.1", + "module-error": "^1.0.2", + "run-parallel-limit": "^1.1.0" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "peer": true + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dev": true, + "peer": true, + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, + "peer": true, + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "peer": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "peer": true + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "peer": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true, + "peer": true + }, + "node_modules/catering": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", + "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "dev": true, + "peer": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, + "peer": true, + "dependencies": { + "check-error": "^1.0.2" + }, + "peerDependencies": { + "chai": ">= 2.1.2 < 5" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true, + "peer": true + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/classic-level": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/classic-level/-/classic-level-1.2.0.tgz", + "integrity": "sha512-qw5B31ANxSluWz9xBzklRWTUAJ1SXIdaVKTVS7HcTGKOAmExx65Wo5BUICW+YGORe2FOUaDghoI9ZDxj82QcFg==", + "dev": true, + "hasInstallScript": true, + "peer": true, + "dependencies": { + "abstract-level": "^1.0.2", + "catering": "^2.1.0", + "module-error": "^1.0.1", + "napi-macros": "~2.0.0", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "peer": true, + "dependencies": { + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "colors": "^1.1.2" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "peer": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "peer": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "dev": true, + "peer": true + }, + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", + "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^4.0.2", + "chalk": "^2.4.2", + "table-layout": "^1.0.2", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-usage/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true, + "peer": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "peer": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "peer": true + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/core-js-pure": { + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.29.1.tgz", + "integrity": "sha512-4En6zYVi0i0XlXHVz/bi6l1XDjCqkKRq765NXuX+SnaIatlE96Odt5lMLjdxUiNI1v9OXI5DSLWYPlmTfkTktg==", + "dev": true, + "hasInstallScript": true, + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "peer": true + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "peer": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "peer": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "peer": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "peer": true + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "peer": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/death": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", + "integrity": "sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==", + "dev": true, + "peer": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "peer": true + }, + "node_modules/deferred-leveldown": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", + "integrity": "sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==", + "dev": true, + "peer": true, + "dependencies": { + "abstract-leveldown": "~6.2.1", + "inherits": "^2.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deferred-leveldown/node_modules/abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "dev": true, + "peer": true, + "dependencies": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deferred-leveldown/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/deferred-leveldown/node_modules/level-supports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", + "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", + "dev": true, + "peer": true, + "dependencies": { + "xtend": "^4.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "peer": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-port": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", + "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", + "dev": true, + "peer": true, + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/difflib": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", + "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==", + "dev": true, + "peer": true, + "dependencies": { + "heap": ">= 0.2.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "peer": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "peer": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.0.tgz", + "integrity": "sha512-AGvFfs+d0JKCJQ4o01ASQLGPmSCxgfU9RFXvzPvZdjKK8oscynksuJhWrSTSw7j7Ep/sZct5b5ZhYCi8S/t0HQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "peer": true + }, + "node_modules/encode-utf8": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", + "dev": true + }, + "node_modules/encoding-down": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", + "integrity": "sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==", + "dev": true, + "peer": true, + "dependencies": { + "abstract-leveldown": "^6.2.1", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "peer": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "peer": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dev": true, + "peer": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract/node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true, + "peer": true + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "peer": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "peer": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", + "dev": true, + "peer": true, + "dependencies": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.12.0" + }, + "optionalDependencies": { + "source-map": "~0.2.0" + } + }, + "node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", + "dev": true, + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw==", + "dev": true, + "peer": true, + "dependencies": { + "idna-uts46-hx": "^2.3.1", + "js-sha3": "^0.5.7" + } + }, + "node_modules/eth-ens-namehash/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", + "dev": true, + "peer": true + }, + "node_modules/eth-gas-reporter": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.25.tgz", + "integrity": "sha512-1fRgyE4xUB8SoqLgN3eDfpDfwEfRxh2Sz1b7wzFbyQA+9TekMmvSjjoRu9SKcSVyK+vLkLIsVbJDsTWjw195OQ==", + "dev": true, + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.0.0-beta.146", + "@solidity-parser/parser": "^0.14.0", + "cli-table3": "^0.5.0", + "colors": "1.4.0", + "ethereum-cryptography": "^1.0.3", + "ethers": "^4.0.40", + "fs-readdir-recursive": "^1.1.0", + "lodash": "^4.17.14", + "markdown-table": "^1.1.3", + "mocha": "^7.1.1", + "req-cwd": "^2.0.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "sha1": "^1.1.1", + "sync-request": "^6.0.0" + }, + "peerDependencies": { + "@codechecks/client": "^0.1.0" + }, + "peerDependenciesMeta": { + "@codechecks/client": { + "optional": true + } + } + }, + "node_modules/eth-gas-reporter/node_modules/ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/eth-gas-reporter/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, + "node_modules/eth-gas-reporter/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "peer": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "peer": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "peer": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true, + "peer": true + }, + "node_modules/eth-gas-reporter/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eth-gas-reporter/node_modules/ethereum-cryptography": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "dev": true, + "peer": true, + "dependencies": { + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/ethers": { + "version": "4.0.49", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz", + "integrity": "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==", + "dev": true, + "peer": true, + "dependencies": { + "aes-js": "3.0.0", + "bn.js": "^4.11.9", + "elliptic": "6.5.4", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.4", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, + "peer": true, + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/eth-gas-reporter/node_modules/fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "deprecated": "\"Please update to latest v2.3 or v2.2\"", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eth-gas-reporter/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", + "dev": true, + "peer": true + }, + "node_modules/eth-gas-reporter/node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eth-gas-reporter/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "peer": true, + "dependencies": { + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eth-gas-reporter/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eth-gas-reporter/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/eth-gas-reporter/node_modules/mocha": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", + "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.5", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/eth-gas-reporter/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "peer": true + }, + "node_modules/eth-gas-reporter/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eth-gas-reporter/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "peer": true, + "dependencies": { + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eth-gas-reporter/node_modules/scrypt-js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "dev": true, + "peer": true + }, + "node_modules/eth-gas-reporter/node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==", + "dev": true, + "peer": true + }, + "node_modules/eth-gas-reporter/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "peer": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "peer": true + }, + "node_modules/eth-gas-reporter/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "peer": true + }, + "node_modules/eth-gas-reporter/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "peer": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/eth-gas-reporter/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "peer": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "peer": true, + "dependencies": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ethereum-bloom-filters": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz", + "integrity": "sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==", + "dev": true, + "peer": true, + "dependencies": { + "js-sha3": "^0.8.0" + } + }, + "node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "peer": true, + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ethereum-waffle": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/ethereum-waffle/-/ethereum-waffle-4.0.10.tgz", + "integrity": "sha512-iw9z1otq7qNkGDNcMoeNeLIATF9yKl1M8AIeu42ElfNBplq0e+5PeasQmm8ybY/elkZ1XyRO0JBQxQdVRb8bqQ==", + "dev": true, + "peer": true, + "dependencies": { + "@ethereum-waffle/chai": "4.0.10", + "@ethereum-waffle/compiler": "4.0.3", + "@ethereum-waffle/mock-contract": "4.0.4", + "@ethereum-waffle/provider": "4.0.5", + "solc": "0.8.15", + "typechain": "^8.0.0" + }, + "bin": { + "waffle": "bin/waffle" + }, + "engines": { + "node": ">=10.0" + }, + "peerDependencies": { + "ethers": "*" + } + }, + "node_modules/ethereum-waffle/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ethereum-waffle/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/ethereum-waffle/node_modules/solc": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.15.tgz", + "integrity": "sha512-Riv0GNHNk/SddN/JyEuFKwbcWcEeho15iyupTSHw5Np6WuXA5D8kEHbyzDHi6sqmvLzu2l+8b1YmL8Ytple+8w==", + "dev": true, + "peer": true, + "dependencies": { + "command-exists": "^1.2.8", + "commander": "^8.1.0", + "follow-redirects": "^1.12.1", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solc.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ethereumjs-abi": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", + "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ethereumjs-abi/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ethereumjs-abi/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, + "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", + "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-util": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", + "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, + "node_modules/ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ethjs-unit/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", + "dev": true, + "peer": true + }, + "node_modules/ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, + "peer": true, + "dependencies": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "peer": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "peer": true + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "peer": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "peer": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "peer": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "peer": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "peer": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "peer": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "peer": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/fmix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fmix/-/fmix-0.1.0.tgz", + "integrity": "sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==", + "dev": true, + "dependencies": { + "imul": "^1.0.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "peer": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fp-ts": { + "version": "1.19.3", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", + "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", + "dev": true, + "peer": true + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true, + "peer": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "peer": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true, + "peer": true + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ganache": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/ganache/-/ganache-7.4.3.tgz", + "integrity": "sha512-RpEDUiCkqbouyE7+NMXG26ynZ+7sGiODU84Kz+FVoXUnQ4qQM4M8wif3Y4qUCt+D/eM1RVeGq0my62FPD6Y1KA==", + "bundleDependencies": [ + "@trufflesuite/bigint-buffer", + "emittery", + "keccak", + "leveldown", + "secp256k1", + "@types/bn.js", + "@types/lru-cache", + "@types/seedrandom" + ], + "dev": true, + "hasShrinkwrap": true, + "peer": true, + "dependencies": { + "@trufflesuite/bigint-buffer": "1.1.10", + "@types/bn.js": "^5.1.0", + "@types/lru-cache": "5.1.1", + "@types/seedrandom": "3.0.1", + "emittery": "0.10.0", + "keccak": "3.0.2", + "leveldown": "6.1.0", + "secp256k1": "4.0.3" + }, + "bin": { + "ganache": "dist/node/cli.js", + "ganache-cli": "dist/node/cli.js" + }, + "optionalDependencies": { + "bufferutil": "4.0.5", + "utf-8-validate": "5.0.7" + } + }, + "node_modules/ganache/node_modules/@trufflesuite/bigint-buffer": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.10.tgz", + "integrity": "sha512-pYIQC5EcMmID74t26GCC67946mgTJFiLXOT/BYozgrd4UEY2JHEGLhWi9cMiQCt5BSqFEvKkCHNnoj82SRjiEw==", + "dev": true, + "hasInstallScript": true, + "inBundle": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "node-gyp-build": "4.4.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ganache/node_modules/@trufflesuite/bigint-buffer/node_modules/node-gyp-build": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", + "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/ganache/node_modules/@types/bn.js": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ganache/node_modules/@types/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/@types/node": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.0.tgz", + "integrity": "sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/@types/seedrandom": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-3.0.1.tgz", + "integrity": "sha512-giB9gzDeiCeloIXDgzFBCgjj1k4WxcDrZtGl6h1IqmUPlxF+Nx8Ve+96QCyDZ/HseB/uvDsKbpib9hU5cU53pw==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/ganache/node_modules/bufferutil": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz", + "integrity": "sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + } + }, + "node_modules/ganache/node_modules/catering": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.0.tgz", + "integrity": "sha512-M5imwzQn6y+ODBfgi+cfgZv2hIUI6oYU/0f35Mdb1ujGeqeoI5tOnl9Q13DTH7LW+7er+NYq8stNOKZD/Z3U/A==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "queue-tick": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ganache/node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ganache/node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/emittery": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.0.tgz", + "integrity": "sha512-AGvFfs+d0JKCJQ4o01ASQLGPmSCxgfU9RFXvzPvZdjKK8oscynksuJhWrSTSw7j7Ep/sZct5b5ZhYCi8S/t0HQ==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/ganache/node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/ganache/node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ganache/node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/ganache/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/ganache/node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ganache/node_modules/keccak": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz", + "integrity": "sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==", + "dev": true, + "hasInstallScript": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ganache/node_modules/leveldown": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-6.1.0.tgz", + "integrity": "sha512-8C7oJDT44JXxh04aSSsfcMI8YiaGRhOFI9/pMEL7nWJLVsWajDPTRxsSHTM2WcTVY5nXM+SuRHzPPi0GbnDX+w==", + "dev": true, + "hasInstallScript": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "abstract-leveldown": "^7.2.0", + "napi-macros": "~2.0.0", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/ganache/node_modules/leveldown/node_modules/abstract-leveldown": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz", + "integrity": "sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "buffer": "^6.0.3", + "catering": "^2.0.0", + "is-buffer": "^2.0.5", + "level-concat-iterator": "^3.0.0", + "level-supports": "^2.0.1", + "queue-microtask": "^1.2.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ganache/node_modules/leveldown/node_modules/level-concat-iterator": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz", + "integrity": "sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "catering": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ganache/node_modules/leveldown/node_modules/level-supports": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-2.1.0.tgz", + "integrity": "sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ganache/node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/ganache/node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/napi-macros": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz", + "integrity": "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/node-gyp-build": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/ganache/node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/queue-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.0.tgz", + "integrity": "sha512-ULWhjjE8BmiICGn3G8+1L9wFpERNxkf8ysxkAer4+TFdRefDaXOCV5m92aMB9FtBVmn/8sETXLXY6BfW7hyaWQ==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ganache/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/ganache/node_modules/secp256k1": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", + "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "dev": true, + "hasInstallScript": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "elliptic": "^6.5.4", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ganache/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/ganache/node_modules/utf-8-validate": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz", + "integrity": "sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + } + }, + "node_modules/ganache/node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "peer": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "peer": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/ghost-testrpc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", + "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", + "dev": true, + "peer": true, + "dependencies": { + "chalk": "^2.4.2", + "node-emoji": "^1.10.0" + }, + "bin": { + "testrpc-sc": "index.js" + } + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "peer": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "peer": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "peer": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "peer": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, + "peer": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hardhat": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.13.0.tgz", + "integrity": "sha512-ZlzBOLML1QGlm6JWyVAG8lVTEAoOaVm1in/RU2zoGAnYEoD1Rp4T+ZMvrLNhHaaeS9hfjJ1gJUBfiDr4cx+htQ==", + "dev": true, + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@metamask/eth-sig-util": "^4.0.0", + "@nomicfoundation/ethereumjs-block": "^4.0.0", + "@nomicfoundation/ethereumjs-blockchain": "^6.0.0", + "@nomicfoundation/ethereumjs-common": "^3.0.0", + "@nomicfoundation/ethereumjs-evm": "^1.0.0", + "@nomicfoundation/ethereumjs-rlp": "^4.0.0", + "@nomicfoundation/ethereumjs-statemanager": "^1.0.0", + "@nomicfoundation/ethereumjs-trie": "^5.0.0", + "@nomicfoundation/ethereumjs-tx": "^4.0.0", + "@nomicfoundation/ethereumjs-util": "^8.0.0", + "@nomicfoundation/ethereumjs-vm": "^6.0.0", + "@nomicfoundation/solidity-analyzer": "^0.1.0", + "@sentry/node": "^5.18.1", + "@types/bn.js": "^5.1.0", + "@types/lru-cache": "^5.1.0", + "abort-controller": "^3.0.0", + "adm-zip": "^0.4.16", + "aggregate-error": "^3.0.0", + "ansi-escapes": "^4.3.0", + "chalk": "^2.4.2", + "chokidar": "^3.4.0", + "ci-info": "^2.0.0", + "debug": "^4.1.1", + "enquirer": "^2.3.0", + "env-paths": "^2.2.0", + "ethereum-cryptography": "^1.0.3", + "ethereumjs-abi": "^0.6.8", + "find-up": "^2.1.0", + "fp-ts": "1.19.3", + "fs-extra": "^7.0.1", + "glob": "7.2.0", + "immutable": "^4.0.0-rc.12", + "io-ts": "1.10.4", + "keccak": "^3.0.2", + "lodash": "^4.17.11", + "mnemonist": "^0.38.0", + "mocha": "^10.0.0", + "p-map": "^4.0.0", + "qs": "^6.7.0", + "raw-body": "^2.4.1", + "resolve": "1.17.0", + "semver": "^6.3.0", + "solc": "0.7.3", + "source-map-support": "^0.5.13", + "stacktrace-parser": "^0.1.10", + "tsort": "0.0.1", + "undici": "^5.14.0", + "uuid": "^8.3.2", + "ws": "^7.4.6" + }, + "bin": { + "hardhat": "internal/cli/bootstrap.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "ts-node": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/hardhat-deploy": { + "version": "0.11.25", + "resolved": "https://registry.npmjs.org/hardhat-deploy/-/hardhat-deploy-0.11.25.tgz", + "integrity": "sha512-ppSgrVE9A13YgTmf2PQGoyIs9o/jgJOMORrUP/rblU5K8mQ2YHWlPvkzZmP4h+SBW+tNmlnvSrf5K5DmMmExhw==", + "dev": true, + "dependencies": { + "@types/qs": "^6.9.7", + "axios": "^0.21.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.2", + "debug": "^4.3.2", + "enquirer": "^2.3.6", + "ethers": "^5.5.3", + "form-data": "^4.0.0", + "fs-extra": "^10.0.0", + "match-all": "^1.2.6", + "murmur-128": "^0.2.1", + "qs": "^6.9.4", + "zksync-web3": "^0.8.1" + } + }, + "node_modules/hardhat-deploy/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/hardhat-deploy/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/hardhat-deploy/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/hardhat-deploy/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/hardhat-deploy/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hardhat-deploy/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/hardhat-deploy/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hardhat-deploy/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/hardhat-deploy/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/hardhat-deploy/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/hardhat-gas-reporter": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz", + "integrity": "sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==", + "dev": true, + "peer": true, + "dependencies": { + "array-uniq": "1.0.3", + "eth-gas-reporter": "^0.2.25", + "sha1": "^1.1.1" + }, + "peerDependencies": { + "hardhat": "^2.0.2" + } + }, + "node_modules/hardhat/node_modules/ethereum-cryptography": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "dev": true, + "peer": true, + "dependencies": { + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "peer": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "peer": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "peer": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/heap": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", + "dev": true, + "peer": true + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "peer": true + }, + "node_modules/http-basic": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", + "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", + "dev": true, + "peer": true, + "dependencies": { + "caseless": "^0.12.0", + "concat-stream": "^1.6.2", + "http-response-object": "^3.0.1", + "parse-cache-control": "^1.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "peer": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-response-object": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", + "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "^10.0.3" + } + }, + "node_modules/http-response-object/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "dev": true, + "peer": true + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, + "peer": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "peer": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", + "dev": true, + "peer": true, + "dependencies": { + "punycode": "2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/idna-uts46-hx/node_modules/punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", + "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", + "dev": true, + "peer": true + }, + "node_modules/immutable": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", + "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", + "dev": true, + "peer": true + }, + "node_modules/imul": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/imul/-/imul-1.0.1.tgz", + "integrity": "sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "peer": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "peer": true + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "peer": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/io-ts": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", + "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", + "dev": true, + "peer": true, + "dependencies": { + "fp-ts": "^1.0.0" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "peer": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "peer": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "peer": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "peer": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "peer": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "peer": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "peer": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "peer": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true, + "peer": true + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true, + "peer": true + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "peer": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "peer": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true, + "peer": true + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "peer": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true, + "peer": true + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dev": true, + "peer": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, + "peer": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "peer": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "peer": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonschema": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", + "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "peer": true, + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/keccak": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz", + "integrity": "sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==", + "dev": true, + "hasInstallScript": true, + "peer": true, + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", + "dev": true, + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "dev": true, + "peer": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/level": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/level/-/level-8.0.0.tgz", + "integrity": "sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==", + "dev": true, + "peer": true, + "dependencies": { + "browser-level": "^1.0.1", + "classic-level": "^1.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/level" + } + }, + "node_modules/level-codec": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", + "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", + "dev": true, + "peer": true, + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-codec/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/level-concat-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz", + "integrity": "sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", + "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", + "dev": true, + "peer": true, + "dependencies": { + "errno": "~0.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-iterator-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz", + "integrity": "sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.4.0", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-mem": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/level-mem/-/level-mem-5.0.1.tgz", + "integrity": "sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg==", + "dev": true, + "peer": true, + "dependencies": { + "level-packager": "^5.0.3", + "memdown": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-packager": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-5.1.1.tgz", + "integrity": "sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==", + "dev": true, + "peer": true, + "dependencies": { + "encoding-down": "^6.3.0", + "levelup": "^4.3.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/level-supports": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz", + "integrity": "sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/level-transcoder": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz", + "integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer": "^6.0.3", + "module-error": "^1.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/level-ws": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-2.0.0.tgz", + "integrity": "sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^3.1.0", + "xtend": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/levelup": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", + "integrity": "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==", + "dev": true, + "peer": true, + "dependencies": { + "deferred-leveldown": "~5.3.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~4.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/levelup/node_modules/level-supports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", + "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", + "dev": true, + "peer": true, + "dependencies": { + "xtend": "^4.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "peer": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "peer": true + }, + "node_modules/lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw==", + "dev": true, + "peer": true + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "peer": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "peer": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "peer": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "peer": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", + "dev": true, + "peer": true + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "peer": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA==", + "dev": true, + "peer": true + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "peer": true + }, + "node_modules/markdown-table": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", + "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", + "dev": true, + "peer": true + }, + "node_modules/match-all": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/match-all/-/match-all-1.2.6.tgz", + "integrity": "sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==", + "dev": true + }, + "node_modules/mcl-wasm": { + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz", + "integrity": "sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "peer": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/memdown": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-5.1.0.tgz", + "integrity": "sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw==", + "dev": true, + "peer": true, + "dependencies": { + "abstract-leveldown": "~6.2.1", + "functional-red-black-tree": "~1.0.1", + "immediate": "~3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/memdown/node_modules/abstract-leveldown": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", + "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", + "dev": true, + "peer": true, + "dependencies": { + "buffer": "^5.5.0", + "immediate": "^3.2.3", + "level-concat-iterator": "~2.0.0", + "level-supports": "~1.0.0", + "xtend": "~4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/memdown/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/memdown/node_modules/immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg==", + "dev": true, + "peer": true + }, + "node_modules/memdown/node_modules/level-supports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", + "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", + "dev": true, + "peer": true, + "dependencies": { + "xtend": "^4.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/memory-level": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/memory-level/-/memory-level-1.0.0.tgz", + "integrity": "sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==", + "dev": true, + "peer": true, + "dependencies": { + "abstract-level": "^1.0.0", + "functional-red-black-tree": "^1.0.1", + "module-error": "^1.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/merkle-patricia-tree": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-4.2.4.tgz", + "integrity": "sha512-eHbf/BG6eGNsqqfbLED9rIqbsF4+sykEaBn6OLNs71tjclbMcMOk1tEPmJKcNcNCLkvbpY/lwyOlizWsqPNo8w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/levelup": "^4.3.0", + "ethereumjs-util": "^7.1.4", + "level-mem": "^5.0.1", + "level-ws": "^2.0.0", + "readable-stream": "^3.6.0", + "semaphore-async-await": "^1.5.1" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "peer": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mnemonist": { + "version": "0.38.5", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", + "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", + "dev": true, + "peer": true, + "dependencies": { + "obliterator": "^2.0.0" + } + }, + "node_modules/mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "peer": true + }, + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "peer": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/module-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz", + "integrity": "sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/murmur-128": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/murmur-128/-/murmur-128-0.2.1.tgz", + "integrity": "sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==", + "dev": true, + "dependencies": { + "encode-utf8": "^1.0.2", + "fmix": "^0.1.0", + "imul": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true, + "peer": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-macros": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz", + "integrity": "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==", + "dev": true, + "peer": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "peer": true + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true, + "peer": true + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "peer": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "peer": true, + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/node-environment-flags/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "dev": true, + "peer": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", + "dev": true, + "peer": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", + "dev": true, + "peer": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "peer": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/number-to-bn": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", + "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/number-to-bn/node_modules/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", + "dev": true, + "peer": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "peer": true, + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.5.tgz", + "integrity": "sha512-yDNzckpM6ntyQiGTik1fKV1DcVDRS+w8bvpWNCBanvH5LfRX9O8WTHqQzG4RZwRAM4I0oU7TV11Lj5v0g20ibw==", + "dev": true, + "peer": true, + "dependencies": { + "array.prototype.reduce": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obliterator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", + "dev": true, + "peer": true + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "peer": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "peer": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ordinal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz", + "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==", + "dev": true, + "peer": true + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "dev": true, + "peer": true, + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "peer": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "peer": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/parse-cache-control": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", + "dev": true, + "peer": true + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dev": true, + "peer": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "peer": true + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "peer": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "peer": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true, + "peer": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "peer": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", + "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", + "dev": true, + "peer": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "peer": true + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "dev": true, + "peer": true, + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "peer": true + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true, + "peer": true + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", + "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "peer": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "dev": true, + "peer": true, + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "dev": true, + "peer": true, + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "peer": true, + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "peer": true, + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "peer": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "dev": true, + "peer": true, + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/req-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", + "integrity": "sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==", + "dev": true, + "peer": true, + "dependencies": { + "req-from": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/req-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz", + "integrity": "sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==", + "dev": true, + "peer": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "peer": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "dev": true, + "peer": true, + "dependencies": { + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request-promise-native": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", + "deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", + "dev": true, + "peer": true, + "dependencies": { + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.12.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "peer": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true, + "peer": true + }, + "node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "peer": true, + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "peer": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "peer": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "peer": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rlp": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", + "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^5.2.0" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/run-parallel-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", + "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rustbn.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", + "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", + "dev": true, + "peer": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "peer": true + }, + "node_modules/sc-istanbul": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz", + "integrity": "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==", + "dev": true, + "peer": true, + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "istanbul": "lib/cli.js" + } + }, + "node_modules/sc-istanbul/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/sc-istanbul/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "dev": true, + "peer": true + }, + "node_modules/sc-istanbul/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", + "dev": true, + "peer": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sc-istanbul/node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sc-istanbul/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/sc-istanbul/node_modules/js-yaml/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sc-istanbul/node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", + "dev": true, + "peer": true + }, + "node_modules/sc-istanbul/node_modules/supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "dev": true + }, + "node_modules/secp256k1": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", + "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "dev": true, + "hasInstallScript": true, + "peer": true, + "dependencies": { + "elliptic": "^6.5.4", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", + "dev": true, + "peer": true + }, + "node_modules/semaphore-async-await": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz", + "integrity": "sha512-b/ptP11hETwYWpeilHXXQiV5UJNJl7ZWWooKRE5eBIYWoom6dZ0SluCIdCtKycsMtZgKWE01/qAw6jblw1YVhg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.1" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "peer": true + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "peer": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "peer": true + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/sha1": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", + "integrity": "sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==", + "dev": true, + "peer": true, + "dependencies": { + "charenc": ">= 0.0.1", + "crypt": ">= 0.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "peer": true, + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "peer": true + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/solc": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", + "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", + "dev": true, + "peer": true, + "dependencies": { + "command-exists": "^1.2.8", + "commander": "3.0.2", + "follow-redirects": "^1.12.1", + "fs-extra": "^0.30.0", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "require-from-string": "^2.0.0", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solcjs" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/solc/node_modules/fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/solc/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", + "dev": true, + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/solc/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/solidity-coverage": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.2.tgz", + "integrity": "sha512-cv2bWb7lOXPE9/SSleDO6czkFiMHgP4NXPj+iW9W7iEKLBk7Cj0AGBiNmGX3V1totl9wjPrT0gHmABZKZt65rQ==", + "dev": true, + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.0.9", + "@solidity-parser/parser": "^0.14.1", + "chalk": "^2.4.2", + "death": "^1.1.0", + "detect-port": "^1.3.0", + "difflib": "^0.2.4", + "fs-extra": "^8.1.0", + "ghost-testrpc": "^0.0.2", + "global-modules": "^2.0.0", + "globby": "^10.0.1", + "jsonschema": "^1.2.4", + "lodash": "^4.17.15", + "mocha": "7.1.2", + "node-emoji": "^1.10.0", + "pify": "^4.0.1", + "recursive-readdir": "^2.2.2", + "sc-istanbul": "^0.4.5", + "semver": "^7.3.4", + "shelljs": "^0.8.3", + "web3-utils": "^1.3.6" + }, + "bin": { + "solidity-coverage": "plugins/bin.js" + }, + "peerDependencies": { + "hardhat": "^2.11.0" + } + }, + "node_modules/solidity-coverage/node_modules/ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/solidity-coverage/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "peer": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.1" + } + }, + "node_modules/solidity-coverage/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "peer": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/solidity-coverage/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "peer": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/solidity-coverage/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solidity-coverage/node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/solidity-coverage/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true, + "peer": true + }, + "node_modules/solidity-coverage/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, + "peer": true, + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/solidity-coverage/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/solidity-coverage/node_modules/fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "deprecated": "\"Please update to latest v2.3 or v2.2\"", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/solidity-coverage/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/solidity-coverage/node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/solidity-coverage/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "peer": true, + "dependencies": { + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/solidity-coverage/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/solidity-coverage/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/solidity-coverage/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/solidity-coverage/node_modules/mocha": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.2.tgz", + "integrity": "sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.5", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/solidity-coverage/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "peer": true + }, + "node_modules/solidity-coverage/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/solidity-coverage/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "peer": true, + "dependencies": { + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/solidity-coverage/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "peer": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/solidity-coverage/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "peer": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solidity-coverage/node_modules/supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "peer": true + }, + "node_modules/solidity-coverage/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "peer": true + }, + "node_modules/solidity-coverage/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "peer": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/solidity-coverage/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "peer": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/solidity-coverage/node_modules/yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "peer": true, + "dependencies": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "peer": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true, + "peer": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "peer": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true, + "peer": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "peer": true + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "peer": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "peer": true + }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", + "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", + "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", + "dev": true, + "peer": true + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "peer": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "dev": true, + "peer": true, + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", + "dev": true, + "peer": true, + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sync-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", + "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", + "dev": true, + "peer": true, + "dependencies": { + "http-response-object": "^3.0.1", + "sync-rpc": "^1.2.1", + "then-request": "^6.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/sync-rpc": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", + "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", + "dev": true, + "peer": true, + "dependencies": { + "get-port": "^3.1.0" + } + }, + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "peer": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table-layout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", + "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table-layout/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "peer": true + }, + "node_modules/table/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/testrpc": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz", + "integrity": "sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA==", + "deprecated": "testrpc has been renamed to ganache-cli, please use this package from now on.", + "dev": true, + "peer": true + }, + "node_modules/then-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", + "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/concat-stream": "^1.6.0", + "@types/form-data": "0.0.33", + "@types/node": "^8.0.0", + "@types/qs": "^6.2.31", + "caseless": "~0.12.0", + "concat-stream": "^1.6.0", + "form-data": "^2.2.0", + "http-basic": "^8.1.1", + "http-response-object": "^3.0.1", + "promise": "^8.0.0", + "qs": "^6.4.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/then-request/node_modules/@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", + "dev": true, + "peer": true + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "peer": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "peer": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "peer": true + }, + "node_modules/ts-command-line-args": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.4.2.tgz", + "integrity": "sha512-mJLQQBOdyD4XI/ZWQY44PIdYde47JhV2xl380O7twPkTQ+Y5vFDHsk8LOeXKuz7dVY5aDCfAzRarNfSqtKOkQQ==", + "dev": true, + "peer": true, + "dependencies": { + "@morgan-stanley/ts-mocking-bird": "^0.6.2", + "chalk": "^4.1.0", + "command-line-args": "^5.1.1", + "command-line-usage": "^6.1.0", + "string-format": "^2.0.0" + }, + "bin": { + "write-markdown": "dist/write-markdown.js" + } + }, + "node_modules/ts-command-line-args/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-command-line-args/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-command-line-args/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ts-command-line-args/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "peer": true + }, + "node_modules/ts-command-line-args/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-command-line-args/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-essentials": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", + "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "typescript": ">=3.7.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "peer": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "peer": true + }, + "node_modules/tsort": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", + "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", + "dev": true, + "peer": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true, + "peer": true + }, + "node_modules/tweetnacl-util": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", + "dev": true, + "peer": true + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "peer": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typechain": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.1.1.tgz", + "integrity": "sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ==", + "dev": true, + "peer": true, + "dependencies": { + "@types/prettier": "^2.1.1", + "debug": "^4.3.1", + "fs-extra": "^7.0.0", + "glob": "7.1.7", + "js-sha3": "^0.8.0", + "lodash": "^4.17.15", + "mkdirp": "^1.0.4", + "prettier": "^2.3.1", + "ts-command-line-args": "^2.2.0", + "ts-essentials": "^7.0.1" + }, + "bin": { + "typechain": "dist/cli/cli.js" + }, + "peerDependencies": { + "typescript": ">=4.3.0" + } + }, + "node_modules/typechain/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typechain/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true, + "peer": true + }, + "node_modules/typescript": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz", + "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.21.0.tgz", + "integrity": "sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA==", + "dev": true, + "peer": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "peer": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "dev": true, + "peer": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "dev": true, + "peer": true + }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "dev": true, + "peer": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "peer": true + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "peer": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "peer": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "peer": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/web3-utils": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.9.0.tgz", + "integrity": "sha512-p++69rCNNfu2jM9n5+VD/g26l+qkEOQ1m6cfRQCbH8ZRrtquTmrirJMgTmyOoax5a5XRYOuws14aypCOs51pdQ==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^5.2.1", + "ethereum-bloom-filters": "^1.0.6", + "ethereumjs-util": "^7.1.0", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "peer": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "peer": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "peer": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true, + "peer": true + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "peer": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "peer": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw==", + "dev": true, + "peer": true, + "bin": { + "window-size": "cli.js" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "peer": true + }, + "node_modules/wordwrapjs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", + "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", + "dev": true, + "peer": true, + "dependencies": { + "reduce-flatten": "^2.0.0", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true, + "peer": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "peer": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "peer": true + }, + "node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "peer": true + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "peer": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "peer": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zksync-web3": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/zksync-web3/-/zksync-web3-0.8.1.tgz", + "integrity": "sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw==", + "dev": true, + "peerDependencies": { + "ethers": "~5.7.0" + } + } + } +} diff --git a/dex/networks/eth/bondcontracts/v0/package.json b/dex/networks/eth/bondcontracts/v0/package.json new file mode 100644 index 0000000000..42aac4d058 --- /dev/null +++ b/dex/networks/eth/bondcontracts/v0/package.json @@ -0,0 +1,9 @@ +{ + "name": "hardhat-project", + "devDependencies": { + "@nomicfoundation/hardhat-toolbox": "^2.0.2", + "@nomiclabs/hardhat-waffle": "^2.0.5", + "chai": "^4.3.7", + "hardhat-deploy": "^0.11.25" + } +} diff --git a/dex/networks/eth/bondcontracts/v0/test/ETHBondV0.test.ts b/dex/networks/eth/bondcontracts/v0/test/ETHBondV0.test.ts new file mode 100644 index 0000000000..47760a99d4 --- /dev/null +++ b/dex/networks/eth/bondcontracts/v0/test/ETHBondV0.test.ts @@ -0,0 +1,202 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { Contract, Signer } from "ethers"; + +describe("ETHBond", () => { + let ethBond: Contract; + let owner: Signer; + let addr1: Signer; + let addr2: Signer; + + const accountID = ethers.utils.id("account1"); + const bondID1 = ethers.utils.id("bond1"); + const bondID2 = ethers.utils.id("bond2"); + const bondID3 = ethers.utils.id("bond3"); + const bondID4 = ethers.utils.id("bond4"); + const bondID5 = ethers.utils.id("bond5"); + + + beforeEach(async () => { + const EthBondFactory = await ethers.getContractFactory("ETHBond"); + [owner, addr1, addr2] = await ethers.getSigners(); + ethBond = await EthBondFactory.deploy(); + }); + + it("should create a bond", async () => { + await ethBond.connect(addr1).createBond(accountID, bondID1, 1000, { value: ethers.utils.parseEther("1") }); + const bond = await ethBond.bondData(accountID, bondID1); + const bondIDs = (await ethBond.bondsForAccount(accountID)).map((bondData: any) => bondData[0]); + + expect(bond.value.toString()).to.equal(ethers.utils.parseEther("1").toString()); + expect(bond.locktime).to.equal(1000); + expect(bond.owner).to.equal(await addr1.getAddress()); + expect(bondIDs).to.deep.equal([bondID1]); + }); + + it("should extend the locktime of a bond without changing the amount", async () => { + const bondID2 = ethers.utils.hexlify(ethers.utils.randomBytes(32)); + + await ethBond.connect(addr1).createBond(accountID, bondID1, 1000, { value: ethers.utils.parseEther("1") }); + const newLocktime = 2000; + + await ethBond.connect(addr1).updateBonds(accountID, [bondID1], [bondID2], ethers.utils.parseEther("1"), newLocktime); + + const bond1AfterUpdate = await ethBond.bondData(accountID, bondID1); + const bond2 = await ethBond.bondData(accountID, bondID2); + const bondIDs = (await ethBond.bondsForAccount(accountID)).map((bondData: any) => bondData[0]); + + expect(bond1AfterUpdate.value.toString()).to.equal("0"); + expect(bond2.value.toString()).to.equal(ethers.utils.parseEther("1").toString()); + expect(bond2.locktime.toString()).to.equal(newLocktime.toString()); + expect(bondIDs).to.deep.equal([bondID2]); + }); + + it("should extend the locktime and decrease the amount of a bond, resulting in two new bonds", async () => { + await ethBond.connect(addr1).createBond(accountID, bondID1, 1000, { value: ethers.utils.parseEther("1") }); + const newLocktime = 2000; + + await ethBond.connect(addr1).updateBonds(accountID, [bondID1], [bondID2, bondID3], ethers.utils.parseEther("0.5"), newLocktime); + + const bond1AfterUpdate = await ethBond.bondData(accountID, bondID1); + const bond2 = await ethBond.bondData(accountID, bondID2); + const bond3 = await ethBond.bondData(accountID, bondID3); + const bondIDs = (await ethBond.bondsForAccount(accountID)).map((bondData: any) => bondData[0]); + + + expect(bond1AfterUpdate.value.toString()).to.equal("0"); + expect(bond2.value.toString()).to.equal(ethers.utils.parseEther("0.5").toString()); + expect(bond2.locktime.toString()).to.equal("1000"); + expect(bond3.value.toString()).to.equal(ethers.utils.parseEther("0.5").toString()); + expect(bond3.locktime.toString()).to.equal(newLocktime.toString()); + expect(bondIDs).to.deep.equal([bondID3, bondID2]); + }); + + it("should update three bonds to output two bonds, one with 0.05 ETH and one with 0.25 ETH", async () => { + const amount = ethers.utils.parseEther("0.1"); + const newLocktime = 2000; + + await ethBond.connect(addr1).createBond(accountID, bondID1, 1000, { value: amount }); + await ethBond.connect(addr1).createBond(accountID, bondID2, 1100, { value: amount }); + await ethBond.connect(addr1).createBond(accountID, bondID3, 1200, { value: amount }); + + await ethBond.connect(addr1).updateBonds(accountID, [bondID1, bondID2, bondID3], [bondID4, bondID5], ethers.utils.parseEther("0.25"), newLocktime); + + const bond1AfterUpdate = await ethBond.bondData(accountID, bondID1); + const bond2AfterUpdate = await ethBond.bondData(accountID, bondID2); + const bond3AfterUpdate = await ethBond.bondData(accountID, bondID3); + const bond4 = await ethBond.bondData(accountID, bondID4); + const bond5 = await ethBond.bondData(accountID, bondID5); + const bondIDs = (await ethBond.bondsForAccount(accountID)).map((bondData: any) => bondData[0]); + + + expect(bond1AfterUpdate.value.toString()).to.equal("0"); + expect(bond2AfterUpdate.value.toString()).to.equal("0"); + expect(bond3AfterUpdate.value.toString()).to.equal("0"); + expect(bond4.value.toString()).to.equal(ethers.utils.parseEther("0.05").toString()); + expect(bond4.locktime.toString()).to.equal("1000"); + expect(bond5.value.toString()).to.equal(ethers.utils.parseEther("0.25").toString()); + expect(bond5.locktime.toString()).to.equal(newLocktime.toString()); + expect(bondIDs).to.deep.equal([bondID5, bondID4]); + }); + + it("should update three bonds to have an amount of 0.4 ETH", async () => { + const amount = ethers.utils.parseEther("0.1"); + const newLocktime = 2000; + + await ethBond.connect(addr1).createBond(accountID, bondID1, 1000, { value: amount }); + await ethBond.connect(addr1).createBond(accountID, bondID2, 1100, { value: amount }); + await ethBond.connect(addr1).createBond(accountID, bondID3, 1200, { value: amount }); + + await ethBond.connect(addr1).updateBonds(accountID, [bondID1, bondID2, bondID3], [bondID4], ethers.utils.parseEther("0.4"), newLocktime, { value: amount }); + + const bond1AfterUpdate = await ethBond.bondData(accountID, bondID1); + const bond2AfterUpdate = await ethBond.bondData(accountID, bondID2); + const bond3AfterUpdate = await ethBond.bondData(accountID, bondID3); + const bond4 = await ethBond.bondData(accountID, bondID4); + const bondIDs = (await ethBond.bondsForAccount(accountID)).map((bondData: any) => bondData[0]); + + + expect(bond1AfterUpdate.value.toString()).to.equal("0"); + expect(bond2AfterUpdate.value.toString()).to.equal("0"); + expect(bond3AfterUpdate.value.toString()).to.equal("0"); + expect(bond4.value.toString()).to.equal(ethers.utils.parseEther("0.4").toString()); + expect(bond4.locktime.toString()).to.equal(newLocktime.toString()); + expect(bondIDs).to.deep.equal([bondID4]); + }); + + it("should fail if the new bond ID already exists", async () => { + const amount = ethers.utils.parseEther("0.1"); + const newLocktime = 2000; + + await ethBond.connect(addr1).createBond(accountID, bondID1, 1000, { value: amount }); + await ethBond.connect(addr1).createBond(accountID, bondID2, 1000, { value: amount }); + + await expect(ethBond.connect(addr1).updateBonds(accountID, [bondID1, bondID2], [bondID2], ethers.utils.parseEther("0.2"), newLocktime)).to.be.revertedWith("new bond already exists"); + }); + + it("should fail if the updated locktime is less than the latest bond's locktime", async () => { + const amount = ethers.utils.parseEther("0.1"); + const locktime = 1000; + + await ethBond.connect(addr1).createBond(accountID, bondID1, locktime, { value: amount }); + await ethBond.connect(addr1).createBond(accountID, bondID2, locktime + 100, { value: amount }); + + await expect(ethBond.connect(addr1).updateBonds(accountID, [bondID1, bondID2], [bondID3], ethers.utils.parseEther("0.2"), locktime)).to.be.revertedWith("locktime cannot decrease"); + }); + + it("should fail if the bonds are not sorted by locktime", async () => { + const amount = ethers.utils.parseEther("0.1"); + const locktime = 1000; + + await ethBond.connect(addr1).createBond(accountID, bondID1, locktime, { value: amount }); + await ethBond.connect(addr1).createBond(accountID, bondID2, locktime - 100, { value: amount }); + + await expect(ethBond.connect(addr1).updateBonds(accountID, [bondID1, bondID2], [bondID3], ethers.utils.parseEther("0.2"), locktime + 1000)).to.be.revertedWith("bonds must be sorted by locktime"); + }); + + it("should fail if the bond owner is not the same as the msg.sender", async () => { + const bondID2 = ethers.utils.hexlify(ethers.utils.randomBytes(32)); + const newBondID = ethers.utils.hexlify(ethers.utils.randomBytes(32)); + + const amount = ethers.utils.parseEther("0.1"); + const locktime = 1000; + + await ethBond.connect(addr1).createBond(accountID, bondID1, locktime, { value: amount }); + await ethBond.connect(addr2).createBond(accountID, bondID2, locktime, { value: amount }); + + await expect(ethBond.connect(addr1).updateBonds(accountID, [bondID1, bondID2], [newBondID], ethers.utils.parseEther("0.2"), locktime + 1000)).to.be.revertedWith("bond owner != msg.sender"); + }); + + it("should fail if the funds sent with the update call are incorrect", async () => { + const amount = ethers.utils.parseEther("0.1"); + const locktime = 1000; + + await ethBond.connect(addr1).createBond(accountID, bondID1, locktime, { value: amount }); + await ethBond.connect(addr1).createBond(accountID, bondID2, locktime, { value: amount }); + + await expect(ethBond.connect(addr1).updateBonds(accountID, [bondID1, bondID2], [bondID3], ethers.utils.parseEther("0.3"), locktime + 1000, { value: ethers.utils.parseEther("0.05") })).to.be.revertedWith("insufficient funds"); + }); + + it("should refund a bond", async () => { + await ethBond.connect(addr1).createBond(accountID, bondID1, 1000, { value: ethers.utils.parseEther("1") }); + + const bond1 = await ethBond.bondData(accountID, bondID1); + await ethers.provider.send("evm_increaseTime", [bond1.locktime.toNumber()]); + await ethers.provider.send("evm_mine"); + + const balanceBefore = await addr1.getBalance(); + + const refundTx = await ethBond.connect(addr1).refundBond(accountID, bondID1); + const refundReceipt = await refundTx.wait(); + + const gasPrice = refundReceipt.gasUsed * refundReceipt.effectiveGasPrice; + + const bond1AfterRefund = await ethBond.bondData(accountID, bondID1); + const balanceAfter = await addr1.getBalance(); + const bondIDs = (await ethBond.bondsForAccount(accountID)).map((bondData: any) => bondData[0]); + + expect(bond1AfterRefund.value.toString()).to.equal("0"); + expect(balanceAfter.sub(balanceBefore).add(gasPrice).toString()).to.equal(ethers.utils.parseEther("1").toString()); + expect(bondIDs).to.deep.equal([]); + }); +}); diff --git a/dex/networks/eth/bondcontracts/v0/tsconfig.json b/dex/networks/eth/bondcontracts/v0/tsconfig.json new file mode 100644 index 0000000000..5bf6feef0d --- /dev/null +++ b/dex/networks/eth/bondcontracts/v0/tsconfig.json @@ -0,0 +1,36 @@ +{ + "compilerOptions": { + "target": "ES2018", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "forceConsistentCasingInFileNames": true, + "composite": true, + "skipLibCheck": true, + "typeRoots": ["node_modules/@types", "node_modules", "types"], + "types": ["mocha", "node", "hardhat-deploy"], + "lib": ["ES2018", "DOM"], + "baseUrl": ".", + "paths": { + "@app/*": ["./app/*"], + "@test/*": ["./test/*"], + "@types/*": ["./types/*"] + } + }, + "include": ["./test/**/*.ts", "./app/**/*.ts", "./types/**/*.ts"], + "exclude": ["node_modules", "coverage"], + "references": [ + { + "path": "./app" + }, + { + "path": "./test" + }, + { + "path": "./types" + } + ] + } + \ No newline at end of file diff --git a/dex/testing/dcrdex/genmarkets.sh b/dex/testing/dcrdex/genmarkets.sh index 7a32b9433e..5541d313db 100755 --- a/dex/testing/dcrdex/genmarkets.sh +++ b/dex/testing/dcrdex/genmarkets.sh @@ -334,7 +334,9 @@ cat << EOF >> "${FILEPATH}" "network": "simnet", "maxFeeRate": 200, "swapConf": 2, - "configPath": "$ETH_CONFIG_PATH" + "configPath": "$ETH_CONFIG_PATH", + "bondAmt": 1000000000, + "bondConfs": 1 }, "DEXTT_simnet": { "bip44symbol": "dextt.eth", diff --git a/dex/testing/eth/harness.sh b/dex/testing/eth/harness.sh index c4ff6eb141..dff04c2a13 100755 --- a/dex/testing/eth/harness.sh +++ b/dex/testing/eth/harness.sh @@ -44,6 +44,7 @@ ETH_SWAP_V0="608060405234801561001057600080fd5b50610b7a806100206000396000f3fe608 ERC20_SWAP_V0="60a060405234801561001057600080fd5b50604051610e92380380610e9283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051610df361009f6000396000818160c50152818161029b0152818161066b01526109f30152610df36000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063a8793f941161005b578063a8793f94146100ff578063d0f761c014610112578063eb84e7f214610135578063f4fd17f9146101a457600080fd5b80637249fbb61461008257806376467cbd146100975780638c8e8fee146100c0575b600080fd5b610095610090366004610ac8565b6101b7565b005b6100aa6100a5366004610ac8565b610376565b6040516100b79190610b19565b60405180910390f35b6100e77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100b7565b61009561010d366004610b7e565b610451565b610125610120366004610ac8565b61074c565b60405190151581526020016100b7565b610191610143366004610ac8565b60006020819052908152604090208054600182015460028301546003840154600485015460059095015493949293919290916001600160a01b0391821691811690600160a01b900460ff1687565b6040516100b79796959493929190610bf3565b6100956101b2366004610c3f565b6107ac565b3233146101df5760405162461bcd60e51b81526004016101d690610ca2565b60405180910390fd5b6101e88161074c565b6102255760405162461bcd60e51b815260206004820152600e60248201526d6e6f7420726566756e6461626c6560901b60448201526064016101d6565b60008181526020818152604080832060058101805460ff60a01b1916600360a01b17905560018101548251336024820152604480820192909252835180820390920182526064018352928301805163a9059cbb60e01b6001600160e01b0390911617905290519092916060916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916102c591610ccc565b6000604051808303816000865af19150503d8060008114610302576040519150601f19603f3d011682016040523d82523d6000602084013e610307565b606091505b5090925090508180156103325750805115806103325750808060200190518101906103329190610cfb565b6103705760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b60448201526064016101d6565b50505050565b6103b36040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a081018290529060c082015290565b60008281526020818152604091829020825160e08101845281548152600182015492810192909252600281015492820192909252600380830154606083015260048301546001600160a01b039081166080840152600584015490811660a084015291929160c0840191600160a01b90910460ff169081111561043757610437610ae1565b600381111561044857610448610ae1565b90525092915050565b3233146104705760405162461bcd60e51b81526004016101d690610ca2565b6000805b82811015610615573684848381811061048f5761048f610d1d565b9050608002019050600080600083602001358152602001908152602001600020905060008260600135116104ed5760405162461bcd60e51b81526020600482015260056024820152640c081d985b60da1b60448201526064016101d6565b813561052f5760405162461bcd60e51b815260206004820152601160248201527003020726566756e6454696d657374616d7607c1b60448201526064016101d6565b60006005820154600160a01b900460ff16600381111561055157610551610ae1565b146105905760405162461bcd60e51b815260206004820152600f60248201526e0c8eae040e6cac6e4cae840d0c2e6d608b1b60448201526064016101d6565b436002820155813560038201556004810180546001600160a01b031916331790556105c16060830160408401610d33565b6005820180546060850135600185018190556001600160a01b03939093166001600160a81b031990911617600160a01b1790556105fe9085610d72565b93505050808061060d90610d8b565b915050610474565b5060408051336024820152306044820152606480820184905282518083039091018152608490910182526020810180516001600160e01b03166323b872dd60e01b17905290516000916060916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169161069591610ccc565b6000604051808303816000865af19150503d80600081146106d2576040519150601f19603f3d011682016040523d82523d6000602084013e6106d7565b606091505b5090925090508180156107025750805115806107025750808060200190518101906107029190610cfb565b6107455760405162461bcd60e51b81526020600482015260146024820152731d1c985b9cd9995c88199c9bdb4819985a5b195960621b60448201526064016101d6565b5050505050565b600081815260208190526040812060016005820154600160a01b900460ff16600381111561077c5761077c610ae1565b148015610795575060048101546001600160a01b031633145b80156107a5575080600301544210155b9392505050565b3233146107cb5760405162461bcd60e51b81526004016101d690610ca2565b6000805b828110156109a357368484838181106107ea576107ea610d1d565b6020604091820293909301838101356000908152938490529220919250600190506005820154600160a01b900460ff16600381111561082b5761082b610ae1565b146108645760405162461bcd60e51b815260206004820152600960248201526862616420737461746560b81b60448201526064016101d6565b60058101546001600160a01b031633146108b25760405162461bcd60e51b815260206004820152600f60248201526e189859081c185c9d1a58da5c185b9d608a1b60448201526064016101d6565b8160200135600283600001356040516020016108d091815260200190565b60408051601f19818403018152908290526108ea91610ccc565b602060405180830381855afa158015610907573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061092a9190610da4565b146109645760405162461bcd60e51b815260206004820152600a602482015269189859081cd958dc995d60b21b60448201526064016101d6565b60058101805460ff60a01b1916600160a11b17905581358155600181015461098c9085610d72565b93505050808061099b90610d8b565b9150506107cf565b5060408051336024820152604480820184905282518083039091018152606490910182526020810180516001600160e01b031663a9059cbb60e01b17905290516000916060916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691610a1d91610ccc565b6000604051808303816000865af19150503d8060008114610a5a576040519150601f19603f3d011682016040523d82523d6000602084013e610a5f565b606091505b509092509050818015610a8a575080511580610a8a575080806020019051810190610a8a9190610cfb565b6107455760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b60448201526064016101d6565b600060208284031215610ada57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60048110610b1557634e487b7160e01b600052602160045260246000fd5b9052565b600060e08201905082518252602083015160208301526040830151604083015260608301516060830152608083015160018060a01b0380821660808501528060a08601511660a0850152505060c0830151610b7760c0840182610af7565b5092915050565b60008060208385031215610b9157600080fd5b823567ffffffffffffffff80821115610ba957600080fd5b818501915085601f830112610bbd57600080fd5b813581811115610bcc57600080fd5b8660208260071b8501011115610be157600080fd5b60209290920196919550909350505050565b8781526020810187905260408101869052606081018590526001600160a01b038481166080830152831660a082015260e08101610c3360c0830184610af7565b98975050505050505050565b60008060208385031215610c5257600080fd5b823567ffffffffffffffff80821115610c6a57600080fd5b818501915085601f830112610c7e57600080fd5b813581811115610c8d57600080fd5b8660208260061b8501011115610be157600080fd5b60208082526010908201526f39b2b73232b910109e9037b934b3b4b760811b604082015260600190565b6000825160005b81811015610ced5760208186018101518583015201610cd3565b506000920191825250919050565b600060208284031215610d0d57600080fd5b815180151581146107a557600080fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215610d4557600080fd5b81356001600160a01b03811681146107a557600080fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610d8557610d85610d5c565b92915050565b600060018201610d9d57610d9d610d5c565b5060010190565b600060208284031215610db657600080fd5b505191905056fea2646970667358221220a055a4890a5ecf3876dbee91dfbeb46ba11b5f7c09b6d935173932d93f8fb92264736f6c63430008120033" TEST_TOKEN="608060405234801561001057600080fd5b506040805180820190915260098152682a32b9ba2a37b5b2b760b91b602082015260039061003e90826101ad565b506040805180820190915260038152621514d560ea1b602082015260049061006690826101ad565b506909513ea9de0243800000600255600060208190526902544faa778090e000007f7d4921c2bc32c0110a31d16f4efb43c7a1228f1df7af765f608241dee5c62ebc8190557f59603491850c7d11499afe95b334ccfd92b48b36a15df31ef59ff5813fe3708281905573d12ab7cf72ccf1f3882ec99ddc53cd415635c3be9091527f5bd8dfce2dbb581d0922a094c40bab2f7d2f0ea9aaf275bf0fcc0f027a2ff91d5561026c565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061013857607f821691505b60208210810361015857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156101a857600081815260208120601f850160051c810160208610156101855750805b601f850160051c820191505b818110156101a457828155600101610191565b5050505b505050565b81516001600160401b038111156101c6576101c661010e565b6101da816101d48454610124565b8461015e565b602080601f83116001811461020f57600084156101f75750858301515b600019600386901b1c1916600185901b1785556101a4565b600085815260208120601f198616915b8281101561023e5788860151825594840194600190910190840161021f565b508582101561025c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6107c08061027b6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c806370a082311161007157806370a08231146101235780638ba4cc3c1461014c57806395d89b4114610161578063a9059cbb14610169578063ce714b511461017c578063dd62ed3e1461018f57600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610101578063313ce56714610114575b600080fd5b6100b66101c8565b6040516100c3919061060a565b60405180910390f35b6100df6100da366004610674565b61025a565b60405190151581526020016100c3565b6002545b6040519081526020016100c3565b6100df61010f36600461069e565b610271565b604051601281526020016100c3565b6100f36101313660046106da565b6001600160a01b031660009081526020819052604090205490565b61015f61015a366004610674565b610320565b005b6100b6610368565b6100df610177366004610674565b610377565b6100df61018a36600461069e565b610384565b6100f361019d3660046106fc565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600380546101d79061072f565b80601f01602080910402602001604051908101604052809291908181526020018280546102039061072f565b80156102505780601f1061022557610100808354040283529160200191610250565b820191906000526020600020905b81548152906001019060200180831161023357829003601f168201915b5050505050905090565b600061026733848461039b565b5060015b92915050565b600061027e84848461048a565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156103085760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b610315853385840361039b565b506001949350505050565b80600260008282546103329190610769565b90915550506001600160a01b0382166000908152602081905260408120805483929061035f908490610769565b90915550505050565b6060600480546101d79061072f565b600061026733848461048a565b600061039184848461039b565b5060019392505050565b6001600160a01b0383166103fd5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016102ff565b6001600160a01b03821661045e5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016102ff565b6001600160a01b0392831660009081526001602090815260408083209490951682529290925291902055565b6001600160a01b0383166104ee5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016102ff565b6001600160a01b0382166105505760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016102ff565b6001600160a01b038316600090815260208190526040902054818110156105c85760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016102ff565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906105ff908490610769565b909155505050505050565b600060208083528351808285015260005b818110156106375785810183015185820160400152820161061b565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461066f57600080fd5b919050565b6000806040838503121561068757600080fd5b61069083610658565b946020939093013593505050565b6000806000606084860312156106b357600080fd5b6106bc84610658565b92506106ca60208501610658565b9150604084013590509250925092565b6000602082840312156106ec57600080fd5b6106f582610658565b9392505050565b6000806040838503121561070f57600080fd5b61071883610658565b915061072660208401610658565b90509250929050565b600181811c9082168061074357607f821691505b60208210810361076357634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561026b57634e487b7160e01b600052601160045260246000fdfea2646970667358221220e48184f15ae575a1ab3966580821ddaff3654cd0137084d70ceeeb4d906b3c5364736f6c63430008120033" MULTIBALANCE_BIN="608060405234801561001057600080fd5b50610483806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063d3e5ca8714610030575b600080fd5b61004361003e3660046102a5565b610059565b604051610050919061032b565b60405180910390f35b60606000610068836001610385565b67ffffffffffffffff8111156100805761008061039e565b6040519080825280602002602001820160405280156100a9578160200160208202803683370190505b509050846001600160a01b031631816000815181106100ca576100ca6103b4565b60200260200101818152505060005b838110156102805760008585838181106100f5576100f56103b4565b905060200201602081019061010a91906103ca565b905060006060826001600160a01b03167f70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be8a60405160240161015b91906001600160a01b0391909116815260200190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161019991906103ec565b600060405180830381855afa9150503d80600081146101d4576040519150601f19603f3d011682016040523d82523d6000602084013e6101d9565b606091505b509092509050816102285760405162461bcd60e51b815260206004820152601560248201527418985b185b98d953d98818d85b1b0819985a5b1959605a1b604482015260640160405180910390fd5b60008180602001905181019061023e919061041b565b9050808661024d876001610385565b8151811061025d5761025d6103b4565b60200260200101818152505050505050808061027890610434565b9150506100d9565b50949350505050565b80356001600160a01b03811681146102a057600080fd5b919050565b6000806000604084860312156102ba57600080fd5b6102c384610289565b9250602084013567ffffffffffffffff808211156102e057600080fd5b818601915086601f8301126102f457600080fd5b81358181111561030357600080fd5b8760208260051b850101111561031857600080fd5b6020830194508093505050509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561036357835183529284019291840191600101610347565b50909695505050505050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103985761039861036f565b92915050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000602082840312156103dc57600080fd5b6103e582610289565b9392505050565b6000825160005b8181101561040d57602081860181015185830152016103f3565b506000920191825250919050565b60006020828403121561042d57600080fd5b5051919050565b6000600182016104465761044661036f565b506001019056fea26469706673582212207074e3e189a2692e2841f7943a9de24bcdbca943ee6bfcbd83a2fa6e43ec497b64736f6c63430008120033" +BOND_V0="608060405234801561001057600080fd5b5061122b806100206000396000f3fe6080604052600436106100705760003560e01c8063c9db44541161004e578063c9db4454146100ec578063dacebc9c146100ff578063de2ec9231461019e578063ef6bb2d3146101cd57600080fd5b80632d27ff401461007557806374e3a3c6146100aa578063c0f5fa70146100bf575b600080fd5b34801561008157600080fd5b50610095610090366004610dc5565b6101ed565b60405190151581526020015b60405180910390f35b6100bd6100b8366004610e4e565b610231565b005b3480156100cb57600080fd5b506100df6100da366004610ee0565b6103ef565b6040516100a19190610ef9565b6100bd6100fa366004610f79565b610559565b34801561010b57600080fd5b5061016661011a366004610dc5565b6000918252602082815260408084209284526001928301909152909120805491810154600290910154919290916001600160401b03811691600160401b9091046001600160a01b031690565b6040516100a1949392919093845260208401929092526001600160401b031660408301526001600160a01b0316606082015260800190565b3480156101aa57600080fd5b506101be6101b9366004610fc4565b610630565b6040516100a19392919061111c565b3480156101d957600080fd5b506100bd6101e8366004610dc5565b61090b565b60008281526020818152604080832084845260018101909252822080541580159061022657506002810154426001600160401b03909116105b925050505b92915050565b3233146102595760405162461bcd60e51b815260040161025090611146565b60405180910390fd5b60008060006102a28a8a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c92508b91508a90508934610630565b9250925092508281906102c85760405162461bcd60e51b81526004016102509190611170565b5060008a81526020819052604090208583111561037d5760008160010160008c8c60008181106102fa576102fa61118a565b9050602002013581526020019081526020016000209050610352828a8a60008181106103285761032861118a565b600286015460209091029290920135916001600160401b0316905061034d8b896111b6565b610a5a565b610377828a8a60018181106103695761036961118a565b90506020020135888a610a5a565b506103a2565b6103a281898960008181106103945761039461118a565b905060200201358789610a5a565b60005b898110156103e1576103cf828c8c848181106103c3576103c361118a565b90506020020135610ad1565b806103d9816111c9565b9150506103a5565b505050505050505050505050565b60008181526020819052604081208054606092905b80156104335781610414816111c9565b6000928352600185016020526040909220600401549192506104049050565b6000826001600160401b0381111561044d5761044d610fae565b6040519080825280602002602001820160405280156104a657816020015b6040805160a08101825260008082526020808301829052928201819052606082018190526080820152825260001990920191018161046b5790505b5084549250905060005b8381101561054f57600083815260018681016020908152604092839020835160a081018552878152815492810192909252918201549281019290925260028101546001600160401b0381166060840152600160401b90046001600160a01b03166080830152835190919084908490811061052c5761052c61118a565b602090810291909101015260040154925080610547816111c9565b9150506104b0565b5095945050505050565b3233146105785760405162461bcd60e51b815260040161025090611146565b600083815260208181526040808320858452600181019092529091208054156105d95760405162461bcd60e51b8152602060048201526013602482015272626f6e6420616c72656164792065786973747360681b6044820152606401610250565b6000341161061d5760405162461bcd60e51b8152602060048201526011602482015270076616c7565206d757374206265203e203607c1b6044820152606401610250565b61062982858534610a5a565b5050505050565b60008781526020819052604081208190606090600101828080610654848e8b610b7d565b9250925092508261067a57600096506001600160401b038916955093506108fe92505050565b898211156107a95760008460008f60008151811061069a5761069a61118a565b6020026020010151815260200190815260200160002090508a836106be91906111b6565b8154101561070f576000836040518060400160405280601a81526020017f6561726c6965737420626f6e6420697320746f6f20736d616c6c00000000000081525097509750975050505050506108fe565b60028c14610760576000836040518060400160405280601d81526020017f696e636f7272656374206e756d626572206f66206e657720626f6e647300000081525097509750975050505050506108fe565b88156107a357600083604051806040016040528060118152602001701b9bc8199d5b991cc81c995c5d5a5c9959607a1b81525097509750975050505050506108fe565b50610846565b60018b146107f9576000826040518060400160405280601d81526020017f696e636f7272656374206e756d626572206f66206e657720626f6e6473000000815250965096509650505050506108fe565b89610804838a6111e2565b146108465760008260405180604001604052806012815260200171696e73756666696369656e742066756e647360701b815250965096509650505050506108fe565b60005b8b8110156108e1578460008e8e848181106108665761086661118a565b905060200201358152602001908152602001600020600001546000146108cf576000836040518060400160405280601781526020017f6e657720626f6e6420616c72656164792065786973747300000000000000000081525097509750975050505050506108fe565b806108d9816111c9565b915050610849565b505060408051602081019091526000815260019650909450925050505b9750975097945050505050565b32331461092a5760405162461bcd60e51b815260040161025090611146565b61093482826101ed565b6109795760405162461bcd60e51b8152602060048201526016602482015275626f6e64206973206e6f7420726566756e6461626c6560501b6044820152606401610250565b6000828152602081815260408083208484526001810190925290912080546002820154600160401b90046001600160a01b03166109b68486610ad1565b6000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610a03576040519150601f19603f3d011682016040523d82523d6000602084013e610a08565b606091505b5090915050600181151514610a515760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606401610250565b50505050505050565b6000838152600180860160205260409091208281554391810191909155600281018054600160401b33026001600160e01b03199091166001600160401b038616171790558454610aac57838555610629565b8454600081815260018701602052604090206004929092015560030183905550509055565b60008181526001830160205260409020600381015415610b0f5760048082015460038301546000908152600186016020526040902090910155610b17565b600481015483555b600481015415610b4157600380820154600483015460009081526001860160205260409020909101555b5060009081526001918201602052604081208181559182018190556002820180546001600160e01b031916905560038201819055600490910155565b600080606060008060005b8751811015610d01576000888281518110610ba557610ba561118a565b6020908102919091018101516000818152918c90526040822080549193509103610c085760008060405180604001604052806013815260200172189bdb9908191bd95cc81b9bdd08195e1a5cdd606a1b8152509750975097505050505050610dbc565b6002810154600160401b90046001600160a01b03163314610c6c576000806040518060400160405280601881526020017f626f6e64206f776e657220213d206d73672e73656e64657200000000000000008152509750975097505050505050610dbc565b60028101546001600160401b0380861691161015610ccd576000806040518060400160405280602081526020017f626f6e6473206d75737420626520736f72746564206279206c6f636b74696d658152509750975097505050505050610dbc565b8054610cd990866111e2565b6002909101549094506001600160401b03169250819050610cf9816111c9565b915050610b88565b5060008860008960018b51610d1691906111b6565b81518110610d2657610d2661118a565b602090810291909101810151825281019190915260400160002060028101549091506001600160401b03808916911610610da1576000806040518060400160405280601881526020017f6c6f636b74696d652063616e6e6f742064656372656173650000000000000000815250955095509550505050610dbc565b50506040805160208101909152600081526001945090925090505b93509350939050565b60008060408385031215610dd857600080fd5b50508035926020909101359150565b60008083601f840112610df957600080fd5b5081356001600160401b03811115610e1057600080fd5b6020830191508360208260051b8501011115610e2b57600080fd5b9250929050565b80356001600160401b0381168114610e4957600080fd5b919050565b600080600080600080600060a0888a031215610e6957600080fd5b8735965060208801356001600160401b0380821115610e8757600080fd5b610e938b838c01610de7565b909850965060408a0135915080821115610eac57600080fd5b50610eb98a828b01610de7565b90955093505060608801359150610ed260808901610e32565b905092959891949750929550565b600060208284031215610ef257600080fd5b5035919050565b602080825282518282018190526000919060409081850190868401855b82811015610f6c57815180518552868101518786015285810151868601526060808201516001600160401b0316908601526080908101516001600160a01b03169085015260a09093019290850190600101610f16565b5091979650505050505050565b600080600060608486031215610f8e57600080fd5b8335925060208401359150610fa560408501610e32565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b600080600080600080600060c0888a031215610fdf57600080fd5b873596506020808901356001600160401b0380821115610ffe57600080fd5b818b0191508b601f83011261101257600080fd5b81358181111561102457611024610fae565b8060051b604051601f19603f8301168101818110858211171561104957611049610fae565b6040529182528381018501918581018f84111561106557600080fd5b948601945b83861015611081578535815294860194860161106a565b509a50505060408b013592508083111561109a57600080fd5b50506110a88a828b01610de7565b909650945050606088013592506110c160808901610e32565b915060a0880135905092959891949750929550565b6000815180845260005b818110156110fc576020818501810151868301820152016110e0565b506000602082860101526020601f19601f83011685010191505092915050565b831515815282602082015260606040820152600061113d60608301846110d6565b95945050505050565b60208082526010908201526f39b2b73232b910109e9037b934b3b4b760811b604082015260600190565b60208152600061118360208301846110d6565b9392505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561022b5761022b6111a0565b6000600182016111db576111db6111a0565b5060010190565b8082018082111561022b5761022b6111a056fea26469706673582212209c57193479fbab98e7760f243c3e4b80a224d78b77e183459698ea178e47cef364736f6c63430008120033" # PASSWORD is the password used to unlock all accounts/wallets/addresses. PASSWORD="abc" @@ -102,6 +103,9 @@ cat > "${NODES_ROOT}/genesis.json" < "${NODES_ROOT}/test_token_contract_address.txt" < "${NODES_ROOT}/eth_bond_contract_address.txt" < "${NODES_ROOT}/harness-ctl/loadTestToken.js" < "${NODES_ROOT}/harness-ctl/loadBondContract.js" < { + if (el.stateMutability === "view") { + // the constant field was deprecated and the output from solc no + // longer contains it, but the geth console version of web3 still + // seems to require it. + el.constant = true; + } + }) + var contract = web3.eth.contract(bondABI) + var bondContract = contract.at('${ETH_BOND_CONTRACT_ADDR}') + web3.eth.defaultAccount = web3.eth.accounts.length > 1 ? web3.eth.accounts[1] : web3.eth.accounts[0] + personal.unlockAccount(web3.eth.defaultAccount, '${PASSWORD}') +EOF + +cat > "${NODES_ROOT}/harness-ctl/alphaWithBonds.sh" < Date: Wed, 7 Feb 2024 11:57:51 -0500 Subject: [PATCH 2/6] client/asset/eth: Add BondUpdater interface and implement it in ETH Client Adds a BondUpdater interface which contains a single method, `UpdateBondsTx`. Similar to MakeBondTx, this generates an unsigned transaction, but instead of creating a new bond from scratch, it uses the funds locked in existing bonds to create a new bond. For ETH, it is not possible to create a signed transaction that will be submitted later because if the nonce is used before the transaction is submitted, the transaction will no longer be valid. Therefore, for ETH, the SignedTx and UnsignedTx in the `asset.Bond` returned from `MakeBondTx` and `UpdateBondsTx` contain the same data. The ETH wallet backend populates the nonce and signs the transaction on the call to `SendTransaction`. --- client/asset/btc/btc.go | 21 +- client/asset/dcr/dcr.go | 26 +- client/asset/eth/eth.go | 709 +++++++++++++++++- client/asset/eth/fundingcoin.go | 50 ++ client/asset/eth/multirpc_live_test.go | 189 +++++ client/asset/eth/txdb.go | 102 ++- client/asset/eth/txdb_test.go | 10 +- client/asset/interface.go | 73 +- client/cmd/dexc-desktop/app_darwin.go | 1 - client/core/core_test.go | 4 + dex/networks/eth/bond.go | 10 +- .../eth/bondcontracts/v0/package-lock.json | 2 + dex/testing/eth/harness.sh | 15 +- 13 files changed, 1124 insertions(+), 88 deletions(-) diff --git a/client/asset/btc/btc.go b/client/asset/btc/btc.go index 0544e66bd5..595a54a7b6 100644 --- a/client/asset/btc/btc.go +++ b/client/asset/btc/btc.go @@ -8,6 +8,7 @@ import ( "context" "crypto/sha256" "encoding/binary" + "encoding/hex" "encoding/json" "errors" "fmt" @@ -4421,6 +4422,11 @@ func (btc *baseWallet) RegFeeConfirmations(_ context.Context, id dex.Bytes) (con return } +// BondConfirmations gets the numer of confirmations since the creation of a bond. +func (btc *baseWallet) BondConfirmations(_ context.Context, id dex.Bytes) (confs uint32, err error) { + return btc.RegFeeConfirmations(context.Background(), id) +} + func (btc *baseWallet) checkPeers() { numPeers, err := btc.node.peerCount() if err != nil { @@ -4972,8 +4978,11 @@ func (btc *baseWallet) MakeBondTx(ver uint16, amt, feeRate uint64, lockTime time bondInfo := &asset.BondTxInfo{ AccountID: acctID, - LockTime: uint64(lockTimeSec), - BondID: pkh, + Bond: &asset.BondInfo{ + ID: hex.EncodeToString(pkh), + Amount: amt, + LockTime: uint64(lockTimeSec), + }, } btc.addTxToHistory(asset.CreateBond, txid, amt, fee, bondInfo, nil, false) @@ -5091,9 +5100,13 @@ func (btc *baseWallet) RefundBond(ctx context.Context, ver uint16, coinID, scrip fees = amt - uint64(msgTx.TxOut[0].Value) } bondInfo := &asset.BondTxInfo{ - LockTime: uint64(lockTime), - BondID: pkhPush, + Bond: &asset.BondInfo{ + ID: hex.EncodeToString(pkhPush), + Amount: amt, + LockTime: uint64(lockTime), + }, } + btc.addTxToHistory(asset.RedeemBond, txID, amt, fees, bondInfo, nil, true) return NewOutput(txHash, 0, uint64(msgTx.TxOut[0].Value)), nil } diff --git a/client/asset/dcr/dcr.go b/client/asset/dcr/dcr.go index 8713fb3e19..ba741b27c7 100644 --- a/client/asset/dcr/dcr.go +++ b/client/asset/dcr/dcr.go @@ -4237,9 +4237,11 @@ func (dcr *ExchangeWallet) MakeBondTx(ver uint16, amt, feeRate uint64, lockTime success = true bondInfo := &asset.BondTxInfo{ - AccountID: acctID, - LockTime: uint64(lockTimeSec), - BondID: pkh, + Bond: &asset.BondInfo{ + ID: hex.EncodeToString(pkh), + Amount: amt, + LockTime: uint64(lockTimeSec), + }, } dcr.addTxToHistory(asset.CreateBond, txHash, amt, fee, bondInfo, nil, false) txIDToRemoveFromHistory = txHash @@ -4332,13 +4334,16 @@ func (dcr *ExchangeWallet) RefundBond(ctx context.Context, ver uint16, coinID, s return nil, translateRPCCancelErr(err) } - refundAmt := msgTx.TxOut[0].Value + fees := amt - uint64(msgTx.TxOut[0].Value) bondInfo := &asset.BondTxInfo{ - LockTime: uint64(lockTime), - BondID: pkhPush, + Bond: &asset.BondInfo{ + ID: hex.EncodeToString(pkhPush), + Amount: amt, + LockTime: uint64(lockTime), + }, } - dcr.addTxToHistory(asset.RedeemBond, txHash, amt, amt-uint64(refundAmt), bondInfo, nil, true) - return newOutput(redeemHash, 0, uint64(refundAmt), wire.TxTreeRegular), nil + dcr.addTxToHistory(asset.RedeemBond, txHash, amt, fees, bondInfo, nil, true) + return newOutput(redeemHash, 0, uint64(msgTx.TxOut[0].Value), wire.TxTreeRegular), nil /* If we need to find the actual unspent bond transaction for any of: (1) the output amount, (2) the commitment output data, or (3) to ensure @@ -4521,6 +4526,11 @@ func (dcr *ExchangeWallet) TransactionConfirmations(ctx context.Context, txID st return uint32(tx.Confirmations), nil } +// BondConfirmations gets the numer of confirmations since the creation of a bond. +func (dcr *ExchangeWallet) BondConfirmations(ctx context.Context, coinID dex.Bytes) (confs uint32, err error) { + return dcr.RegFeeConfirmations(ctx, coinID) +} + // RegFeeConfirmations gets the number of confirmations for the specified // output. func (dcr *ExchangeWallet) RegFeeConfirmations(ctx context.Context, coinID dex.Bytes) (confs uint32, err error) { diff --git a/client/asset/eth/eth.go b/client/asset/eth/eth.go index 5bac46c57d..83637a8497 100644 --- a/client/asset/eth/eth.go +++ b/client/asset/eth/eth.go @@ -31,7 +31,9 @@ import ( "decred.org/dcrdex/dex/keygen" "decred.org/dcrdex/dex/networks/erc20" dexeth "decred.org/dcrdex/dex/networks/eth" + v0Bond "decred.org/dcrdex/dex/networks/eth/bondcontracts/v0" multibal "decred.org/dcrdex/dex/networks/eth/contracts/multibalance" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" "github.com/decred/dcrd/hdkeychain/v3" "github.com/ethereum/go-ethereum" @@ -270,6 +272,12 @@ func (d *Driver) DecodeCoinID(coinID []byte) (string, error) { return "", err } return c.String(), nil + case bondCoinSize: + c, err := decodeBondCoin(coinID) + if err != nil { + return "", err + } + return c.String(), nil case common.AddressLength * 2, common.AddressLength*2 + 2: hexAddr := string(coinID) if !common.IsHexAddress(hexAddr) { @@ -383,6 +391,7 @@ var _ asset.Authenticator = (*ETHWallet)(nil) var _ asset.TokenApprover = (*TokenWallet)(nil) var _ asset.WalletHistorian = (*ETHWallet)(nil) var _ asset.WalletHistorian = (*TokenWallet)(nil) +var _ asset.BondUpdater = (*ETHWallet)(nil) type baseWallet struct { // The asset subsystem starts with Connect(ctx). This ctx will be initialized @@ -461,6 +470,11 @@ type assetWallet struct { refundReserves uint64 } + maintainingBondReserves atomic.Bool + + ethBond *v0Bond.ETHBond + bondAddress common.Address + findRedemptionMtx sync.RWMutex findRedemptionReqs map[[32]byte]*findRedemptionRequest @@ -832,6 +846,18 @@ func (w *ETHWallet) Connect(ctx context.Context) (_ *sync.WaitGroup, err error) } } + bondAddress, found := dexeth.ETHBondAddress[w.net] + if !found { + return nil, fmt.Errorf("no bond address for network %s", w.net) + } + + ethBond, err := v0Bond.NewETHBond(bondAddress, w.node.contractBackend()) + if err != nil { + return nil, err + } + w.ethBond = ethBond + w.bondAddress = bondAddress + w.txDB, err = newBadgerTxDB(filepath.Join(w.dir, "tx.db"), w.log.SubLogger("TXDB")) if err != nil { return nil, err @@ -1152,7 +1178,7 @@ func (w *assetWallet) fundReserveOfType(t fundReserveType) *uint64 { // lockFunds locks funds for a use case. func (w *assetWallet) lockFunds(amt uint64, t fundReserveType) error { - balance, err := w.balance() + balance, err := w.balanceWithoutBondReserves() if err != nil { return err } @@ -1195,11 +1221,12 @@ func (w *assetWallet) amountLocked() uint64 { // Balance returns the available and locked funds (token or eth). func (w *assetWallet) Balance() (*asset.Balance, error) { - return w.balance() + return w.balanceWithBondReserves() } -// balance returns the total available funds in the account. -func (w *assetWallet) balance() (*asset.Balance, error) { +// balanceWithoutBondReserves returns the total available funds in the account +// without accounting for bond reserves. +func (w *assetWallet) balanceWithoutBondReserves() (*asset.Balance, error) { bal, err := w.balanceWithTxPool() if err != nil { return nil, fmt.Errorf("pending balance error: %w", err) @@ -1215,9 +1242,33 @@ func (w *assetWallet) balance() (*asset.Balance, error) { Available: available, Locked: locked, Immature: w.atomize(bal.PendingIn), + Other: make(map[asset.BalanceCategory]asset.CustomBalance), }, nil } +// balanceWithBondReserves returns the total available funds in the account +// accounting for bond reserves. +func (w *assetWallet) balanceWithBondReserves() (*asset.Balance, error) { + bal, err := w.balanceWithoutBondReserves() + if err != nil { + return nil, err + } + + reserves := w.bondReserves() + + if reserves > bal.Available { + w.log.Warnf("Available balance insufficient for bond reserves: %f < %f", bal.Available, reserves) + bal.ReservesDeficit = reserves - bal.Available + reserves = bal.Available + } + + bal.BondReserves = reserves + bal.Available -= reserves + bal.Locked += reserves + + return bal, nil +} + // MaxOrder generates information about the maximum order size and associated // fees that the wallet can support for the given DEX configuration. The fees are an // estimate based on current network conditions, and will be <= the fees @@ -1968,7 +2019,7 @@ func (w *ETHWallet) Swap(swaps *asset.Swaps) ([]asset.Receipt, asset.Coin, uint6 } txHash := tx.Hash() - w.addToTxHistory(tx.Nonce(), swapVal, swaps.FeeRate*gasLimit, w.assetID, txHash, asset.Swap, nil) + w.addToTxHistory(tx.Nonce(), swapVal, swaps.FeeRate*gasLimit, w.assetID, txHash, asset.Swap, nil, nil) receipts := make([]asset.Receipt, 0, n) for _, swap := range swaps.Contracts { @@ -2059,7 +2110,7 @@ func (w *TokenWallet) Swap(swaps *asset.Swaps) ([]asset.Receipt, asset.Coin, uin contractAddr := w.netToken.SwapContracts[swaps.Version].Address.String() txHash := tx.Hash() - w.addToTxHistory(tx.Nonce(), swapVal, swaps.FeeRate*gasLimit, w.assetID, txHash, asset.Swap, nil) + w.addToTxHistory(tx.Nonce(), swapVal, swaps.FeeRate*gasLimit, w.assetID, txHash, asset.Swap, nil, nil) receipts := make([]asset.Receipt, 0, n) for _, swap := range swaps.Contracts { @@ -2232,7 +2283,7 @@ func (w *assetWallet) Redeem(form *asset.RedeemForm, feeWallet *assetWallet, non } txHash := tx.Hash() - w.addToTxHistory(tx.Nonce(), redeemedValue, gasFeeCap*gasLimit, w.assetID, txHash, asset.Redeem, nil) + w.addToTxHistory(tx.Nonce(), redeemedValue, gasFeeCap*gasLimit, w.assetID, txHash, asset.Redeem, nil, nil) txs := make([]dex.Bytes, len(form.Redemptions)) for i := range txs { @@ -2313,7 +2364,7 @@ func (w *assetWallet) approveToken(amount *big.Int, maxFeeRate, gasLimit uint64, if amount.Cmp(big.NewInt(0)) == 0 { txType = asset.RevokeTokenApproval } - w.addToTxHistory(tx.Nonce(), 0, maxFeeRate*gasLimit, w.assetID, txHash, txType, nil) + w.addToTxHistory(tx.Nonce(), 0, maxFeeRate*gasLimit, w.assetID, txHash, txType, nil, nil) return nil }) @@ -2383,7 +2434,7 @@ func (w *TokenWallet) ApproveToken(assetVer uint32, onConfirm func()) (string, e return "", fmt.Errorf("error calculating approval gas: %w", err) } - ethBal, err := w.parent.balance() + ethBal, err := w.parent.Balance() if err != nil { return "", fmt.Errorf("error getting eth balance: %w", err) } @@ -2433,7 +2484,7 @@ func (w *TokenWallet) UnapproveToken(assetVer uint32, onConfirm func()) (string, return "", fmt.Errorf("error calculating approval gas: %w", err) } - ethBal, err := w.parent.balance() + ethBal, err := w.parent.Balance() if err != nil { return "", fmt.Errorf("error getting eth balance: %w", err) } @@ -2896,7 +2947,7 @@ func (w *assetWallet) Refund(_, contract dex.Bytes, feeRate uint64) (dex.Bytes, txHash := tx.Hash() refundValue := dexeth.WeiToGwei(swap.Value) - w.addToTxHistory(tx.Nonce(), refundValue, fees, w.assetID, txHash, asset.Refund, nil) + w.addToTxHistory(tx.Nonce(), refundValue, fees, w.assetID, txHash, asset.Refund, nil, nil) return txHash[:], nil } @@ -2928,14 +2979,265 @@ func (eth *ETHWallet) Locked() bool { return eth.node.locked() } -// SendTransaction broadcasts a valid fully-signed transaction. -func (eth *baseWallet) SendTransaction(rawTx []byte) ([]byte, error) { +func txIsSigned(tx *types.Transaction) bool { + if tx == nil { + return false + } + + v, r, s := tx.RawSignatureValues() + // If all three values are zero, the transaction is not signed. + return !((v == nil || v.Cmp(big.NewInt(0)) == 0) && + (r == nil || r.Cmp(big.NewInt(0)) == 0) && + (s == nil || s.Cmp(big.NewInt(0)) == 0)) +} + +func (w *assetWallet) bondTxInfo(tx *types.Transaction) (asset.TransactionType, *asset.BondTxInfo) { + newBondTxInfo := func(accountID, bondID [32]byte, lockTime uint64) *asset.BondTxInfo { + return &asset.BondTxInfo{ + AccountID: accountID[:], + Bond: &asset.BondInfo{ + ID: hex.EncodeToString(bondID[:]), + Amount: w.atomize(tx.Value()), + LockTime: lockTime, + }, + } + } + + updateBondTxInfo := func(accountID [32]byte, bondsToUpdate, newBondIDs [][32]byte, value *big.Int, locktime uint64) *asset.BondTxInfo { + replacedBonds := make([]*asset.BondInfo, len(bondsToUpdate)) + var totalReplacedBondValue uint64 + var changeBondLockTime uint64 + for i, bondID := range bondsToUpdate { + bondData, err := w.ethBond.BondData(&bind.CallOpts{Context: w.ctx, From: w.addr}, accountID, bondID) + if err != nil { + w.log.Errorf("updateBondTxToInfo: failed to get bond data: %v", err) + continue + } + replacedBonds[i] = &asset.BondInfo{ + ID: hex.EncodeToString(bondID[:]), + Amount: w.atomize(bondData.Value), + LockTime: bondData.Locktime, + } + totalReplacedBondValue += w.atomize(bondData.Value) + if changeBondLockTime == 0 || bondData.Locktime < changeBondLockTime { + changeBondLockTime = bondData.Locktime + } + } + + var newBondID string + if len(newBondIDs) == 2 { + newBondID = hex.EncodeToString(newBondIDs[1][:]) + } else { + newBondID = hex.EncodeToString(newBondIDs[0][:]) + } + newBondValue := w.atomize(value) + newBond := &asset.BondInfo{ + ID: newBondID, + Amount: newBondValue, + LockTime: locktime, + } + + var changeBond *asset.BondInfo + if len(newBondIDs) == 2 { + changeBond = &asset.BondInfo{ + ID: hex.EncodeToString(newBondIDs[0][:]), + Amount: totalReplacedBondValue - newBondValue, + LockTime: changeBondLockTime, + } + } + + return &asset.BondTxInfo{ + AccountID: accountID[:], + Bond: newBond, + ChangeBond: changeBond, + ReplacedBonds: replacedBonds, + } + } + + accountID, bondID, lockTime, err := dexeth.ParseCreateBondTx(tx.Data()) + if err == nil { + return asset.CreateBond, newBondTxInfo(accountID, bondID, lockTime) + } + + accountID, bondsToUpdate, newBondIDs, value, locktime, err := dexeth.ParseUpdateBondsTx(tx.Data()) + if err == nil { + return asset.UpdateBond, updateBondTxInfo(accountID, bondsToUpdate, newBondIDs, value, locktime) + } + + // This is checked in the sendUnsignedBondTransaction, so this should never happen + w.log.Errorf("bondTxToInfo: failed to parse bond tx data: %v", err) + return asset.Unknown, nil +} + +// sendBondTxWithNewNonceAndGasFee resubmits a bond transaction with the gas +// fee provided and a new nonce. The transaction is placed into monitoredTxs +// with the key being the hash of the unsigned nonce-less transaction. +func (w *assetWallet) sendBondTxWithNewNonceAndGasFee(tx *types.Transaction, gasFeeCap *big.Int) (common.Hash, error) { + w.nonceSendMtx.Lock() + defer w.nonceSendMtx.Unlock() + + txOpts, err := w.node.txOpts(w.ctx, dexeth.WeiToGwei(tx.Value()), tx.Gas(), gasFeeCap, nil) + if err != nil { + return common.Hash{}, err + } + sentTx, err := w.node.sendTransaction(w.ctx, txOpts, *tx.To(), tx.Data()) + if err != nil { + if mRPC, is := w.node.(*multiRPCClient); is { + mRPC.voidUnusedNonce() + } + return common.Hash{}, err + } + + txHash := sentTx.Hash() + fees := dexeth.WeiToGwei(sentTx.GasPrice()) * sentTx.Gas() + bondAmount := dexeth.WeiToGwei(sentTx.Value()) + + txType, bondTxInfo := w.bondTxInfo(tx) + w.addToTxHistory(txOpts.Nonce.Uint64(), bondAmount, fees, w.assetID, txHash, txType, bondTxInfo, nil) + + w.tipMtx.RLock() + tip := w.currentTip + w.tipMtx.RUnlock() + + w.monitoredTxs[tx.Hash()] = &monitoredTx{ + tx: sentTx, + blockSubmitted: tip.Number.Uint64(), + removeAfterConfirms: 3, + timeSubmitted: time.Now(), + } + + return txHash, nil +} + +// sendUnsignedBondTransaction takes an unsigned bond creation transaction, +// adds a nonce, and submits it to the network. If the transaction has already +// been submitted (it is found in in monitoredTxs, then the transaction is not +// resubmitted unless it has been overridden by another transaction with the +// same nonce or the base gas fee has increased and the transaction cannot be +// mined at the current max fee rate. +func (w *assetWallet) sendUnsignedBondTransaction(tx *types.Transaction) ([]byte, error) { + _, _, _, newBondErr := dexeth.ParseCreateBondTx(tx.Data()) + if newBondErr != nil { + _, _, _, _, _, updateBondErr := dexeth.ParseUpdateBondsTx(tx.Data()) + if updateBondErr != nil { + return nil, fmt.Errorf("non-bond creation transactions must be signed before sending: %w", newBondErr) + } + } + + baseFee, _, err := w.node.currentFees(w.ctx) + if err != nil { + return nil, fmt.Errorf("error getting net fee state: %w", err) + } + + w.monitoredTxsMtx.Lock() + defer w.monitoredTxsMtx.Unlock() + + monitoredTx, found := w.monitoredTxs[tx.Hash()] + if !found { + // If this is the first time submitting this transaction, do not submit + // if the base fee is greater than the gas fee limit. + gasFeeCap := tx.GasFeeCap() + if baseFee.Cmp(tx.GasFeeCap()) > 0 { + gasFeeLimitWei := dexeth.GweiToWei(w.gasFeeLimit()) + if baseFee.Cmp(gasFeeLimitWei) > 0 { + return nil, fmt.Errorf("base fee %d exceeds gas fee limit %d. not sending bond tx", baseFee, gasFeeLimitWei) + } + // In MakeBondTx, the GasFeeCap is set to gasFeeLimit, but maybe the + // user updated the gasFeeLimit due to the above error message. + gasFeeCap = gasFeeLimitWei + } + + txHash, err := w.sendBondTxWithNewNonceAndGasFee(tx, gasFeeCap) + if err != nil { + return nil, err + } + + return txHash.Bytes(), nil + } + + receipt, _, err := w.node.transactionReceipt(w.ctx, monitoredTx.tx.Hash()) + if err != nil && err != asset.CoinNotFoundError { + return nil, err + } + if err == nil && receipt.BlockNumber.Cmp(big.NewInt(0)) > 0 { + // If already mined, just return the tx hash + return monitoredTx.tx.Hash().Bytes(), nil + } + + // If the transaction has been recently submitted, transactionReceipt might + // return asset.CoinNotFoundError and the confirmed nonce was already bumped. + if err == asset.CoinNotFoundError && time.Since(monitoredTx.timeSubmitted) < time.Minute { + return monitoredTx.tx.Hash().Bytes(), nil + } + + // If the transaction is still pending, check if the nonce is still valid. + // If not, resubmit with new nonce. + confirmedNonce, err := w.node.getConfirmedNonce(w.ctx) + if err != nil { + return nil, err + } + if confirmedNonce > monitoredTx.tx.Nonce() { + txHash, err := w.sendBondTxWithNewNonceAndGasFee(tx, monitoredTx.tx.GasFeeCap()) + if err != nil { + return nil, err + } + return txHash.Bytes(), nil + } + + // If nonce is not yet expired, check if gas fee too low. + if baseFee.Cmp(monitoredTx.tx.GasFeeCap()) > 0 { + baseFeeGwei := dexeth.WeiToGwei(baseFee) + gasLimit := monitoredTx.tx.Gas() + if gasLimit == 0 { + // Should not happen, but return here to avoid divide-by-zero + // panic below. + return nil, fmt.Errorf("gas is zero") + } + + gasFeeCapGwei := dexeth.WeiToGwei(monitoredTx.tx.GasFeeCap()) + originalFundsUsed := gasFeeCapGwei * monitoredTx.tx.Gas() + additionalFundsNeeded := (2 * baseFeeGwei * gasLimit) - originalFundsUsed + bal, err := w.Balance() + if err != nil { + return nil, err + } + + // Use as much as possible. On the initial send, we can reject, but if this tx is + // already pending, we should try to bump the gas fee in order to avoid holding up + // other transactions. + var gasFeeCap *big.Int + if bal.Available > additionalFundsNeeded { + gasFeeCap = gasFeeCap.Mul(baseFee, big.NewInt(2)) + } else { + totalFee := dexeth.GweiToWei(bal.Available + originalFundsUsed) + gasFeeCap = totalFee.Div(totalFee, big.NewInt(int64(monitoredTx.tx.Gas()))) + } + + txHash, err := w.sendBondTxWithNewNonceAndGasFee(tx, gasFeeCap) + if err != nil { + return nil, err + } + return txHash.Bytes(), nil + } + + // If nonce is not yet expired and gas fee is still good, just return the tx hash + return monitoredTx.tx.Hash().Bytes(), nil +} + +// SendTransaction broadcasts a transaction. If it is not yet signed, +// a nonce will be added and the transaction signed. +func (w *assetWallet) SendTransaction(rawTx []byte) ([]byte, error) { tx := new(types.Transaction) err := tx.UnmarshalBinary(rawTx) if err != nil { return nil, fmt.Errorf("failed to unmarshal transaction: %w", err) } - if err := eth.node.sendSignedTransaction(eth.ctx, tx); err != nil { + + if !txIsSigned(tx) { + return w.sendUnsignedBondTransaction(tx) + } + + if err := w.node.sendSignedTransaction(w.ctx, tx); err != nil { return nil, err } return tx.Hash().Bytes(), nil @@ -3074,6 +3376,291 @@ func (w *ETHWallet) EstimateSendTxFee(addr string, value, _ uint64, subtract boo return maxFee, w.ValidateAddress(addr), nil } +// MakeBondTx creates an unsigned transaction to create a new bond. ETH +// transactions cannot be signed beforehand due to nonce ordering, so the +// the SignedTx and UnsignedTx fields in the return value both contain +// the same data. The nonce and the signature is added when SendTransaction +// is called. +func (w *ETHWallet) MakeBondTx(ver uint16, amt uint64, feeRate uint64, lockTime time.Time, privKey *secp256k1.PrivateKey, acctID []byte) (*asset.Bond, func(), error) { + if ver != 0 { + return nil, nil, fmt.Errorf("only version 0 bonds are supported") + } + + var accountID, bondID [32]byte + copy(accountID[:], acctID) + copy(bondID[:], privKey.Serialize()) + data, err := dexeth.PackCreateBondTx(accountID, bondID, uint64(lockTime.Unix())) + if err != nil { + return nil, nil, err + } + + balance, err := w.balanceWithoutBondReserves() + if err != nil { + return nil, nil, err + } + + gasFeeLimit := w.gasFeeLimit() + if balance.Available < amt+dexeth.NewBondGas*gasFeeLimit { + return nil, nil, asset.ErrInsufficientBalance + } + + bondTx := types.NewTx(&types.DynamicFeeTx{ + Value: dexeth.GweiToWei(amt), + To: &w.bondAddress, + Gas: dexeth.NewBondGas, + GasFeeCap: dexeth.GweiToWei(gasFeeLimit), + Data: data}) + serializedTx, err := bondTx.MarshalBinary() + if err != nil { + return nil, nil, err + } + + abort := func() {} + + return &asset.Bond{ + Version: ver, + AssetID: BipID, + Amount: amt, + CoinID: createBondCoin(accountID, bondID, amt).ID(), + SignedTx: serializedTx, + UnsignedTx: serializedTx, + LockTime: uint64(lockTime.Unix()), + }, abort, nil +} + +// setupForUpdateBond extracts the accountID and bondIDs from the bondCoins, +// sorts the bondIDs by lock time, and returns the earliest lockTime and total +// value of the bonds to be updated. +func (w *ETHWallet) setupForUpdateBond(bondCoins []dex.Bytes) (accountID [32]byte, sortedBondIDs [][32]byte, earliestLockTime uint64, totalValue uint64, err error) { + type bondIDAndLockTime struct { + bondID [32]byte + lockTime uint64 + } + + bondIDsAndLockTimes := make([]*bondIDAndLockTime, len(bondCoins)) + totalBondValueWei := big.NewInt(0) + + for i, bondCoin := range bondCoins { + bondCoin, err := decodeBondCoin(bondCoin) + if err != nil { + return [32]byte{}, nil, 0, 0, err + } + + bondData, err := w.ethBond.BondData(&bind.CallOpts{Context: w.ctx, From: w.addr}, bondCoin.accountID, bondCoin.bondID) + if err != nil { + return [32]byte{}, nil, 0, 0, fmt.Errorf("error getting bond data: %w", err) + } + + if i == 0 { + accountID = bondCoin.accountID + } else if accountID != bondCoin.accountID { + return [32]byte{}, nil, 0, 0, fmt.Errorf("bonds to update must be from the same account") + } + + bondIDsAndLockTimes[i] = &bondIDAndLockTime{ + bondID: bondCoin.bondID, + lockTime: bondData.Locktime, + } + totalBondValueWei = totalBondValueWei.Add(totalBondValueWei, bondData.Value) + } + + totalValue = dexeth.WeiToGwei(totalBondValueWei) + + sort.Slice(bondIDsAndLockTimes, func(i, j int) bool { + return bondIDsAndLockTimes[i].lockTime < bondIDsAndLockTimes[j].lockTime + }) + earliestLockTime = bondIDsAndLockTimes[0].lockTime + + sortedBondIDs = make([][32]byte, len(bondIDsAndLockTimes)) + for i, bondIDAndLockTime := range bondIDsAndLockTimes { + sortedBondIDs[i] = bondIDAndLockTime.bondID + } + + return accountID, sortedBondIDs, earliestLockTime, totalValue, nil +} + +// UpdateBondTx creates an unsigned transaction that uses the funds locked in +// one or more bonds to create a new bond with a longer lockTime. If the total +// value of the bonds is greater than the new bond, a "change" bond will be +// created with the remaining funds and the same lockTime as the earliest +// expiring bond. If two bonds are being created, the "change" bond will be the +// first in the returned []*asset.Bond slice. +// +// Requirements: +// - The correct amount of privKeys must be passed, depending on whether or not +// a change bond is needed. +// - The lockTime must be later than the latest lockTime of the bondsToUpdate. +// - The value of the earliest expiring bond must be greater than the "change" +// bond value. +// - The bondsToUpdate must all be from the same account. +func (w *ETHWallet) UpdateBondTx(ver uint16, bondsToUpdate []dex.Bytes, privKeys []*secp256k1.PrivateKey, amt uint64, lockTime time.Time) ([]*asset.Bond, error) { + if len(bondsToUpdate) == 0 { + return nil, fmt.Errorf("no bonds to update") + } + + accountID, bondIDs, earliestLockTime, totalValueGwei, err := w.setupForUpdateBond(bondsToUpdate) + if err != nil { + return nil, err + } + + var gweiRequired uint64 + if totalValueGwei < amt { + gweiRequired = amt - totalValueGwei + } + balance, err := w.balanceWithoutBondReserves() + if err != nil { + return nil, err + } + gasFeeLimit := w.gasFeeLimit() + if balance.Available < gweiRequired+dexeth.UpdateBondGas*gasFeeLimit { + return nil, asset.ErrInsufficientBalance + } + + newBondCoinIDs := make([][32]byte, 0, len(privKeys)) + for _, privKey := range privKeys { + var bondID [32]byte + copy(bondID[:], privKey.Serialize()) + newBondCoinIDs = append(newBondCoinIDs, bondID) + } + + weiAmt := dexeth.GweiToWei(amt) + lt := uint64(lockTime.Unix()) + weiToSend := dexeth.GweiToWei(gweiRequired) + canUpdate, _, reason, err := w.ethBond.VerifyBondUpdate( + &bind.CallOpts{Context: w.ctx, From: w.addr}, accountID, bondIDs, newBondCoinIDs, weiAmt, lt, weiToSend) + if err != nil { + return nil, fmt.Errorf("error checking if bond can be updated: %w", err) + } + if !canUpdate { + return nil, fmt.Errorf("bond cannot be updated: %s", reason) + } + + data, err := dexeth.PackUpdateBondsTx(accountID, bondIDs, newBondCoinIDs, weiAmt, lt) + if err != nil { + return nil, err + } + + bondTx := types.NewTx(&types.DynamicFeeTx{ + Value: weiToSend, + To: &w.bondAddress, + Gas: dexeth.UpdateBondGas, + GasFeeCap: dexeth.GweiToWei(gasFeeLimit), + Data: data}) + serializedTx, err := bondTx.MarshalBinary() + if err != nil { + return nil, err + } + + if len(newBondCoinIDs) == 2 { + return []*asset.Bond{ + { + Version: ver, + AssetID: BipID, + Amount: totalValueGwei - amt, + CoinID: createBondCoin(accountID, newBondCoinIDs[0], totalValueGwei-amt).ID(), + SignedTx: serializedTx, + UnsignedTx: serializedTx, + LockTime: earliestLockTime, + }, + { + Version: ver, + AssetID: BipID, + Amount: amt, + CoinID: createBondCoin(accountID, newBondCoinIDs[1], amt).ID(), + SignedTx: serializedTx, + UnsignedTx: serializedTx, + LockTime: uint64(lockTime.Unix()), + }, + }, nil + } + + return []*asset.Bond{ + { + Version: ver, + AssetID: BipID, + Amount: amt, + CoinID: createBondCoin(accountID, newBondCoinIDs[0], amt).ID(), + SignedTx: serializedTx, + UnsignedTx: serializedTx, + LockTime: uint64(lockTime.Unix()), + }, + }, nil +} + +// RefundBond retrieves the funds locked in an expired bond. +func (w *ETHWallet) RefundBond(ctx context.Context, ver uint16, coinID []byte, _ []byte, _ uint64, _ *secp256k1.PrivateKey) (asset.Coin, error) { + bondCoin, err := decodeBondCoin(coinID) + if err != nil { + return nil, err + } + + refundable, err := w.ethBond.BondRefundable(&bind.CallOpts{Context: ctx}, bondCoin.accountID, bondCoin.bondID) + if err != nil { + return nil, fmt.Errorf("error checking if bond is refundable: %w", err) + } + if !refundable { + return nil, fmt.Errorf("bond is not refundable") + } + + bondData, err := w.ethBond.BondData(&bind.CallOpts{Context: ctx}, bondCoin.accountID, bondCoin.bondID) + if err != nil { + return nil, fmt.Errorf("error getting bond data: %w", err) + } + + w.nonceSendMtx.Lock() + defer w.nonceSendMtx.Unlock() + txOpts, err := w.node.txOpts(ctx, 0, dexeth.RefundBondGas, dexeth.GweiToWei(w.gasFeeLimit()), nil) + if err != nil { + return nil, err + } + tx, err := w.ethBond.RefundBond(txOpts, bondCoin.accountID, bondCoin.bondID) + if err != nil { + return nil, fmt.Errorf("error refunding bond: %w", err) + } + + bondVal := dexeth.WeiToGwei(bondData.Value) + fees := dexeth.WeiToGwei(tx.GasPrice()) * tx.Gas() + + bondInfo := &asset.BondTxInfo{ + AccountID: bondCoin.accountID[:], + Bond: &asset.BondInfo{ + ID: hex.EncodeToString(bondCoin.bondID[:]), + Amount: bondVal, + LockTime: bondData.Locktime, + }, + } + w.addToTxHistory(tx.Nonce(), bondVal, fees, w.assetID, tx.Hash(), asset.RedeemBond, bondInfo, nil) + + return createBondCoin(bondCoin.accountID, bondCoin.bondID, bondVal), nil +} + +// SetBondReserves does nothing for ETH, because bond reserves are only +// required for the fee buffer. +func (a *assetWallet) SetBondReserves(reserves uint64) { + a.maintainingBondReserves.Store(reserves > 0) +} + +func bondFeeBuffer(feeRateLimit uint64) uint64 { + const numExtensions uint64 = 8 + return feeRateLimit * dexeth.UpdateBondGas * numExtensions +} + +// BondsFeeBuffer suggests how much may be required to be reserved for +// transaction fees when bond rotation is enabled. +func (w *assetWallet) BondsFeeBuffer(feeRate uint64) uint64 { + return bondFeeBuffer(feeRate) +} + +// bondReserves returns the bond fee buffer if the nominal bond reserves +// and greater than zero, otherwise it returns zero. +func (w *assetWallet) bondReserves() uint64 { + if w.maintainingBondReserves.Load() { + return w.BondsFeeBuffer(w.gasFeeLimit()) + } + + return 0 +} + // EstimateSendTxFee returns a tx fee estimate for a send tx. The provided fee // rate is ignored since all sends will use an internally derived fee rate. If // an address is provided, it will ensure wallet has enough to cover total @@ -3177,7 +3764,7 @@ func (w *ETHWallet) Send(addr string, value, _ uint64) (asset.Coin, error) { txType = asset.SelfSend } - w.addToTxHistory(tx.Nonce(), value, maxFee, w.assetID, txHash, txType, &addr) + w.addToTxHistory(tx.Nonce(), value, maxFee, w.assetID, txHash, txType, nil, &addr) return &coin{id: txHash, value: value}, nil } @@ -3201,7 +3788,7 @@ func (w *TokenWallet) Send(addr string, value, _ uint64) (asset.Coin, error) { } txHash := tx.Hash() - w.addToTxHistory(tx.Nonce(), value, maxFee, w.assetID, txHash, asset.Send, &addr) + w.addToTxHistory(tx.Nonce(), value, maxFee, w.assetID, txHash, asset.Send, nil, &addr) return &coin{id: txHash, value: value}, nil } @@ -3359,11 +3946,32 @@ func (eth *baseWallet) swapOrRedemptionFeesPaid(ctx context.Context, coinID, con return dexeth.WeiToGwei(bigFees), secretHashes, nil } -// TransactionConfirmations gets the number of confirmations for the specified -// transaction. -func (eth *baseWallet) TransactionConfirmations(ctx context.Context, txID string) (confs uint32, err error) { - txHash := common.HexToHash(txID) - return eth.node.transactionConfirmations(ctx, txHash) +// BondConfirmations gets the numer of confirmations since the creation of a bond. +func (eth *ETHWallet) BondConfirmations(ctx context.Context, coinID dex.Bytes) (confs uint32, err error) { + bondCoin, err := decodeBondCoin(coinID) + if err != nil { + return 0, err + } + + bondData, err := eth.ethBond.BondData(&bind.CallOpts{Context: ctx}, bondCoin.accountID, bondCoin.bondID) + if err != nil { + return 0, err + } + + bestHdr, err := eth.node.bestHeader(ctx) + if err != nil { + return 0, err + } + + if bondData.InitBlockNumber.Int64() == 0 { + return 0, nil + } + + if bestHdr.Number.Int64() < bondData.InitBlockNumber.Int64() { + return 0, nil + } + + return uint32(bestHdr.Number.Int64() - bondData.InitBlockNumber.Int64() + 1), nil } // RegFeeConfirmations gets the number of confirmations for the specified @@ -3495,6 +4103,9 @@ func (eth *ETHWallet) checkForNewBlocks(ctx context.Context) { go func() { for _, w := range connectedWallets { + if w.emit == nil { + continue + } w.emit.TipChange(bestHdr.Number.Uint64()) } }() @@ -3517,6 +4128,48 @@ func (eth *ETHWallet) checkForNewBlocks(ctx context.Context) { defer eth.txDbWg.Done() eth.checkPendingTxs() }() + + eth.txDbWg.Add(1) + go func() { + defer eth.txDbWg.Done() + eth.clearConfirmedMonitoredTxs(bestHdr.Number.Uint64()) + }() +} + +// clearConfirmedMonitoredTxs removes monitored transaction maked with +// removeAfterConfirms if they have been confirmed. +func (w *assetWallet) clearConfirmedMonitoredTxs(currentTip uint64) { + w.monitoredTxsMtx.Lock() + defer w.monitoredTxsMtx.Unlock() + + for _, tx := range w.monitoredTxs { + if tx.removeAfterConfirms == 0 { + continue + } + + txHash := tx.tx.Hash() + _, txBlock, err := w.node.getTransaction(w.ctx, txHash) + if err != nil && errors.Is(asset.CoinNotFoundError, err) { + continue + } else if err != nil { + w.log.Errorf("error getting receipt for monitored tx %s: %v", tx.tx.Hash(), err) + continue + } + + w.log.Tracef("clearing monitored tx %s, txBlock: %d, currentTip: %d", txHash, txBlock, currentTip) + + var confirms uint64 + if currentTip >= uint64(txBlock) { + confirms = uint64(txBlock) - currentTip + 1 + } + + if confirms >= tx.removeAfterConfirms { + if err := w.txDB.removeMonitoredTxs([]common.Hash{txHash}); err != nil { + w.log.Errorf("failed to delete monitored tx: %v", err) + } + delete(w.monitoredTxs, tx.tx.Hash()) + } + } } // getLatestMonitoredTx looks up a txHash in the monitoredTxs map. If the @@ -4585,6 +5238,10 @@ func (w *baseWallet) emitTransactionNote(tx *asset.WalletTransaction, new bool) } w.walletsMtx.RUnlock() + if baseWallet.emit == nil { + return + } + if found { baseWallet.emit.TransactionNote(tx, new) } else { @@ -4733,7 +5390,7 @@ func (w *baseWallet) checkPendingTxs() { const txHistoryNonceKey = "Nonce" -func (w *baseWallet) addToTxHistory(nonce, amount, fees uint64, assetID uint32, txHash common.Hash, txType asset.TransactionType, recipient *string) { +func (w *baseWallet) addToTxHistory(nonce, amount, fees uint64, assetID uint32, txHash common.Hash, txType asset.TransactionType, bondInfo *asset.BondTxInfo, recipient *string) { var tokenAssetID *uint32 if assetID != w.baseChainID { tokenAssetID = &assetID @@ -4750,6 +5407,7 @@ func (w *baseWallet) addToTxHistory(nonce, amount, fees uint64, assetID uint32, AdditionalData: map[string]string{ txHistoryNonceKey: strconv.FormatUint(nonce, 10), }, + BondInfo: bondInfo, }, SubmissionTime: uint64(time.Now().Unix()), savedToDB: true, @@ -4798,6 +5456,13 @@ func (w *TokenWallet) TxHistory(n int, refID *string, past bool) ([]*asset.Walle return w.txDB.getTxs(n, refID, past, &w.assetID) } +// TransactionConfirmations gets the number of confirmations for the specified +// transaction. +func (eth *baseWallet) TransactionConfirmations(ctx context.Context, txID string) (confs uint32, err error) { + txHash := common.HexToHash(txID) + return eth.node.transactionConfirmations(ctx, txHash) +} + // providersFile reads a file located at ~/dextest/credentials.json. // The file contains seed and provider information for wallets used for // getgas, deploy, and nodeclient testing. If simnet providers are not diff --git a/client/asset/eth/fundingcoin.go b/client/asset/eth/fundingcoin.go index 536cbd1779..aaf0d56e66 100644 --- a/client/asset/eth/fundingcoin.go +++ b/client/asset/eth/fundingcoin.go @@ -7,12 +7,14 @@ import ( "encoding/binary" "fmt" + "decred.org/dcrdex/client/asset" "decred.org/dcrdex/dex" "github.com/ethereum/go-ethereum/common" ) const fundingCoinIDSize = 28 // address (20) + amount (8) = 28 const tokenFundingCoinIDSize = 36 // address (20) + amount (8) + amount (8) = 36 +const bondCoinSize = 64 // accountID (32) + bondID (32) // fundingCoin is an identifier for a coin which has not yet been sent to the // swap contract. @@ -135,3 +137,51 @@ func createTokenFundingCoin(address common.Address, tokenValue, fees uint64) *to fees: fees, } } + +type bondCoin struct { + accountID [32]byte + bondID [32]byte + value uint64 +} + +var _ asset.Coin = (*bondCoin)(nil) + +func decodeBondCoin(coinID []byte) (*bondCoin, error) { + if len(coinID) != bondCoinSize { + return nil, fmt.Errorf("decodeBondRefundCoin: length expected %v, got %v", + bondCoinSize, len(coinID)) + } + + var bondID, accountID [32]byte + copy(accountID[:], coinID[0:32]) + copy(bondID[:], coinID[32:64]) + + return &bondCoin{ + bondID: bondID, + accountID: accountID, + }, nil +} + +func (c *bondCoin) ID() dex.Bytes { + return append(c.accountID[:], c.bondID[:]...) +} + +func (c *bondCoin) String() string { + return fmt.Sprintf("accountID: %x, bondID: %x", c.accountID, c.bondID) +} + +func (c *bondCoin) Value() uint64 { + return c.value +} + +func (c *bondCoin) TxID() string { + return "" +} + +func createBondCoin(accountID, bondID [32]byte, value uint64) *bondCoin { + return &bondCoin{ + accountID: accountID, + bondID: bondID, + value: value, + } +} diff --git a/client/asset/eth/multirpc_live_test.go b/client/asset/eth/multirpc_live_test.go index 7e9d159ee3..6ea6cb1354 100644 --- a/client/asset/eth/multirpc_live_test.go +++ b/client/asset/eth/multirpc_live_test.go @@ -4,10 +4,18 @@ package eth import ( "context" + "encoding/hex" + "fmt" "os" + "path/filepath" "testing" + "time" + "decred.org/dcrdex/client/asset" "decred.org/dcrdex/dex" + "decred.org/dcrdex/dex/encode" + dexeth "decred.org/dcrdex/dex/networks/eth" + "github.com/decred/dcrd/dcrec/secp256k1/v4" ) const ( @@ -17,6 +25,14 @@ const ( var mt *MRPCTest +var ( + ctx = context.Background() + homeDir = os.Getenv("HOME") + simnetWalletDir = filepath.Join(homeDir, "dextest", "eth", "client_rpc_tests", "simnet") + simnetWalletSeed = "0812f5244004217452059e2fd11603a511b5d0870ead753df76c966ce3c71531" + pw = "bee75192465cef9f8ab1198093dfed594e93ae810ccbbf2b3b12e1771cc6cb19" +) + func TestMain(m *testing.M) { ctx, shutdown := context.WithCancel(context.Background()) mt = NewMRPCTest(ctx, ChainConfig, NetworkCompatibilityData, "eth") @@ -96,3 +112,176 @@ func TestFreeServers(t *testing.T) { func TestMainnetCompliance(t *testing.T) { mt.TestMainnetCompliance(t) } + +func setupWallet(walletDir, seed string, net dex.Network) error { + walletType := walletTypeRPC + seedBytes, err := hex.DecodeString(seed) + if err != nil { + return fmt.Errorf("error decoding seed: %v", err) + } + + comp, err := NetworkCompatibilityData(net) + if err != nil { + return fmt.Errorf("error finding compatibility data: %v", err) + } + + cfg := &asset.CreateWalletParams{ + Type: walletType, + Seed: seedBytes, + Pass: []byte(pw), + Settings: map[string]string{ + "gasfeelimit": "200", + "providers": filepath.Join(homeDir, "dextest", "eth", "alpha", "node", "geth.ipc"), + "special_activelyUsed": "false", + }, + DataDir: walletDir, + Net: net, + Logger: dex.StdOutLogger("T", dex.LevelTrace), + } + + return CreateEVMWallet(dexeth.ChainIDs[net], cfg, &comp, false) +} + +func TestMakeBondTx(t *testing.T) { + err := setupWallet(simnetWalletDir, simnetWalletSeed, dex.Simnet) + if err != nil { + t.Fatalf("error setting up wallet: %v", err) + } + + walletConfig := &asset.WalletConfig{ + Type: "rpc", + Settings: map[string]string{ + "gasfeelimit": "200", + "providers": filepath.Join(homeDir, "dextest", "eth", "alpha", "node", "geth.ipc"), + "special_activelyUsed": "false", + }, + PeersChange: func(uint32, error) {}, + DataDir: simnetWalletDir, + } + log := dex.StdOutLogger("T", dex.LevelTrace) + + backend, err := newWallet(walletConfig, log, dex.Simnet) + if err != nil { + t.Fatalf("error creating wallet: %v", err) + } + + context, cancel := context.WithCancel(context.Background()) + defer cancel() + cm := dex.NewConnectionMaster(backend) + err = cm.Connect(context) + if err != nil { + t.Fatalf("error connecting wallet: %v", err) + } + + priv, err := secp256k1.GeneratePrivateKey() + if err != nil { + t.Fatal(err) + } + + addr, err := backend.DepositAddress() + if err != nil { + t.Fatalf("error getting deposit address: %v", err) + } + fmt.Printf("deposit address: %s\n", addr) + + accountID := encode.RandomBytes(32) + fmt.Printf("accountID %x\n", accountID) + amt := uint64(1000000000) + bond, _, err := backend.MakeBondTx(0, amt, 0, time.Now(), priv, accountID) + if err != nil { + t.Fatalf("error creating bond tx: %v", err) + } + + err = backend.Unlock([]byte(pw)) + if err != nil { + t.Fatalf("error unlocking wallet: %v", err) + } + + bondTxHash, err := backend.SendTransaction(bond.SignedTx) + if err != nil { + t.Fatalf("error sending bond tx: %v", err) + } + + fmt.Printf("Initial bond ID %s\n", hex.EncodeToString(priv.Serialize())) + fmt.Printf("Initial bond TX Hash %x\n", bondTxHash) + + var confs uint32 + for i := 0; i < 30; i++ { + confs, err = backend.BondConfirmations(ctx, bond.CoinID) + if err != nil { + t.Fatalf("error getting confirmations: %v", err) + } + if confs > 0 { + break + } + fmt.Println("Waiting for confirmations for initial bond tx...") + time.Sleep(1 * time.Second) + } + if confs == 0 { + t.Fatalf("no confirmations") + } + + newPriv1, err := secp256k1.GeneratePrivateKey() + if err != nil { + t.Fatal(err) + } + + newPriv2, err := secp256k1.GeneratePrivateKey() + if err != nil { + t.Fatal(err) + } + + fmt.Printf("Change Bond ID: %s\n", hex.EncodeToString(newPriv1.Serialize())) + fmt.Printf("Updated Bond ID: %s\n", hex.EncodeToString(newPriv2.Serialize())) + + newBonds, err := backend.UpdateBondTx(0, []dex.Bytes{bond.CoinID}, []*secp256k1.PrivateKey{newPriv1, newPriv2}, amt/2, time.Now()) + if err != nil { + t.Fatalf("error creating update bond tx: %v", err) + } + + for _, newBond := range newBonds { + newBondTxHash, err := backend.SendTransaction(newBond.SignedTx) + if err != nil { + t.Fatalf("error sending update bond tx: %v", err) + } + fmt.Printf("Update bond tx hash %x\n", newBondTxHash) + } + + for i := 0; i < 30; i++ { + confs, err = backend.BondConfirmations(ctx, newBonds[0].CoinID) + if err != nil { + t.Fatalf("error getting confirmations: %v", err) + } + if confs > 0 { + break + } + fmt.Println("Waiting for confirmations for update bond tx...") + time.Sleep(1 * time.Second) + } + if confs == 0 { + t.Fatalf("no confirmations") + } + + bal, err := backend.Balance() + if err != nil { + t.Fatalf("error getting balance: %v", err) + } + preRefundBalance := bal.Available + + _, err = backend.RefundBond(ctx, 0, newBonds[0].CoinID, nil, 0, priv) + if err != nil { + t.Fatalf("error creating refund tx: %v", err) + } + + for i := 0; i < 20; i++ { + bal, err := backend.Balance() + if err != nil { + t.Fatalf("error getting balance: %v", err) + } + if bal.Available > preRefundBalance { + return + } + fmt.Println("Waiting for bond refund...") + time.Sleep(1 * time.Second) + } +} diff --git a/client/asset/eth/txdb.go b/client/asset/eth/txdb.go index 4b7da5491c..db91ba9845 100644 --- a/client/asset/eth/txdb.go +++ b/client/asset/eth/txdb.go @@ -34,15 +34,27 @@ type extendedWalletTx struct { savedToDB bool } -// monitoredTx is used to keep track of redemption transactions that have not -// yet been confirmed. If a transaction has to be replaced due to the fee -// being too low or another transaction being mined with the same nonce, -// the replacement transaction's ID is recorded in the replacementTx field. -// replacedTx is used to maintain a doubly linked list, which allows deletion -// of transactions that were replaced after a transaction is confirmed. +// monitoredTx is used to keep track of redemption and bond creation/update +// transactions that have not yet been confirmed. +// +// If a redemption transaction has to be resubmitted, the replacement +// transaction's ID is recorded in the replacementTx field. replacedTx is used +// to maintain a doubly linked list, which allows the most recently submitted +// transaction to be looked up in case an older one's ID is requested. +// +// For bond creation/update transactions this is not needed, since BondConfirmations +// is called using the BondID instead of with the transaction ID. type monitoredTx struct { tx *types.Transaction blockSubmitted uint64 + // There is a goroutine that runs on each new block that checks the + // number of confirmations for all monitoredTxs with removeAfterConfirms > 0. + // If the number of confirmations is greater than or equal to + // removeAfterConfirms, the transaction is removed. This is done for + // bond transactions. redemption transactions are removed separately + // from this process. + removeAfterConfirms uint64 + timeSubmitted time.Time // This mutex must be held during the entire process of confirming // a transaction. This is to avoid confirmations of the same @@ -60,7 +72,7 @@ type monitoredTx struct { // MarshalBinary marshals a monitoredTx into a byte array. // It satisfies the encoding.BinaryMarshaler interface for monitoredTx. func (m *monitoredTx) MarshalBinary() (data []byte, err error) { - b := encode.BuildyBytes{0} + b := encode.BuildyBytes{1} txB, err := m.tx.MarshalBinary() if err != nil { return nil, fmt.Errorf("error marshaling tx: %v", err) @@ -71,24 +83,26 @@ func (m *monitoredTx) MarshalBinary() (data []byte, err error) { binary.BigEndian.PutUint64(blockB, m.blockSubmitted) b = b.AddData(blockB) - if m.replacementTx != nil { - replacementTxHash := m.replacementTx[:] - b = b.AddData(replacementTxHash) + removeAfterConfirmsB := make([]byte, 8) + binary.BigEndian.PutUint64(removeAfterConfirmsB, m.removeAfterConfirms) + b = b.AddData(removeAfterConfirmsB) + + if m.replacementTx == nil { + b = b.AddData([]byte{}) + } else { + b = b.AddData(m.replacementTx[:]) + } + + if m.replacedTx == nil { + b = b.AddData([]byte{}) + } else { + b = b.AddData(m.replacedTx[:]) } return b, nil } -// UnmarshalBinary loads a data from a marshalled byte array into a -// monitoredTx. -func (m *monitoredTx) UnmarshalBinary(data []byte) error { - ver, pushes, err := encode.DecodeBlob(data) - if err != nil { - return err - } - if ver != 0 { - return fmt.Errorf("unknown version %d", ver) - } +func (m *monitoredTx) unmarshalV0(pushes [][]byte) error { if len(pushes) != 2 && len(pushes) != 3 { return fmt.Errorf("wrong number of pushes %d", len(pushes)) } @@ -108,6 +122,54 @@ func (m *monitoredTx) UnmarshalBinary(data []byte) error { return nil } +// v1 added the removeAfterConfirms and the replacedTx fields. +func (m *monitoredTx) unmarshalV1(pushes [][]byte) error { + if len(pushes) != 5 { + return fmt.Errorf("wrong number of pushes %d", len(pushes)) + } + + m.tx = &types.Transaction{} + if err := m.tx.UnmarshalBinary(pushes[0]); err != nil { + return fmt.Errorf("error reading tx: %w", err) + } + + m.blockSubmitted = binary.BigEndian.Uint64(pushes[1]) + m.removeAfterConfirms = binary.BigEndian.Uint64(pushes[2]) + + if len(pushes[3]) > 0 { + var replacementTxHash common.Hash + copy(replacementTxHash[:], pushes[3]) + m.replacementTx = &replacementTxHash + } + + if len(pushes[4]) > 0 { + var replacedTxHash common.Hash + copy(replacedTxHash[:], pushes[4]) + m.replacedTx = &replacedTxHash + } + + return nil +} + +// UnmarshalBinary loads a data from a marshalled byte array into a +// monitoredTx. +func (m *monitoredTx) UnmarshalBinary(data []byte) error { + ver, pushes, err := encode.DecodeBlob(data) + if err != nil { + return err + } + + if ver > 1 { + return fmt.Errorf("unknown version %d", ver) + } + + if ver == 0 { + return m.unmarshalV0(pushes) + } + + return m.unmarshalV1(pushes) +} + var ( // noncePrefix is the prefix for the key used to map a nonce to an // extendedWalletTx. diff --git a/client/asset/eth/txdb_test.go b/client/asset/eth/txdb_test.go index f6a6c148fa..575e626a2f 100644 --- a/client/asset/eth/txdb_test.go +++ b/client/asset/eth/txdb_test.go @@ -268,10 +268,16 @@ func TestTxDB(t *testing.T) { if a.tx.Hash() != b.tx.Hash() { return false } - if a.replacementTx != nil && b.replacementTx != nil && *a.replacementTx != *b.replacementTx { + if (a.replacementTx == nil) != (b.replacementTx == nil) { return false } - if a.replacedTx != nil && b.replacedTx != nil && *a.replacedTx != *b.replacedTx { + if a.replacementTx != nil && *a.replacementTx != *b.replacementTx { + return false + } + if (a.replacedTx == nil) != (b.replacedTx == nil) { + return false + } + if a.replacedTx != nil && *a.replacedTx != *b.replacedTx { return false } if a.blockSubmitted != b.blockSubmitted { diff --git a/client/asset/interface.go b/client/asset/interface.go index 929065bb7c..974416991c 100644 --- a/client/asset/interface.go +++ b/client/asset/interface.go @@ -35,6 +35,7 @@ const ( WalletTraitTicketBuyer // The wallet can participate in decred staking. WalletTraitHistorian // This wallet can return its transaction history WalletTraitFundsMixer // The wallet can mix funds. + WalletTraitBondUpdater // The wallet can update bonds. ) // IsRescanner tests if the WalletTrait has the WalletTraitRescanner bit set. @@ -145,6 +146,12 @@ func (wt WalletTrait) IsFundsMixer() bool { return wt&WalletTraitFundsMixer != 0 } +// IsBondUpdater tests if the WalletTrait has the WalletTraitBondUpdater bit set, +// which indicates the wallet implements the BondUpdater interface. +func (wt WalletTrait) IsBondUpdater() bool { + return wt&WalletTraitBondUpdater != 0 +} + // DetermineWalletTraits returns the WalletTrait bitset for the provided Wallet. func DetermineWalletTraits(w Wallet) (t WalletTrait) { if _, is := w.(Rescanner); is { @@ -201,6 +208,9 @@ func DetermineWalletTraits(w Wallet) (t WalletTrait) { if _, is := w.(FundsMixer); is { t |= WalletTraitFundsMixer } + if _, is := w.(BondUpdater); is { + t |= WalletTraitBondUpdater + } return t } @@ -614,6 +624,8 @@ type Bonder interface { // RefundBond will refund the bond given the full bond output details and // private key to spend it. The bond is broadcasted. RefundBond(ctx context.Context, ver uint16, coinID, script []byte, amt uint64, privKey *secp256k1.PrivateKey) (Coin, error) + // BondConfirmations gets the numer of confirmations since the creation of a bond. + BondConfirmations(ctx context.Context, coinID dex.Bytes) (confs uint32, err error) // A RefundBondByCoinID may be created in the future to attempt to refund a // bond by locating it on chain, i.e. without providing the amount or @@ -624,6 +636,32 @@ type Bonder interface { // required for efficient client bond management. } +// BondUpdater is a wallet that can use the values of existing bonds to create +// new bonds with a longer lockTime. Wallets that support this do not need to +// reserve funds in order to maintain a certain tier, because bonds can be +// extended before they expire. +type BondUpdater interface { + Bonder + + // UpdateBondTx creates an unsigned transaction that uses the funds locked + // in one or more bonds to create a new bond with a longer lockTime. If the + // total value of the bonds is greater than the new bond, a "change" bond + // will be created with the remaining funds and the same lockTime as the + // earliest expiring bond. If two bonds are being created, the "change" + // bond will be the first in the returned []*asset.Bond slice. + // + // Requirements: + // - The correct amount of privKeys must be passed, depending on whether + // or not a change bond is needed. The first will be used for the + // change bond. + // - The lockTime must be later than the latest lockTime of the + // bondsToUpdate. + // - The value of the earliest expiring bond must be greater than the + // "change" bond value. + // - The bondsToUpdate must all be from the same account. + UpdateBondTx(ver uint16, bondsToUpdate []dex.Bytes, privKeys []*secp256k1.PrivateKey, amt uint64, lockTime time.Time) ([]*Bond, error) +} + // Rescanner is a wallet implementation with rescan functionality. type Rescanner interface { Rescan(ctx context.Context) error @@ -1083,6 +1121,7 @@ const ( TicketPurchase TicketVote TicketRevocation + UpdateBond ) // IncomingTxType returns true if the wallet's balance increases due to a @@ -1091,15 +1130,20 @@ func IncomingTxType(txType TransactionType) bool { return txType == Receive || txType == Redeem || txType == Refund || txType == RedeemBond } -// BondTxInfo contains information about a CreateBond or RedeemBond -// transaction. +type BondInfo struct { + ID string `json:"id"` + Amount uint64 `json:"amount"` + LockTime uint64 `json:"lockTime"` +} + +// BondTxInfo contains information about a CreateBond, RedeemBond, or +// UpdateBond transaction. type BondTxInfo struct { // AccountID is the account is the account ID that the bond is applied to. - AccountID dex.Bytes `json:"accountID"` - // LockTime is the time until which the bond is locked. - LockTime uint64 `json:"lockTime"` - // BondID is the ID of the bond. - BondID dex.Bytes `json:"bondID"` + AccountID dex.Bytes `json:"accountID"` + Bond *BondInfo `json:"bond"` + ChangeBond *BondInfo `json:"changeBond"` + ReplacedBonds []*BondInfo `json:"replacedBond"` } // WalletTransaction represents a transaction that was made by a wallet. @@ -1144,11 +1188,12 @@ type WalletHistorian interface { // the corresponding signed transaction, and a final request is made once the // bond is fully confirmed. The caller should manage the private key. type Bond struct { - Version uint16 - AssetID uint32 - Amount uint64 - CoinID []byte - Data []byte // additional data to interpret the bond e.g. redeem script, bond contract, etc. + Version uint16 + AssetID uint32 + Amount uint64 + CoinID []byte + LockTime uint64 + Data []byte // additional data to interpret the bond e.g. redeem script, bond contract, etc. // SignedTx and UnsignedTx are the opaque (raw bytes) signed and unsigned // bond creation transactions, in whatever encoding and funding scheme for // this asset and wallet. The unsigned one is used to pre-validate this bond @@ -1159,6 +1204,10 @@ type Bond struct { // RedeemTx is a backup transaction that spends the bond output. Normally // the a key index will be used to derive the key when the bond expires. RedeemTx []byte + + // ReplacedBy is set to the CoinID of the bond that has replaced this bond, + // if any. + ReplacedBy dex.Bytes } // ShieldedStatus is the balance and address associated with the shielded diff --git a/client/cmd/dexc-desktop/app_darwin.go b/client/cmd/dexc-desktop/app_darwin.go index 6e03607316..6f801e7bad 100644 --- a/client/cmd/dexc-desktop/app_darwin.go +++ b/client/cmd/dexc-desktop/app_darwin.go @@ -244,7 +244,6 @@ func mainCore() error { <-clientCore.Ready() var marketMaker *mm.MarketMaker - var mmCM *dex.ConnectionMaster if cfg.Experimental { // TODO: on shutdown, stop market making and wait for trades to be // canceled. diff --git a/client/core/core_test.go b/client/core/core_test.go index 0f6a6d8ba5..afa66d6e55 100644 --- a/client/core/core_test.go +++ b/client/core/core_test.go @@ -1097,6 +1097,10 @@ func (*TXCWallet) FundMultiOrder(ord *asset.MultiOrder, maxLock uint64) (coins [ var _ asset.Bonder = (*TXCWallet)(nil) +func (*TXCWallet) BondConfirmations(ctx context.Context, id dex.Bytes) (confs uint32, err error) { + return 0, nil +} + func (*TXCWallet) BondsFeeBuffer(feeRate uint64) uint64 { return 4 * 1000 * feeRate * 2 } diff --git a/dex/networks/eth/bond.go b/dex/networks/eth/bond.go index 95fa38ba4f..e0a970c950 100644 --- a/dex/networks/eth/bond.go +++ b/dex/networks/eth/bond.go @@ -41,7 +41,7 @@ func PackCreateBondTx(accountID [32]byte, bondID [32]byte, locktime uint64) ([]b return BondABI.Pack("createBond", accountID, bondID, locktime) } -func ParseCreateBondTx(data []byte) (accountID [32]byte, id [32]byte, locktime uint64, err error) { +func ParseCreateBondTx(data []byte) (accountID, bondID [32]byte, locktime uint64, err error) { decoded, err := ParseCallData(data, BondABI) if err != nil { return [32]byte{}, [32]byte{}, 0, err @@ -63,9 +63,9 @@ func ParseCreateBondTx(data []byte) (accountID [32]byte, id [32]byte, locktime u return [32]byte{}, [32]byte{}, 0, fmt.Errorf("expected [32]byte for accountID, got %T", args[0].value) } - id, ok = args[1].value.([32]byte) + bondID, ok = args[1].value.([32]byte) if !ok { - return [32]byte{}, [32]byte{}, 0, fmt.Errorf("expected [32]byte for id, got %T", args[1].value) + return [32]byte{}, [32]byte{}, 0, fmt.Errorf("expected [32]byte for bondID, got %T", args[1].value) } locktime, ok = args[2].value.(uint64) @@ -73,14 +73,14 @@ func ParseCreateBondTx(data []byte) (accountID [32]byte, id [32]byte, locktime u return [32]byte{}, [32]byte{}, 0, fmt.Errorf("expected uint64 for locktime, got %T", args[2].value) } - return accountID, id, locktime, nil + return accountID, bondID, locktime, nil } func PackUpdateBondsTx(accountID [32]byte, bondsToUpdate [][32]byte, newBondIDs [][32]byte, value *big.Int, locktime uint64) ([]byte, error) { return BondABI.Pack("updateBonds", accountID, bondsToUpdate, newBondIDs, value, locktime) } -func ParseUpdateBondsTx(data []byte) (accountID [32]byte, bondsToUpdate [][32]byte, newBondIDs [][32]byte, value *big.Int, locktime uint64, err error) { +func ParseUpdateBondsTx(data []byte) (accountID [32]byte, bondsToUpdate, newBondIDs [][32]byte, value *big.Int, locktime uint64, err error) { decoded, err := ParseCallData(data, BondABI) if err != nil { return [32]byte{}, nil, nil, nil, 0, err diff --git a/dex/networks/eth/bondcontracts/v0/package-lock.json b/dex/networks/eth/bondcontracts/v0/package-lock.json index 4e592ecb1f..620821f1e4 100644 --- a/dex/networks/eth/bondcontracts/v0/package-lock.json +++ b/dex/networks/eth/bondcontracts/v0/package-lock.json @@ -5713,6 +5713,7 @@ "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz", "integrity": "sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A==", "dev": true, + "hasInstallScript": true, "optional": true, "peer": true, "dependencies": { @@ -6101,6 +6102,7 @@ "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz", "integrity": "sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q==", "dev": true, + "hasInstallScript": true, "optional": true, "peer": true, "dependencies": { diff --git a/dex/testing/eth/harness.sh b/dex/testing/eth/harness.sh index dff04c2a13..a53fee17f3 100755 --- a/dex/testing/eth/harness.sh +++ b/dex/testing/eth/harness.sh @@ -291,20 +291,7 @@ MULTIBALANCE_CONTRACT_HASH=$("${NODES_ROOT}/harness-ctl/alpha" "attach --preload echo "Deploying Bond contract." BOND_CONTRACT_HASH=$("${NODES_ROOT}/harness-ctl/alpha" "attach --preload ${NODES_ROOT}/harness-ctl/deploy.js --exec deploy(\"${ALPHA_ADDRESS}\",\"${BOND_V0}\")" | sed 's/"//g') - -# Initial sync for light nodes takes quite a while. Wait for them to show -# blocks on the network. -while true -do - N=$("${NODES_ROOT}/harness-ctl/gamma" "attach --exec eth.blockNumber") - if [ "$N" -gt 0 ]; then - break - fi - echo "Waiting for light nodes to sync." - # Although not necessary here, mine while waiting so that transactions are - # mined if not mined yet. - "${NODES_ROOT}/harness-ctl/mine-beta" "5" -done +echo "Bond contract hash is ${BOND_CONTRACT_HASH}. Saving to ${NODES_ROOT}/bond_contract_hash.txt" mine_pending_txs() { while true From 9b0ab19e247ac31258fd250ec349b26fd62ba153 Mon Sep 17 00:00:00 2001 From: martonp Date: Thu, 8 Feb 2024 15:18:57 -0500 Subject: [PATCH 3/6] client/core: Support wallets that implement 'BondUpdater` This updates the client to support wallets that implement `BondUpdater`. In `rotateBonds`, if an account is set to maintain a certain tier, and it already has some weak or expired bonds posted in an asset that supports updating bonds, it will use the funds in those bonds to create a new bond with a sufficiently long lockTime. --- client/core/bond.go | 288 +++++++++++++++++++++++++++--- client/core/core.go | 2 +- client/core/core_test.go | 376 +++++++++++++++++++++++++++++++++++++-- client/core/wallet.go | 21 +++ client/db/bolt/db.go | 37 ++++ client/db/interface.go | 2 + client/db/types.go | 20 ++- 7 files changed, 700 insertions(+), 46 deletions(-) diff --git a/client/core/bond.go b/client/core/bond.go index df695c558d..02a1bffb28 100644 --- a/client/core/bond.go +++ b/client/core/bond.go @@ -7,6 +7,8 @@ import ( "fmt" "math" "sort" + "strconv" + "strings" "time" "decred.org/dcrdex/client/asset" @@ -235,6 +237,7 @@ func (c *Core) updateBondReserves(balanceCheckID ...uint32) { // asset. n := uint64(len(bondValues)) feeReserves := n * bonder.BondsFeeBuffer(c.feeSuggestionAny(w.AssetID)) + // Even if reserves are 0, we may still want to reserve fees for // renewing bonds. paddedReserves := nominalReserves + feeReserves @@ -254,6 +257,7 @@ func (c *Core) updateBondReserves(balanceCheckID ...uint32) { paddedReserves, unbip(w.AssetID), avail) } } + bonder.SetBondReserves(paddedReserves) } } @@ -370,20 +374,21 @@ func (c *Core) dexBondConfig(dc *dexConnection, now int64) *dexBondCfg { type dexAcctBondState struct { ExchangeAuth - repost []*asset.Bond - mustPost int64 // includes toComp - toComp int64 - inBonds uint64 + repost []*asset.Bond + mustPost int64 // includes toComp + toComp int64 + inBonds uint64 + weakBonds, strongBonds []*db.Bond } -// bondStateOfDEX collects all the information needed to determine what -// bonds need to be refunded and how much new bonds should be posted. func (c *Core) bondStateOfDEX(dc *dexConnection, bondCfg *dexBondCfg) *dexAcctBondState { dc.acct.authMtx.Lock() defer dc.acct.authMtx.Unlock() state := new(dexAcctBondState) - weakBonds := make([]*db.Bond, 0, len(dc.acct.bonds)) + + state.weakBonds = make([]*db.Bond, 0, len(dc.acct.bonds)) + state.strongBonds = make([]*db.Bond, 0, len(dc.acct.bonds)) filterExpiredBonds := func(bonds []*db.Bond) (liveBonds []*db.Bond) { for _, bond := range bonds { @@ -395,9 +400,11 @@ func (c *Core) bondStateOfDEX(dc *dexConnection, bondCfg *dexBondCfg) *dexAcctBo c.log.Infof("Newly expired bond found: %v (%s)", coinIDString(bond.AssetID, bond.CoinID), unbip(bond.AssetID)) } else { if int64(bond.LockTime) <= bondCfg.replaceThresh { - weakBonds = append(weakBonds, bond) // but not yet expired (still live or pending) + state.weakBonds = append(state.weakBonds, bond) // but not yet expired (still live or pending) c.log.Infof("Soon to expire bond found: %v (%s)", coinIDString(bond.AssetID, bond.CoinID), unbip(bond.AssetID)) + } else { + state.strongBonds = append(state.strongBonds, bond) } liveBonds = append(liveBonds, bond) } @@ -412,7 +419,7 @@ func (c *Core) bondStateOfDEX(dc *dexConnection, bondCfg *dexBondCfg) *dexAcctBo dc.acct.bonds = filterExpiredBonds(dc.acct.bonds) dc.acct.pendingBonds = filterExpiredBonds(dc.acct.pendingBonds) // possibly expired before confirmed state.PendingStrength = sumBondStrengths(dc.acct.pendingBonds, bondCfg.bondAssets) - state.WeakStrength = sumBondStrengths(weakBonds, bondCfg.bondAssets) + state.WeakStrength = sumBondStrengths(state.weakBonds, bondCfg.bondAssets) state.LiveStrength = sumBondStrengths(dc.acct.bonds, bondCfg.bondAssets) // for max bonded check state.PendingBonds = dc.pendingBonds() // Extract the expired bonds. @@ -473,6 +480,10 @@ func (c *Core) refundExpiredBonds(ctx context.Context, acct *dexAccount, cfg *de assetIDs := make(map[uint32]struct{}) for _, bond := range state.ExpiredBonds { + if bond.ReplacedBy != nil { + continue + } + bondIDStr := fmt.Sprintf("%v (%s)", coinIDString(bond.AssetID, bond.CoinID), unbip(bond.AssetID)) if now < int64(bond.LockTime) { ttr := time.Duration(int64(bond.LockTime)-now) * time.Second @@ -617,6 +628,216 @@ func (c *Core) repostPendingBonds(dc *dexConnection, cfg *dexBondCfg, state *dex } } +func bondsForAsset(state *dexAcctBondState, assetID uint32) (weakAndExpired []*db.Bond, strong []*db.Bond) { + weakAndExpired = make([]*db.Bond, 0, len(state.weakBonds)+len(state.ExpiredBonds)) + strong = make([]*db.Bond, 0, len(state.strongBonds)) + + for _, b := range state.weakBonds { + if b.AssetID == assetID { + weakAndExpired = append(weakAndExpired, b) + } + } + for _, b := range state.ExpiredBonds { + if b.AssetID == assetID { + weakAndExpired = append(weakAndExpired, b) + } + } + for _, b := range state.strongBonds { + if b.AssetID == assetID { + strong = append(strong, b) + } + } + + return +} + +func (c *Core) updateBonds(dc *dexConnection, cfg *dexBondCfg, state *dexAcctBondState, wallet *xcWallet, unlocked bool) (bool, error) { + if state.TargetTier == 0 || state.mustPost <= 0 || cfg.bondExpiry <= 0 { + return false, nil + } + + bondAsset := cfg.bondAssets[state.BondAssetID] + if bondAsset == nil { + return false, nil + } + + weakAndExpired, strong := bondsForAsset(state, state.BondAssetID) + bondsToUpdate := make([]*db.Bond, 0, len(state.strongBonds)+len(state.weakBonds)+len(state.ExpiredBonds)) + lockDur := minBondLifetime(c.net, cfg.bondExpiry) + lockTime := time.Now().Add(lockDur).Truncate(time.Second) + + // Always include strong bonds that expire prior to the lockTime. + var strongBondAmt uint64 + for _, bond := range strong { + if bond.LockTime < uint64(lockTime.Unix()) { + bondsToUpdate = append(bondsToUpdate, bond) + strongBondAmt += bond.Amount + } + } + + mustPostAmt := uint64(state.mustPost) * bondAsset.Amt + + // Include weak/expired bonds until the mustPost amount is reached. + // Prefer bonds that expire later. + sort.Slice(weakAndExpired, func(i, j int) bool { + return weakAndExpired[i].LockTime > weakAndExpired[j].LockTime + }) + var reusedBondedAmt uint64 + for _, bond := range weakAndExpired { + bondsToUpdate = append(bondsToUpdate, bond) + reusedBondedAmt += bond.Amount + if reusedBondedAmt >= mustPostAmt { + break + } + } + + // If there are no bonds to update, then a new bond must be created. + if len(bondsToUpdate) == 0 { + return false, nil + } + + var additionalAmtRequired uint64 + if reusedBondedAmt < mustPostAmt { + additionalAmtRequired = mustPostAmt - reusedBondedAmt + } + + amtToPost := additionalAmtRequired + + // Make sure we're not posting more than MaxBondedAmt + if state.MaxBondedAmt > 0 { + expiredStrength := sumBondStrengths(state.ExpiredBonds, cfg.bondAssets) + currentlyBondedAmt := uint64(state.PendingStrength+state.LiveStrength+expiredStrength) * bondAsset.Amt + if currentlyBondedAmt >= state.MaxBondedAmt { + // If greater then something went wrong... + amtToPost = 0 + } else if currentlyBondedAmt+amtToPost > state.MaxBondedAmt { + amtToPost = state.MaxBondedAmt - currentlyBondedAmt + } + } + amtToPost = amtToPost / bondAsset.Amt * bondAsset.Amt // round down to nearest bond size + + // Make sure the new bond is not larger than we need + newBondSize := reusedBondedAmt + strongBondAmt + amtToPost + totalRequired := strongBondAmt + uint64(state.mustPost)*bondAsset.Amt + if totalRequired < newBondSize { + newBondSize = totalRequired + } + + bondKeys := make([]*secp256k1.PrivateKey, 0, 2) + keyIndexes := make([]uint32, 0, 2) + + // Will always create at least one new bond. + bondKey, keyIndex, err := c.nextBondKey(bondAsset.ID) + defer bondKey.Zero() + if err != nil { + return false, err + } + bondKeys = append(bondKeys, bondKey) + keyIndexes = append(keyIndexes, keyIndex) + + // If we reusing more than the size of the new bond, we need + // a "change" bond. + if reusedBondedAmt+strongBondAmt > newBondSize { + bondKey, keyIndex, err := c.nextBondKey(bondAsset.ID) + defer bondKey.Zero() + if err != nil { + return false, err + } + bondKeys = append(bondKeys, bondKey) + keyIndexes = append(keyIndexes, keyIndex) + } + + bondIDsToUpdate := make([]dex.Bytes, 0, len(bondsToUpdate)) + for _, bond := range bondsToUpdate { + bondIDsToUpdate = append(bondIDsToUpdate, bond.CoinID) + } + + newBonds, err := wallet.UpdateBondTx(bondAsset.Version, bondIDsToUpdate, bondKeys, newBondSize, lockTime) + if err != nil { + return false, codedError(bondPostErr, err) + } + + nonChangeBond := newBonds[0] + if len(newBonds) == 2 { + nonChangeBond = newBonds[1] + } + err = c.preValidateBond(dc, nonChangeBond) + if err != nil { + return false, err + } + + newDBBonds := make([]*db.Bond, 0, len(newBonds)+len(bondsToUpdate)) + var replacementBondID dex.Bytes + for i, bond := range newBonds { + newDBBonds = append(newDBBonds, &db.Bond{ + Version: bond.Version, + AssetID: bond.AssetID, + CoinID: bond.CoinID, + UnsignedTx: bond.UnsignedTx, + SignedTx: bond.SignedTx, + Data: bond.Data, + Amount: bond.Amount, + LockTime: bond.LockTime, + KeyIndex: keyIndexes[i], + RefundTx: bond.RedeemTx, + }) + replacementBondID = bond.CoinID + } + for _, updatedBond := range bondsToUpdate { + updatedBond.ReplacedBy = replacementBondID + newDBBonds = append(newDBBonds, updatedBond) + } + + err = c.db.AddBonds(dc.acct.host, newDBBonds) + if err != nil { + return false, err + } + + removeBond := func(bondsList *[]*db.Bond, coinID dex.Bytes) bool { + list := *bondsList + for i, bond := range list { + if bytes.Equal(bond.CoinID, coinID) { + newList := append(list[:i], list[i+1:]...) + *bondsList = newList + return true + } + } + return false + } + + // Add the newly created bond(s) to pendingBonds, and remove the replaced bonds. + dc.acct.authMtx.Lock() + for i, bond := range newDBBonds { + if i < len(newBonds) { + dc.acct.pendingBonds = append(dc.acct.pendingBonds, bond) + } else { + if !(removeBond(&dc.acct.bonds, bond.CoinID) || removeBond(&dc.acct.pendingBonds, bond.CoinID) || removeBond(&dc.acct.expiredBonds, bond.CoinID)) { + c.log.Warnf("Failed to remove replaced bond %s from account", bond.CoinID) + } + } + } + dc.acct.authMtx.Unlock() + + if txCast, err := wallet.SendTransaction(newBonds[0].SignedTx); err != nil { + c.log.Warnf("Failed to broadcast update bond tx (%v). Tx bytes: %x", err, newBonds[0].SignedTx) + } else { + c.log.Infof("Broadcasted update bond tx %v", txCast) + } + + c.updateAssetBalance(state.BondAssetID) + + for _, bond := range newBonds { + bondCoinStr := coinIDString(bond.AssetID, bond.CoinID) + details := fmt.Sprintf("Waiting for %d confirmations to post bond %v (%s) to %s", + bondAsset.Confs, bondCoinStr, unbip(bond.AssetID), dc.acct.host) // TODO: subject, detail := c.formatDetails(...) + c.notify(newBondPostNoteWithConfirmations(TopicBondConfirming, string(TopicBondConfirming), + details, db.Success, bond.AssetID, bondCoinStr, 0, dc.acct.host, &state.ExchangeAuth)) + c.monitorBondConfs(dc, bond, bondAsset.Confs) + } + + return true, nil +} + // postRequiredBonds posts any required bond increments for a dexConnection. func (c *Core) postRequiredBonds( dc *dexConnection, @@ -708,9 +929,24 @@ func (c *Core) rotateBonds(ctx context.Context) { bondCfg := c.dexBondConfig(dc, now) acctBondState := c.bondStateOfDEX(dc, bondCfg) - c.repostPendingBonds(dc, bondCfg, acctBondState, unlocked) + wallet, err := c.connectedWallet(acctBondState.BondAssetID) + if err != nil { + if acctBondState.TargetTier > 0 { + c.log.Errorf("%v wallet not available for bonds: %v", unbip(acctBondState.BondAssetID), err) + } + continue + } + + var updatePerformed bool + if _, isUpdater := wallet.Wallet.(asset.BondUpdater); isUpdater { + updatePerformed, err = c.updateBonds(dc, bondCfg, acctBondState, wallet, unlocked) + if err != nil { + c.log.Errorf("Error while trying to update bonds for %v: %v", dc.acct.host, err) + } + } + refundedAssets, expiredStrength, err := c.refundExpiredBonds(ctx, dc.acct, bondCfg, acctBondState, now) if err != nil { c.log.Errorf("Failed to refund expired bonds for %v: %v", dc.acct.host, err) @@ -728,15 +964,9 @@ func (c *Core) rotateBonds(ctx context.Context) { continue } - wallet, err := c.connectedWallet(acctBondState.BondAssetID) - if err != nil { - if acctBondState.TargetTier > 0 { - c.log.Errorf("%v wallet not available for bonds: %v", unbip(acctBondState.BondAssetID), err) - } - continue + if !updatePerformed { + c.postRequiredBonds(dc, bondCfg, acctBondState, bondAsset, wallet, expiredStrength, unlocked) } - - c.postRequiredBonds(dc, bondCfg, acctBondState, bondAsset, wallet, expiredStrength, unlocked) } c.updateBondReserves() @@ -780,6 +1010,8 @@ func (c *Core) preValidateBond(dc *dexConnection, bond *asset.Bond) error { return nil } +var errAlreadyConfirming = fmt.Errorf("bond already confirming") + func (c *Core) postBond(dc *dexConnection, bond *asset.Bond) (*msgjson.PostBondResult, error) { if len(dc.acct.encKey) == 0 { return nil, fmt.Errorf("uninitialized account") @@ -804,6 +1036,9 @@ func (c *Core) postBond(dc *dexConnection, bond *asset.Bond) (*msgjson.PostBondR postBondRes := new(msgjson.PostBondResult) err := dc.signAndRequest(postBond, msgjson.PostBondRoute, postBondRes, DefaultResponseTimeout) if err != nil { + if strings.Contains(err.Error(), strconv.Itoa(msgjson.BondAlreadyConfirmingError)) { + return nil, errAlreadyConfirming + } return nil, codedError(registerErr, err) } @@ -834,6 +1069,11 @@ func (c *Core) postAndConfirmBond(dc *dexConnection, bond *asset.Bond) { // bond will be active (and account created if new) and we should confirm // the bond (in DB and dc.acct.{bond,pendingBonds}). pbr, err := c.postBond(dc, bond) // can be long while server searches + if errors.Is(err, errAlreadyConfirming) { + // No need for error notification if is server still confirming. + c.log.Warnf("Still waiting for server to confirm bond: %s", coinIDStr) + return + } if err != nil { subject, details := c.formatDetails(TopicBondPostError, err, err) c.notify(newBondPostNote(TopicBondPostError, subject, details, db.ErrorLevel, dc.acct.host)) @@ -861,7 +1101,8 @@ func (c *Core) monitorBondConfs(dc *dexConnection, bond *asset.Bond, reqConfs ui c.log.Errorf("No connected wallet for asset %v: %v", unbip(assetID), err) return } - lastConfs, err := wallet.RegFeeConfirmations(c.ctx, coinID) + + lastConfs, err := wallet.BondConfirmations(c.ctx, coinID) coinNotFound := errors.Is(err, asset.CoinNotFoundError) if err != nil && !coinNotFound { c.log.Errorf("Error getting confirmations for %s: %w", coinIDStr, err) @@ -892,7 +1133,7 @@ func (c *Core) monitorBondConfs(dc *dexConnection, bond *asset.Bond, reqConfs ui trigger := func() (bool, error) { // Retrieve the current wallet in case it was reconfigured. wallet, _ := c.wallet(assetID) // We already know the wallet is there by now. - confs, err := wallet.RegFeeConfirmations(c.ctx, coinID) + confs, err := wallet.BondConfirmations(c.ctx, coinID) if err != nil && !errors.Is(err, asset.CoinNotFoundError) { return false, fmt.Errorf("Error getting confirmations for %s: %w", coinIDStr, err) } @@ -1530,16 +1771,15 @@ func (c *Core) makeAndPostBond(dc *dexConnection, acctExists bool, wallet *xcWal coinIDString(bond.AssetID, bondCoinCast), bondCoinStr) } - // Set up the coin waiter, which watches confirmations so the user knows - // when to expect their account to be marked paid by the server. - c.monitorBondConfs(dc, bond, reqConfs) - c.updateAssetBalance(bond.AssetID) // Start waiting for reqConfs. subject, details := c.formatDetails(TopicBondConfirming, reqConfs, makeCoinIDToken(bondCoinStr, bond.AssetID), unbip(bond.AssetID), dc.acct.host) c.notify(newBondPostNoteWithConfirmations(TopicBondConfirming, subject, details, db.Success, bond.AssetID, bondCoinStr, 0, dc.acct.host, c.exchangeAuth(dc))) + // Set up the coin waiter, which watches confirmations so the user knows + // when to expect their account to be marked paid by the server. + c.monitorBondConfs(dc, bond, reqConfs) return bond.CoinID, nil } diff --git a/client/core/core.go b/client/core/core.go index 493d3ca08f..6dac0ebdc5 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -8469,7 +8469,7 @@ func (c *Core) startDexConnection(acctInfo *db.AccountInfo, dc *dexConnection) e defer dc.acct.authMtx.Unlock() for _, dbBond := range acctInfo.Bonds { - if dbBond.Refunded { // maybe don't even load these, but it may be of use for record keeping + if dbBond.Refunded || dbBond.ReplacedBy != nil { // maybe don't even load these, but it may be of use for record keeping continue } diff --git a/client/core/core_test.go b/client/core/core_test.go index afa66d6e55..f9fe4ea077 100644 --- a/client/core/core_test.go +++ b/client/core/core_test.go @@ -365,6 +365,7 @@ type TDB struct { acctErr error createAccountErr error addBondErr error + addBondsErr error storeAccountProofErr error updateOrderErr error activeDEXOrders []*db.MetaOrder @@ -429,6 +430,10 @@ func (tdb *TDB) AddBond(host string, bond *db.Bond) error { return tdb.addBondErr } +func (tdb *TDB) AddBonds(host string, bonds []*db.Bond) error { + return tdb.addBondsErr +} + func (tdb *TDB) ConfirmBond(host string, assetID uint32, bondCoinID []byte) error { return nil } @@ -648,6 +653,7 @@ func (r *tReceipt) SignedRefund() dex.Bytes { } type TXCWallet struct { + assetID uint32 swapSize uint64 sendFeeSuggestion uint64 sendCoin *tCoin @@ -700,6 +706,7 @@ type TXCWallet struct { feeCoin []byte makeRegFeeTxErr error feeCoinSent []byte + sentRawTransaction []byte sendTxnErr error contractExpired bool contractLockTime time.Time @@ -721,9 +728,11 @@ type TXCWallet struct { bondTxCoinID []byte refundBondCoin asset.Coin refundBondErr error + makeBondTxRes *asset.Bond makeBondTxErr error reserves atomic.Uint64 + refundBondCoinParam dex.Bytes confirmRedemptionResult *asset.ConfirmRedemptionStatus confirmRedemptionErr error confirmRedemptionCalled bool @@ -754,6 +763,7 @@ func newTWallet(assetID uint32) (*xcWallet, *TXCWallet) { SupportedVersions: []uint32{0}, }, bondTxCoinID: encode.RandomBytes(32), + assetID: assetID, } var broadcasting uint32 = 1 xcWallet := &xcWallet{ @@ -946,6 +956,7 @@ func (w *TXCWallet) Send(address string, value, feeSuggestion uint64) (asset.Coi } func (w *TXCWallet) SendTransaction(rawTx []byte) ([]byte, error) { + w.sentRawTransaction = rawTx return w.feeCoinSent, w.sendTxnErr } @@ -1097,8 +1108,8 @@ func (*TXCWallet) FundMultiOrder(ord *asset.MultiOrder, maxLock uint64) (coins [ var _ asset.Bonder = (*TXCWallet)(nil) -func (*TXCWallet) BondConfirmations(ctx context.Context, id dex.Bytes) (confs uint32, err error) { - return 0, nil +func (w *TXCWallet) BondConfirmations(ctx context.Context, id dex.Bytes) (confs uint32, err error) { + return w.tConfirmations(ctx, id) } func (*TXCWallet) BondsFeeBuffer(feeRate uint64) uint64 { @@ -1117,6 +1128,9 @@ func (w *TXCWallet) MakeBondTx(ver uint16, amt, feeRate uint64, lockTime time.Ti if w.makeBondTxErr != nil { return nil, nil, w.makeBondTxErr } + if w.makeBondTxRes != nil { + return w.makeBondTxRes, func() {}, nil + } return &asset.Bond{ Version: ver, AssetID: dcrBondAsset.ID, @@ -1129,6 +1143,8 @@ func (w *TXCWallet) TransactionConfirmations(ctx context.Context, txID string) ( return 0, nil } +var _ asset.Bonder = (*TXCWallet)(nil) + type TAccountLocker struct { *TXCWallet reserveNRedemptions uint64 @@ -1153,6 +1169,46 @@ func newTAccountLocker(assetID uint32) (*xcWallet, *TAccountLocker) { return xcWallet, accountLocker } +type TUpdateBonder struct { + *TXCWallet + lastUpdateBondTxParams *updateBondParams + updateBondTxRes []*asset.Bond + updateBondTxErr error +} + +var _ asset.BondUpdater = (*TUpdateBonder)(nil) + +func newTUpdateBonder(assetID uint32) (*xcWallet, *TUpdateBonder) { + xcWallet, tWallet := newTWallet(assetID) + updateBonder := &TUpdateBonder{TXCWallet: tWallet} + xcWallet.Wallet = updateBonder + return xcWallet, updateBonder +} + +type updateBondParams struct { + ver uint16 + bonds []dex.Bytes + privKeys []*secp256k1.PrivateKey + amt uint64 + lockTime time.Time +} + +func (w *TUpdateBonder) UpdateBondTx(ver uint16, bondsToUpdate []dex.Bytes, privKeys []*secp256k1.PrivateKey, amt uint64, lockTime time.Time) ([]*asset.Bond, error) { + if w.updateBondTxErr != nil { + return nil, w.updateBondTxErr + } + + w.lastUpdateBondTxParams = &updateBondParams{ + ver: ver, + bonds: bondsToUpdate, + privKeys: privKeys, + amt: amt, + lockTime: lockTime, + } + + return w.updateBondTxRes, nil +} + func (w *TAccountLocker) ReserveNRedemptions(n uint64, ver uint32, maxFeeRate uint64) (uint64, error) { return w.reserveNRedemptions, w.reserveNRedemptionsErr } @@ -1416,19 +1472,21 @@ func (rig *testRig) queueRegister(regRes *msgjson.RegisterResult) { }) } -func (rig *testRig) queuePrevalidateBond() { +func (rig *testRig) queuePrevalidateBond(res *msgjson.PreValidateBondResult) { rig.ws.queueResponse(msgjson.PreValidateBondRoute, func(msg *msgjson.Message, f msgFunc) error { preEval := new(msgjson.PreValidateBond) msg.Unmarshal(preEval) - preEvalResult := &msgjson.PreValidateBondResult{ - AccountID: rig.dc.acct.id[:], - AssetID: preEval.AssetID, - Amount: dcrBondAsset.Amt, - // Expiry: , + if res == nil { + res = &msgjson.PreValidateBondResult{ + AccountID: rig.dc.acct.id[:], + AssetID: preEval.AssetID, + Amount: dcrBondAsset.Amt, + // Expiry: , + } } - sign(tDexPriv, preEvalResult) - resp, _ := msgjson.NewResponse(msg.ID, preEvalResult, nil) + sign(tDexPriv, res) + resp, _ := msgjson.NewResponse(msg.ID, res, nil) f(resp) return nil }) @@ -2114,7 +2172,7 @@ func TestPostBond(t *testing.T) { } queuePostBondSequence := func() { - rig.queuePrevalidateBond() + rig.queuePrevalidateBond(nil) rig.queuePostBond(postBondResult) queueTipChange() rig.queueNotifyFee() @@ -10759,14 +10817,14 @@ func TestRotateBonds(t *testing.T) { acct.maxBondedAmt = maxBondedPerTier * targetTier acct.bondAsset = bondAsset.ID tDcrWallet.bal = &asset.Balance{Available: bondAsset.Amt*targetTier + bondFeeBuffer} - rig.queuePrevalidateBond() + rig.queuePrevalidateBond(nil) run(1, 0, bondAsset.Amt+bondFeeBuffer) // Post and then expire the bond. This first bond should move to expired and we // should create another bond. acct.bonds, acct.pendingBonds = acct.pendingBonds, nil acct.bonds[0].LockTime = locktimeExpired - rig.queuePrevalidateBond() + rig.queuePrevalidateBond(nil) // The newly expired bond will be refunded in time to fund our next round, // so we only need fees reserved. run(1, 1, bondFeeBuffer) @@ -10780,7 +10838,7 @@ func TestRotateBonds(t *testing.T) { // Make the live bond weak. Should get a pending bond. Only fees reserves, // because we still have an expired bond. acct.bonds[0].LockTime = weakTimeThresh - 1 - rig.queuePrevalidateBond() + rig.queuePrevalidateBond(nil) run(1, 1, bondFeeBuffer) // Refund the expired bond @@ -10791,7 +10849,7 @@ func TestRotateBonds(t *testing.T) { acct.targetTier = 2 acct.bonds = nil - rig.queuePrevalidateBond() + rig.queuePrevalidateBond(nil) run(2, 0, bondAsset.Amt*2+bondFeeBuffer) // Check that a new bond will be scheduled for merge with an existing bond @@ -10799,7 +10857,7 @@ func TestRotateBonds(t *testing.T) { acct.bonds = append(acct.bonds, acct.pendingBonds[0]) acct.pendingBonds = nil acct.bonds[0].LockTime = mergeableLocktimeThresh + 5 - rig.queuePrevalidateBond() + rig.queuePrevalidateBond(nil) run(1, 0, 2*bondAsset.Amt+bondFeeBuffer) mergingBond := acct.pendingBonds[0] if mergingBond.LockTime != acct.bonds[0].LockTime { @@ -10809,10 +10867,294 @@ func TestRotateBonds(t *testing.T) { // Same thing, but without the merge, just to check our threshold calc. acct.pendingBonds = nil acct.bonds[0].LockTime = mergeableLocktimeThresh - 1 - rig.queuePrevalidateBond() + rig.queuePrevalidateBond(nil) run(1, 0, 2*bondAsset.Amt+bondFeeBuffer) unmergingBond := acct.pendingBonds[0] if unmergingBond.LockTime == acct.bonds[0].LockTime { t.Fatalf("Unmergeable bond was scheduled for merged") } } + +func TestRotateBondsUpdater(t *testing.T) { + bondAmt := uint64(1e7) + + bondAssets := map[string]*msgjson.BondAsset{ + tUTXOAssetA.Symbol: { + Version: 0, + ID: tUTXOAssetA.ID, + Confs: 2, + Amt: bondAmt, + }, + tUTXOAssetB.Symbol: { + Version: 0, + ID: tUTXOAssetB.ID, + Confs: 2, + Amt: bondAmt / 2, + }, + } + + bondIDs := make([]dex.Bytes, 0, 6) + for i := 0; i < 6; i++ { + bondIDs = append(bondIDs, encode.RandomBytes(32)) + } + + newBond := func(assetID uint32, coinID dex.Bytes, lockTime uint64, amt uint64) *db.Bond { + return &db.Bond{ + AssetID: assetID, + CoinID: coinID, + LockTime: lockTime, + Amount: amt, + } + } + + now := uint64(time.Now().Unix()) + bondExpiry := uint64(60 * 60) + lockDur := minBondLifetime(dex.Mainnet, int64(bondExpiry)) + lockTime := time.Now().Add(lockDur).Truncate(time.Second) + weakBondThreshold := uint64(time.Now().Unix() + int64(bondExpiry) + pendingBuffer(dex.Mainnet)) + + pk := func() *secp256k1.PrivateKey { + pk, _ := secp256k1.GeneratePrivateKey() + return pk + } + + tests := []struct { + name string + + bonds []*db.Bond + pendingBonds []*db.Bond + expiredBonds []*db.Bond + targetTier uint64 + makeBondTxRes *asset.Bond + updateBondTxRes []*asset.Bond + maxBondedAmt uint64 + + expUpdateBondParams *updateBondParams + expExpiredBonds []*db.Bond + expPendingBonds []*db.Bond + expBonds []*db.Bond + }{ + { + name: "no bonds to update", + targetTier: 4, + bonds: []*db.Bond{}, + makeBondTxRes: &asset.Bond{ + CoinID: bondIDs[0], + AssetID: tUTXOAssetA.ID, + Amount: 4 * bondAmt, + }, + expPendingBonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[0], 0, 4*bondAmt), + }, + }, + { + name: "1 strong, 1 weak, need additional", + targetTier: 4, + bonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[0], weakBondThreshold+1, 2*bondAmt), // strong + newBond(tUTXOAssetA.ID, bondIDs[1], weakBondThreshold, 1*bondAmt), // weak + }, + updateBondTxRes: []*asset.Bond{{ + CoinID: bondIDs[2], + AssetID: tUTXOAssetA.ID, + Amount: 4 * bondAmt, + }}, + expUpdateBondParams: &updateBondParams{ + bonds: []dex.Bytes{ + bondIDs[0], bondIDs[1], + }, + lockTime: lockTime, + privKeys: []*secp256k1.PrivateKey{pk()}, + amt: 4 * bondAmt, + }, + expPendingBonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[2], 0, 4*bondAmt), + }, + }, + { + name: "1 strong, 1 weak, 1 expired, need change", + targetTier: 4, + bonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[0], weakBondThreshold+1, 2*bondAmt), // strong + newBond(tUTXOAssetA.ID, bondIDs[1], weakBondThreshold, bondAmt), // weak + }, + expiredBonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[2], now, 2*bondAmt), + }, + updateBondTxRes: []*asset.Bond{{ + CoinID: bondIDs[3], + AssetID: tUTXOAssetA.ID, + Amount: 4 * bondAmt, + }}, + expUpdateBondParams: &updateBondParams{ + bonds: []dex.Bytes{ + bondIDs[0], bondIDs[1], bondIDs[2], + }, + lockTime: lockTime, + privKeys: []*secp256k1.PrivateKey{pk(), pk()}, + amt: 4 * bondAmt, + }, + expPendingBonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[3], 0, 4*bondAmt), + }, + }, + { + name: "1 strong, 1 weak, 1 expired, no additional, no change", + targetTier: 4, + bonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[0], weakBondThreshold+1, 2*bondAmt), // strong + newBond(tUTXOAssetA.ID, bondIDs[1], weakBondThreshold, bondAmt), // weak + }, + expiredBonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[2], now, 1*bondAmt), + }, + updateBondTxRes: []*asset.Bond{{ + CoinID: bondIDs[3], + AssetID: tUTXOAssetA.ID, + Amount: 4 * bondAmt, + }}, + expUpdateBondParams: &updateBondParams{ + bonds: []dex.Bytes{ + bondIDs[0], bondIDs[1], bondIDs[2], + }, + lockTime: lockTime, + privKeys: []*secp256k1.PrivateKey{pk()}, + amt: 4 * bondAmt, + }, + expPendingBonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[3], 0, 4*bondAmt), + }, + }, + { + name: "ensure max bonded amt is respected", + maxBondedAmt: 4 * bondAmt, + targetTier: 5, + bonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[0], weakBondThreshold+1, 2*bondAmt), // strong + newBond(tUTXOAssetA.ID, bondIDs[1], weakBondThreshold, 1*bondAmt), // weak + }, + updateBondTxRes: []*asset.Bond{{ + CoinID: bondIDs[2], + AssetID: tUTXOAssetA.ID, + Amount: 4 * bondAmt, + }}, + expUpdateBondParams: &updateBondParams{ + bonds: []dex.Bytes{ + bondIDs[0], bondIDs[1], + }, + lockTime: lockTime, + privKeys: []*secp256k1.PrivateKey{pk()}, + amt: 4 * bondAmt, + }, + expPendingBonds: []*db.Bond{ + newBond(tUTXOAssetA.ID, bondIDs[2], 0, 4*bondAmt), + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + rig := newTestRig() + defer rig.shutdown() + tCore := rig.core + + dcrWallet, tDCRWallet := newTUpdateBonder(tUTXOAssetA.ID) + tCore.wallets[tUTXOAssetA.ID] = dcrWallet + tDCRWallet.contractExpired = true + tDCRWallet.refundBondCoin = &tCoin{id: encode.RandomBytes(32), val: 1e11} + tDCRWallet.updateBondTxRes = test.updateBondTxRes + tDCRWallet.makeBondTxRes = test.makeBondTxRes + + err := rig.core.Login(tPW) + if err != nil { + t.Fatalf("initial Login error: %v", err) + } + + dc := rig.core.conns[tDexHost] + dc.cfg = &msgjson.ConfigResult{ + BondAssets: bondAssets, + BondExpiry: bondExpiry, + } + acct := rig.dc.acct + acct.isAuthed = true + acct.targetTier = test.targetTier + acct.expiredBonds = test.expiredBonds + acct.pendingBonds = test.pendingBonds + acct.bonds = test.bonds + acct.maxBondedAmt = test.maxBondedAmt + dc.acct.bondAsset = tUTXOAssetA.ID + + var bondAmt uint64 + if test.makeBondTxRes != nil { + bondAmt = test.makeBondTxRes.Amount + } else { + bondAmt = test.updateBondTxRes[len(test.updateBondTxRes)-1].Amount + } + rig.queuePrevalidateBond(&msgjson.PreValidateBondResult{ + Amount: bondAmt, + }) + + rig.core.rotateBonds(rig.core.ctx) + + exp := test.expUpdateBondParams + got := tDCRWallet.lastUpdateBondTxParams + if (exp == nil) != (got == nil) { + t.Fatalf("%s: expected %v, got %v", test.name, exp, got) + } + if test.expUpdateBondParams != nil { + if !reflect.DeepEqual(exp.bonds, got.bonds) { + t.Fatalf("expected %v, got %v", exp.bonds, got.bonds) + } + if got.lockTime.Before(exp.lockTime) || got.lockTime.After(exp.lockTime.Add(20*time.Second)) { + t.Fatalf("expected %v, got %v", exp.lockTime, got.lockTime) + } + if exp.amt != got.amt { + t.Fatalf("expected %v, got %v", exp.amt, got.amt) + } + if len(exp.privKeys) != len(got.privKeys) { + t.Fatalf("expected %v, got %v", len(exp.privKeys), len(got.privKeys)) + } + } + + bondsEqual := func(b1, b2 *db.Bond) bool { + if b1.Amount != b2.Amount { + return false + } + if b1.AssetID != b2.AssetID { + return false + } + if !bytes.Equal(b1.CoinID, b2.CoinID) { + return false + } + return true + } + + if len(test.expExpiredBonds) != len(dc.acct.expiredBonds) { + t.Fatalf("expected %d expired bonds, got %d", len(test.expExpiredBonds), len(dc.acct.expiredBonds)) + } + for i, bond := range test.expExpiredBonds { + if !bondsEqual(bond, dc.acct.expiredBonds[i]) { + t.Fatalf("expected expired bond %v, got %v", bond, dc.acct.expiredBonds[i]) + } + } + + if len(test.expPendingBonds) != len(dc.acct.pendingBonds) { + t.Fatalf("expected %d pending bonds, got %d", len(test.expPendingBonds), len(dc.acct.pendingBonds)) + } + for i, bond := range test.expPendingBonds { + if !bondsEqual(bond, dc.acct.pendingBonds[i]) { + t.Fatalf("expected pending bond %v, got %v", bond, dc.acct.pendingBonds[i]) + } + } + + if len(test.expBonds) != len(dc.acct.bonds) { + t.Fatalf("expected %d bonds, got %d", len(test.expBonds), len(dc.acct.bonds)) + } + for i, bond := range test.expBonds { + if !bondsEqual(bond, dc.acct.bonds[i]) { + t.Fatalf("expected bond %v, got %v", bond, dc.acct.bonds[i]) + } + } + }) + } +} diff --git a/client/core/wallet.go b/client/core/wallet.go index 8e8f080143..c8037cccf4 100644 --- a/client/core/wallet.go +++ b/client/core/wallet.go @@ -571,6 +571,17 @@ func (w *xcWallet) BondsFeeBuffer(feeRate uint64) uint64 { return bonder.BondsFeeBuffer(feeRate) } +// UpdateBondTx authors a transaction that uses previouly created bonds to +// create a new DEX time-locked fidelity bond transaction. This only works +// if the asset.Wallet implementation is a BondUpdater. +func (w *xcWallet) UpdateBondTx(ver uint16, bondsToUpdate []dex.Bytes, privKeys []*secp256k1.PrivateKey, amt uint64, lockTime time.Time) ([]*asset.Bond, error) { + bonder, ok := w.Wallet.(asset.BondUpdater) + if !ok { + return nil, errors.New("wallet does not support updating bond transactions") + } + return bonder.UpdateBondTx(ver, bondsToUpdate, privKeys, amt, lockTime) +} + // RefundBond will refund the bond if the asset.Wallet implementation is a // Bonder. The lock time must be passed to spend the bond. LockTimeExpired // should be used to check first. @@ -582,6 +593,16 @@ func (w *xcWallet) RefundBond(ctx context.Context, ver uint16, coinID, script [] return bonder.RefundBond(ctx, ver, coinID, script, amt, priv) } +// BondConfirmations returns the amount of confirmations of a bond if the +// asset.Wallet implementation is a Bonder.s +func (w *xcWallet) BondConfirmations(ctx context.Context, bondID dex.Bytes) (uint32, error) { + bonder, ok := w.Wallet.(asset.Bonder) + if !ok { + return 0, errors.New("wallet does not support bond confirmations") + } + return bonder.BondConfirmations(ctx, bondID) +} + // SendTransaction broadcasts a raw transaction if the wallet is a Broadcaster. func (w *xcWallet) SendTransaction(tx []byte) ([]byte, error) { bonder, ok := w.Wallet.(asset.Broadcaster) diff --git a/client/db/bolt/db.go b/client/db/bolt/db.go index 4a030294e3..0013107549 100644 --- a/client/db/bolt/db.go +++ b/client/db/bolt/db.go @@ -85,6 +85,7 @@ var ( confirmedKey = []byte("confirmed") refundedKey = []byte("refunded") lockTimeKey = []byte("lockTime") + replacedByKey = []byte("replacedBy") dexKey = []byte("dex") updateTimeKey = []byte("utime") accountKey = []byte("account") @@ -839,6 +840,11 @@ func (db *BoltDB) storeBond(bondBkt *bbolt.Bucket, bond *db.Bond) error { return fmt.Errorf("lockTimeKey put error: %w", err) } + err = bondBkt.Put(replacedByKey, bond.ReplacedBy) + if err != nil { + return fmt.Errorf("replacedByKey put error: %w", err) + } + return nil } @@ -867,6 +873,37 @@ func (db *BoltDB) AddBond(host string, bond *db.Bond) error { }) } +// AddBonds saves a slice of new Bonds or updates existing bonds for an existing +// DEX account. +func (db *BoltDB) AddBonds(host string, bondsSlice []*db.Bond) error { + acctKey := []byte(host) + return db.acctsUpdate(func(accts *bbolt.Bucket) error { + acct := accts.Bucket(acctKey) + if acct == nil { + return fmt.Errorf("account not found for %s", host) + } + + bonds, err := acct.CreateBucketIfNotExists(bondsSubBucket) + if err != nil { + return fmt.Errorf("unable to access bonds sub-bucket for account for %s: %w", host, err) + } + + for _, bond := range bondsSlice { + bondUID := bond.UniqueID() + bondBkt, err := bonds.CreateBucketIfNotExists(bondUID) + if err != nil { + return fmt.Errorf("failed to create bond %x bucket: %w", bondUID, err) + } + + if err := db.storeBond(bondBkt, bond); err != nil { + return err + } + } + + return nil + }) +} + func (db *BoltDB) setBondFlag(host string, assetID uint32, bondCoinID []byte, flagKey []byte) error { acctKey := []byte(host) return db.acctsUpdate(func(accts *bbolt.Bucket) error { diff --git a/client/db/interface.go b/client/db/interface.go index 6145587b2e..d781e41123 100644 --- a/client/db/interface.go +++ b/client/db/interface.go @@ -40,6 +40,8 @@ type DB interface { UpdateAccountInfo(ai *AccountInfo) error // AddBond saves a new Bond or updates an existing bond for a DEX. AddBond(host string, bond *Bond) error + // AddBonds saves new bonds or updates existing bonds for a DEX. + AddBonds(host string, bondsSlice []*Bond) error // NextBondKeyIndex returns the next bond key index and increments the // stored value so that subsequent calls will always return a higher index. NextBondKeyIndex(assetID uint32) (uint32, error) diff --git a/client/db/types.go b/client/db/types.go index 244808fe9e..cb30e10b38 100644 --- a/client/db/types.go +++ b/client/db/types.go @@ -106,6 +106,7 @@ type Bond struct { LockTime uint64 `json:"lockTime"` KeyIndex uint32 `json:"keyIndex"` // child key index for HD path: m / hdKeyPurposeBonds / assetID' / bondIndex RefundTx dex.Bytes `json:"refundTx"` // pays to wallet that created it - only a backup for emergency! + ReplacedBy dex.Bytes `json:"replacedBy"` Confirmed bool `json:"confirmed"` // if reached required confs according to server, not in serialization Refunded bool `json:"refunded"` // not in serialization @@ -120,7 +121,7 @@ func (b *Bond) UniqueID() []byte { // Encode serialized the Bond. Confirmed and Refund are not included. func (b *Bond) Encode() []byte { - return versionedBytes(2). + return versionedBytes(3). AddData(uint16Bytes(b.Version)). AddData(uint32Bytes(b.AssetID)). AddData(b.CoinID). @@ -131,7 +132,8 @@ func (b *Bond) Encode() []byte { AddData(uint64Bytes(b.LockTime)). AddData(uint32Bytes(b.KeyIndex)). AddData(b.RefundTx). - AddData(uint32Bytes(b.Strength)) + AddData(uint32Bytes(b.Strength)). + AddData(b.ReplacedBy) // Confirmed and Refunded are not part of the encoding. } @@ -148,6 +150,8 @@ func DecodeBond(b []byte) (*Bond, error) { return decodeBond_v1(pushes) case 2: return decodeBond_v2(pushes) + case 3: + return decodeBond_v3(pushes) } return nil, fmt.Errorf("unknown Bond version %d", ver) } @@ -181,19 +185,26 @@ func decodeBond_v0(pushes [][]byte) (*Bond, error) { func decodeBond_v1(pushes [][]byte) (*Bond, error) { if len(pushes) != 10 { - return nil, fmt.Errorf("decodeBond_v0: expected 10 data pushes, got %d", len(pushes)) + return nil, fmt.Errorf("decodeBond_v1: expected 10 data pushes, got %d", len(pushes)) } return decodeBond_v2(append(pushes, []byte{0, 0, 0, 0} /* uint32 strength */)) } func decodeBond_v2(pushes [][]byte) (*Bond, error) { if len(pushes) != 11 { - return nil, fmt.Errorf("decodeBond_v0: expected 10 data pushes, got %d", len(pushes)) + return nil, fmt.Errorf("decodeBond_v2: expected 11 data pushes, got %d", len(pushes)) + } + return decodeBond_v3(append(pushes, nil /* replacedBy */)) +} +func decodeBond_v3(pushes [][]byte) (*Bond, error) { + if len(pushes) != 12 { + return nil, fmt.Errorf("decodeBond_v3: expected 12 data pushes, got %d", len(pushes)) } ver, assetIDB, coinID := pushes[0], pushes[1], pushes[2] utx, stx := pushes[3], pushes[4] data, amtB, lockTimeB := pushes[5], pushes[6], pushes[7] keyIndex, refundTx, strength := pushes[8], pushes[9], pushes[10] + replacedBy := pushes[11] return &Bond{ Version: intCoder.Uint16(ver), AssetID: intCoder.Uint32(assetIDB), @@ -206,6 +217,7 @@ func decodeBond_v2(pushes [][]byte) (*Bond, error) { KeyIndex: intCoder.Uint32(keyIndex), RefundTx: refundTx, Strength: intCoder.Uint32(strength), + ReplacedBy: replacedBy, }, nil } From 288158359d9b8358473f48091c74b46f677a8579 Mon Sep 17 00:00:00 2001 From: martonp Date: Thu, 6 Apr 2023 18:54:20 -0400 Subject: [PATCH 4/6] server/asset/eth: Add BondUpdater interface and implement in ETH This adds a BondUpdater interface in the server that requires a backend to implement an `AllAccountBonds` method. in addition to the Bonder interface's methods. This method returns all the currenlty active bonds for an account. This new interface is implemented by the ETH backend. This is required for assets where it is possible to use existing unexpired bonds to fund new bonds, because the server needs to know if bonds that it was previously using the calculates a user's tier no longer exist. --- server/asset/eth/eth.go | 107 ++++++++++++++++++++- server/asset/eth/eth_test.go | 8 ++ server/asset/eth/rpcclient.go | 95 ++++++++++++++++-- server/asset/eth/rpcclient_harness_test.go | 23 ++++- server/dex/dex.go | 31 ++++++ 5 files changed, 253 insertions(+), 11 deletions(-) diff --git a/server/asset/eth/eth.go b/server/asset/eth/eth.go index 5ed850fb0c..f1c25c2f6b 100644 --- a/server/asset/eth/eth.go +++ b/server/asset/eth/eth.go @@ -20,9 +20,11 @@ import ( "decred.org/dcrdex/dex" "decred.org/dcrdex/dex/config" dexeth "decred.org/dcrdex/dex/networks/eth" + "decred.org/dcrdex/server/account" "decred.org/dcrdex/server/asset" "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -158,6 +160,8 @@ type ethFetcher interface { loadToken(ctx context.Context, assetID uint32, vToken *VersionedToken) error swap(ctx context.Context, assetID uint32, secretHash [32]byte) (*dexeth.SwapState, error) accountBalance(ctx context.Context, assetID uint32, addr common.Address) (*big.Int, error) + bond(ctx context.Context, accountID, bondID [32]byte) (*bondInfo, error) + accountBonds(ctx context.Context, accountID [32]byte) ([]*bondInfo, error) } type baseBackend struct { @@ -337,13 +341,17 @@ func NewEVMBackend( if !found { return nil, fmt.Errorf("no contract address for %s version %d on %s", assetName, ethContractVersion, net) } + bondContractAddress, found := dexeth.ETHBondAddress[net] + if !found { + return nil, fmt.Errorf("no bond address for network %s", net) + } eth, err := unconnectedETH(baseChainID, contractAddr, vTokens, log, net) if err != nil { return nil, err } - eth.node = newRPCClient(baseChainID, net, endpoints, contractAddr, log.SubLogger("RPC")) + eth.node = newRPCClient(baseChainID, net, endpoints, contractAddr, bondContractAddress, log.SubLogger("RPC")) return eth, nil } @@ -722,6 +730,103 @@ func (eth *baseBackend) ValidateSignature(addr string, pubkey, msg, sig []byte) return nil } +// BondVer returns the latest supported bond version. +func (eth *ETHBackend) BondVer() uint16 { + return 0 +} + +// AllAccountBonds returns all the bonds for the specified account. +func (eth *ETHBackend) AllAccountBonds(ctx context.Context, acct account.AccountID) ([]*asset.BondData, error) { + bonds, err := eth.node.accountBonds(ctx, acct) + if err != nil { + return nil, err + } + + assetBonds := make([]*asset.BondData, 0, len(bonds)) + for _, bond := range bonds { + assetBonds = append(assetBonds, &asset.BondData{ + AccountID: acct, + CoinID: append(acct[:], bond.BondID[:]...), + Amount: dexeth.WeiToGwei(bond.Value), + LockTime: bond.Locktime, + }) + } + return assetBonds, nil +} + +// BondCoin locates a bond transaction output, validates the entire transaction, +// and returns the amount, encoded lockTime and account ID, and the +// confirmations of the transaction. It is a CoinNotFoundError if the +// transaction output is spent. +func (eth *ETHBackend) BondCoin(ctx context.Context, ver uint16, coinID []byte) (amt, lockTime, confs int64, + acct account.AccountID, err error) { + fail := func(err error) (int64, int64, int64, account.AccountID, error) { + return 0, 0, 0, account.AccountID{}, err + } + + if len(coinID) != 64 { + return fail(fmt.Errorf("coinID should be 32 bytes, got %d", len(coinID))) + } + + var accountID, bondID [32]byte + copy(accountID[:], coinID[:32]) + copy(bondID[:], coinID[32:]) + + bondData, err := eth.node.bond(ctx, accountID, bondID) + if err != nil && errors.Is(err, ethereum.NotFound) { + return fail(asset.CoinNotFoundError) + } + if err != nil { + return fail(err) + } + + bn, err := eth.node.blockNumber(ctx) + if err != nil { + return fail(err) + } + + amt = int64(dexeth.WeiToGwei(bondData.Value)) + lockTime = int64(bondData.Locktime) + confs = int64(bn) - bondData.InitBlockNumber.Int64() + return amt, lockTime, confs, accountID, nil +} + +func makeBondCoinID(acct account.AccountID, bondID [32]byte) []byte { + return append(acct[:], bondID[:]...) +} + +// ParseBondTx returns the data about the bond that will be created using the +// rawTx. If the transaction is an update transaction, the amount and lockTime +// of the non-change transaction will be returned. +func (eth *ETHBackend) ParseBondTx(ver uint16, rawTx []byte) (bondCoinID []byte, amt int64, bondAddr string, + bondPubKeyHash []byte, lockTime int64, acct account.AccountID, err error) { + + fail := func(err error) ([]byte, int64, string, []byte, int64, account.AccountID, error) { + return nil, 0, "", nil, 0, account.AccountID{}, err + } + + tx := new(types.Transaction) + if err := tx.UnmarshalBinary(rawTx); err != nil { + return fail(fmt.Errorf("unable to decode tx: %v", err)) + } + + accountID, bondID, lt, err := dexeth.ParseCreateBondTx(tx.Data()) + if err != nil { + accountID, _, newBondIDs, value, lt, err := dexeth.ParseUpdateBondsTx(tx.Data()) + if err != nil { + return fail(fmt.Errorf("failed to parse bond tx: %v", err)) + } + + newBondID := newBondIDs[0] + if len(newBondIDs) == 2 { + newBondID = newBondIDs[1] + } + return makeBondCoinID(accountID, newBondID), int64(dexeth.WeiToGwei(value)), "", nil, int64(lt), accountID, nil + } + + return makeBondCoinID(accountID, bondID), int64(dexeth.WeiToGwei(tx.Value())), "", nil, int64(lt), accountID, nil +} + // poll pulls the best hash from an eth node and compares that to a stored // hash. If the same does nothing. If different, updates the stored hash and // notifies listeners on block chans. diff --git a/server/asset/eth/eth_test.go b/server/asset/eth/eth_test.go index f51ff39c2b..688733267f 100644 --- a/server/asset/eth/eth_test.go +++ b/server/asset/eth/eth_test.go @@ -154,6 +154,14 @@ func (n *testNode) accountBalance(ctx context.Context, assetID uint32, addr comm return n.acctBal, n.acctBalErr } +func (n *testNode) bond(ctx context.Context, accountID, bondID [32]byte) (*bondInfo, error) { + return nil, nil +} + +func (n *testNode) accountBonds(ctx context.Context, accountID [32]byte) ([]*bondInfo, error) { + return nil, nil +} + func tSwap(bn, locktime int64, value uint64, secret [32]byte, state dexeth.SwapStep, participantAddr *common.Address) *dexeth.SwapState { return &dexeth.SwapState{ Secret: secret, diff --git a/server/asset/eth/rpcclient.go b/server/asset/eth/rpcclient.go index 764a218a61..b02c01a288 100644 --- a/server/asset/eth/rpcclient.go +++ b/server/asset/eth/rpcclient.go @@ -17,8 +17,11 @@ import ( "decred.org/dcrdex/dex" dexeth "decred.org/dcrdex/dex/networks/eth" + bondV0 "decred.org/dcrdex/dex/networks/eth/bondcontracts/v0" swapv0 "decred.org/dcrdex/dex/networks/eth/contracts/v0" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -42,6 +45,16 @@ type ContextCaller interface { CallContext(ctx context.Context, result any, method string, args ...any) error } +type bondContract interface { + BondData(opts *bind.CallOpts, accountID [32]byte, bondID [32]byte) (struct { + Value *big.Int + InitBlockNumber *big.Int + Locktime uint64 + Owner common.Address + }, error) + BondsForAccount(opts *bind.CallOpts, accountID [32]byte) ([]bondV0.ETHBondBondInfo, error) +} + type ethConn struct { *ethclient.Client endpoint string @@ -51,7 +64,8 @@ type ethConn struct { // tokens are tokeners for loaded tokens. tokens is not protected by a // mutex, as it is expected that the caller will connect and place calls to // loadToken sequentially in the same thread during initialization. - tokens map[uint32]*tokener + tokens map[uint32]*tokener + bondContract bondContract // caller is a client for raw calls not implemented by *ethclient.Client. caller ContextCaller txPoolSupported bool @@ -157,21 +171,23 @@ type rpcclient struct { healthCheckCounter int tokensLoaded map[uint32]*VersionedToken ethContractAddr common.Address + bondContractAddr common.Address // the order of clients will change based on the health of the connections. clientsMtx sync.RWMutex clients []*ethConn } -func newRPCClient(baseChainID uint32, net dex.Network, endpoints []endpoint, ethContractAddr common.Address, log dex.Logger) *rpcclient { +func newRPCClient(baseChainID uint32, net dex.Network, endpoints []endpoint, ethContractAddr common.Address, bondContractAddr common.Address, log dex.Logger) *rpcclient { return &rpcclient{ - baseChainID: baseChainID, - baseChainName: strings.ToUpper(dex.BipIDSymbol(baseChainID)), - net: net, - endpoints: endpoints, - log: log, - ethContractAddr: ethContractAddr, - tokensLoaded: make(map[uint32]*VersionedToken), + baseChainID: baseChainID, + baseChainName: strings.ToUpper(dex.BipIDSymbol(baseChainID)), + net: net, + endpoints: endpoints, + log: log, + ethContractAddr: ethContractAddr, + tokensLoaded: make(map[uint32]*VersionedToken), + bondContractAddr: bondContractAddr, } } @@ -239,6 +255,12 @@ func (c *rpcclient) connectToEndpoint(ctx context.Context, endpoint endpoint) (* } ec.swapContract = &swapSourceV0{es} + bc, err := bondV0.NewETHBond(c.bondContractAddr, ec.Client) + if err != nil { + return nil, fmt.Errorf("unable to initialize bond contract for %q: %v", endpoint, err) + } + ec.bondContract = bc + for assetID, vToken := range c.tokensLoaded { tkn, err := newTokener(ctx, vToken, c.net, ec.Client) if err != nil { @@ -551,6 +573,61 @@ func (c *rpcclient) swap(ctx context.Context, assetID uint32, secretHash [32]byt }) } +type bondInfo struct { + AccountID [32]byte + BondID [32]byte + Value *big.Int + InitBlockNumber *big.Int + Locktime uint64 + Owner common.Address +} + +func (c *rpcclient) bond(ctx context.Context, accountID, bondID [32]byte) (*bondInfo, error) { + var bond *bondInfo + return bond, c.withClient(func(ec *ethConn) error { + b, err := ec.bondContract.BondData(&bind.CallOpts{Context: ctx}, accountID, bondID) + if err != nil { + return err + } + if b.InitBlockNumber == nil || b.InitBlockNumber.Cmp(big.NewInt(0)) == 0 { + return ethereum.NotFound + } + bond = &bondInfo{ + AccountID: accountID, + BondID: bondID, + Value: b.Value, + InitBlockNumber: b.InitBlockNumber, + Locktime: b.Locktime, + Owner: b.Owner, + } + return nil + }, true) +} + +func (c *rpcclient) accountBonds(ctx context.Context, accountID [32]byte) ([]*bondInfo, error) { + var bondInfos []*bondInfo + return bondInfos, c.withClient(func(ec *ethConn) error { + bonds, err := ec.bondContract.BondsForAccount(&bind.CallOpts{Context: ctx}, accountID) + if err != nil { + return err + } + + c.log.Tracef("Got all bonds for account: %x\n", accountID) + bondInfos = make([]*bondInfo, 0, len(bonds)) + for _, bond := range bonds { + bondInfos = append(bondInfos, &bondInfo{ + AccountID: accountID, + BondID: bond.BondID, + Value: bond.Value, + InitBlockNumber: bond.InitBlockNumber, + Locktime: bond.Locktime, + Owner: bond.Owner, + }) + } + return nil + }, true) +} + // transaction gets the transaction that hashes to hash from the chain or // mempool. Errors if tx does not exist. func (c *rpcclient) transaction(ctx context.Context, hash common.Hash) (tx *types.Transaction, isMempool bool, err error) { diff --git a/server/asset/eth/rpcclient_harness_test.go b/server/asset/eth/rpcclient_harness_test.go index 9a76bb49a8..fe2a95d1e3 100644 --- a/server/asset/eth/rpcclient_harness_test.go +++ b/server/asset/eth/rpcclient_harness_test.go @@ -6,6 +6,7 @@ package eth import ( + "encoding/hex" "errors" "fmt" "math/big" @@ -20,6 +21,7 @@ import ( "decred.org/dcrdex/dex" "decred.org/dcrdex/dex/encode" dexeth "decred.org/dcrdex/dex/networks/eth" + "decred.org/dcrdex/server/account" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" ) @@ -57,7 +59,12 @@ func TestMain(m *testing.M) { return 1, fmt.Errorf("no contract address for eth version %d on %s", ethContractVersion, dex.Simnet) } - ethClient = newRPCClient(BipID, dex.Simnet, []endpoint{{url: wsEndpoint}, {url: alphaIPCFile}}, ethContractAddr, log) + bondContractAddress, found := dexeth.ETHBondAddress[dex.Simnet] + if !found { + return 1, fmt.Errorf("no bond address for network %s", dex.Simnet) + } + + ethClient = newRPCClient(BipID, dex.Simnet, []endpoint{{url: wsEndpoint}, {url: alphaIPCFile}}, ethContractAddr, bondContractAddress, log) dexeth.ContractAddresses[0][dex.Simnet] = getContractAddrFromFile(contractAddrFile) @@ -199,6 +206,20 @@ func TestMonitorHealth(t *testing.T) { } } +func TestAllAccountBonds(t *testing.T) { + acctIDS := "83a1ddd916b9a04eb055129fb1249eff4469c064ff32bc470ee1c9ae5fe9d240" + accIDB, _ := hex.DecodeString(acctIDS) + var acctID account.AccountID + copy(acctID[:], accIDB) + bonds, err := ethClient.accountBonds(ctx, acctID) + if err != nil { + t.Fatalf("AllAccountBonds error: %v", err) + } + for _, bond := range bonds { + fmt.Printf("%s\n\n", hex.EncodeToString(bond.BondID[:])) + } +} + func TestHeaderSubscription(t *testing.T) { ctx, cancel := context.WithTimeout(ctx, headerExpirationTime) defer cancel() diff --git a/server/dex/dex.go b/server/dex/dex.go index f2d64f1c9b..e956a7b8ec 100644 --- a/server/dex/dex.go +++ b/server/dex/dex.go @@ -257,6 +257,16 @@ type Bonder interface { bondPubKeyHash []byte, lockTime int64, acct account.AccountID, err error) } +// BondUpdater is a type that supports using funds in existing bonds to +// create new bonds. This requires the server to be able to locate all +// the active bonds for an account to know which previously posted bonds +// should no longer applied to a user's tier. +type BondUpdater interface { + Bonder + + AllAccountBonds(ctx context.Context, acct account.AccountID) (bonds []*asset.BondData, err error) +} + // NewDEX creates the dex manager and starts all subsystems. Use Stop to // shutdown cleanly. The Context is used to abort setup. // 1. Validate each specified asset. @@ -440,6 +450,7 @@ func NewDEX(ctx context.Context, cfg *DexConf) (*DEX, error) { xpubs := make(map[string]string) // to enforce uniqueness bondAssets := make(map[string]*msgjson.BondAsset) bonders := make(map[uint32]Bonder) + bondUpdaters := make(map[uint32]BondUpdater) // Start asset backends. lockableAssets := make(map[uint32]*swap.SwapperAsset, len(cfg.Assets)) @@ -510,6 +521,10 @@ func NewDEX(ctx context.Context, cfg *DexConf) (*DEX, error) { bonders[assetID] = bc log.Infof("Bonds accepted using %s: amount %d, confs %d", symbol, assetConf.BondAmt, assetConf.BondConfs) + + if bondUpdater, ok := be.(BondUpdater); ok { + bondUpdaters[assetID] = bondUpdater + } } if assetConf.RegFee > 0 { @@ -664,6 +679,20 @@ func NewDEX(ctx context.Context, cfg *DexConf) (*DEX, error) { return bc.BondCoin(ctx, version, coinID) } + allBondChecker := func(ctx context.Context, assetID uint32, ver uint16, acctID account.AccountID) ([]*asset.BondData, error) { + bu, ok := bondUpdaters[assetID] + if !ok { + return nil, fmt.Errorf("bond asset %v is not an updater", assetID) + } + + return bu.AllAccountBonds(ctx, acctID) + } + + isBondUpdater := func(assetID uint32) bool { + _, ok := bondUpdaters[assetID] + return ok + } + bondTxParser := func(assetID uint32, version uint16, rawTx []byte) (bondCoinID []byte, amt, lockTime int64, acct account.AccountID, err error) { bc := bonders[assetID] @@ -697,6 +726,8 @@ func NewDEX(ctx context.Context, cfg *DexConf) (*DEX, error) { BondTxParser: bondTxParser, BondChecker: bondChecker, BondExpiry: uint64(dex.BondExpiry(cfg.Network)), + AllBondChecker: allBondChecker, + IsBondUpdater: isBondUpdater, UserUnbooker: userUnbookFun, MiaUserTimeout: cfg.BroadcastTimeout, CancelThreshold: cfg.CancelThreshold, From c478930333bc493c5dda69c21db7bf3ebed5ea0c Mon Sep 17 00:00:00 2001 From: martonp Date: Thu, 6 Apr 2023 19:03:54 -0400 Subject: [PATCH 5/6] server/{auth,db}: Update server to support `BondUpdater`s When a new bond is posted for an asset that implements `BondUpdater`, all of the currently active bonds for that asset are retrieved from the blockchain, and the the bonds for this asset that were stored in the database and the `AuthManager` are replaced by what was retreived. --- server/asset/common.go | 8 ++ server/asset/eth/rpcclient_harness_test.go | 2 +- server/auth/auth.go | 70 ++++++++++-- server/auth/auth_test.go | 5 +- server/auth/registrar.go | 119 ++++++++++++++++++--- server/db/driver/pg/accounts.go | 60 +++++++++++ server/db/driver/pg/internal/accounts.go | 2 + server/db/interface.go | 6 ++ 8 files changed, 248 insertions(+), 24 deletions(-) diff --git a/server/asset/common.go b/server/asset/common.go index c86fa9c3c2..b4f7680309 100644 --- a/server/asset/common.go +++ b/server/asset/common.go @@ -9,6 +9,7 @@ import ( "time" "decred.org/dcrdex/dex" + "decred.org/dcrdex/server/account" ) // Addresser retrieves unique addresses. @@ -199,3 +200,10 @@ type BackedAsset struct { dex.Asset Backend Backend } + +type BondData struct { + AccountID account.AccountID + Amount uint64 + LockTime uint64 + CoinID []byte +} diff --git a/server/asset/eth/rpcclient_harness_test.go b/server/asset/eth/rpcclient_harness_test.go index fe2a95d1e3..ee380a22dd 100644 --- a/server/asset/eth/rpcclient_harness_test.go +++ b/server/asset/eth/rpcclient_harness_test.go @@ -224,7 +224,7 @@ func TestHeaderSubscription(t *testing.T) { ctx, cancel := context.WithTimeout(ctx, headerExpirationTime) defer cancel() ept := endpoint{url: wsEndpoint} - cl := newRPCClient(BipID, dex.Simnet, []endpoint{ept}, ethClient.ethContractAddr, ethClient.log) + cl := newRPCClient(BipID, dex.Simnet, []endpoint{ept}, ethClient.ethContractAddr, ethClient.bondContractAddr, ethClient.log) ec, err := cl.connectToEndpoint(ctx, ept) if err != nil { t.Fatalf("connectToEndpoint error: %v", err) diff --git a/server/auth/auth.go b/server/auth/auth.go index b7c4dc3b2c..11ab1a4e96 100644 --- a/server/auth/auth.go +++ b/server/auth/auth.go @@ -52,6 +52,7 @@ type Storage interface { CreateAccountWithBond(acct *account.Account, bond *db.Bond) error AddBond(acct account.AccountID, bond *db.Bond) error DeleteBond(assetID uint32, coinID []byte) error + UpdateAssetBonds(acct *account.Account, bonds []*db.Bond, newAcct bool) error CreateAccount(acct *account.Account, feeAsset uint32, feeAddr string) error // DEPRECATED AccountRegAddr(account.AccountID) (addr string, asset uint32, err error) // DEPRECATED @@ -85,6 +86,10 @@ type FeeChecker func(assetID uint32, coinID []byte) (addr string, val uint64, co type BondCoinChecker func(ctx context.Context, assetID uint32, ver uint16, coinID []byte) (amt, lockTime, confs int64, acct account.AccountID, err error) +type AllBondChecker func(ctx context.Context, assetID uint32, ver uint16, acct account.AccountID) ([]*asset.BondData, error) + +type BondUpdaterChecker func(assetID uint32) bool + // BondTxParser parses a dex fidelity bond transaction and the redeem script of // the first output of the transaction, which must be the actual bond output. // The returned account ID is from the second output. This will become a @@ -131,6 +136,26 @@ func (client *clientInfo) bondTier() (bondTier int64) { return } +// not thread-safe +func (client *clientInfo) updateAssetBonds(assetID uint32, bonds []*db.Bond) (bondTier int64) { + var n int + for _, bond := range client.bonds { + if bond.AssetID != assetID { + bondTier += int64(bond.Strength) + client.bonds[n] = bond + n++ + } + } + client.bonds = client.bonds[:n] + + for _, bond := range bonds { + client.bonds = append(client.bonds, bond) + bondTier += int64(bond.Strength) + } + + return +} + // not thread-safe func (client *clientInfo) addBond(bond *db.Bond) (bondTier int64) { var dup bool @@ -227,12 +252,15 @@ func (client *clientInfo) respHandler(id uint64) *respHandler { // signing messages with the DEX's private key. AuthManager manages requests to // the 'connect' route. type AuthManager struct { - wg sync.WaitGroup - storage Storage - signer Signer - checkFee FeeChecker // legacy fee confs, amt, and address - parseBondTx BondTxParser - checkBond BondCoinChecker // fidelity bond amount, lockTime, acct, and confs + wg sync.WaitGroup + storage Storage + signer Signer + checkFee FeeChecker // legacy fee confs, amt, and address + parseBondTx BondTxParser + checkBond BondCoinChecker // fidelity bond amount, lockTime, acct, and confs + checkAllBonds AllBondChecker // all bonds for an account + // isBondupdater checks if a bond is a bond updater, which means that checkAllBonds should be called + isBondUpdater BondUpdaterChecker miaUserTimeout time.Duration unbookFun func(account.AccountID) route func(route string, handler comms.MsgHandler) @@ -388,6 +416,11 @@ type Config struct { // BondChecker locates an unspent bond, and extracts the amount, lockTime, // and account ID, plus txn confirmations. BondChecker BondCoinChecker + // AllBondChecker returns all the bonds for an account. + AllBondChecker AllBondChecker + // IsBondUpdater returns whether or not AllBondChecker can be called on + // an asset. + IsBondUpdater BondUpdaterChecker // FeeAddress retrieves a fresh registration fee address for an asset. It // should return an empty string for an unsupported asset. @@ -444,6 +477,8 @@ func NewAuthManager(cfg *Config) *AuthManager { checkFee: cfg.FeeChecker, // e.g. dcr's FeeCoin parseBondTx: cfg.BondTxParser, // e.g. dcr's ParseBondTx checkBond: cfg.BondChecker, // e.g. dcr's BondCoin + checkAllBonds: cfg.AllBondChecker, + isBondUpdater: cfg.IsBondUpdater, miaUserTimeout: cfg.MiaUserTimeout, unbookFun: cfg.UserUnbooker, route: cfg.Route, @@ -1300,6 +1335,29 @@ func (auth *AuthManager) addBond(user account.AccountID, bond *db.Bond) *account return rep } +// updateAssetBonds removes all of a user's bond's that were posted using a +// certain asset, and replaces them with the bonds provided. +func (auth *AuthManager) updateAssetBonds(user account.AccountID, assetID uint32, bonds []*db.Bond) *account.Reputation { + client := auth.user(user) + if client == nil { + return nil // offline + } + + auth.violationMtx.Lock() + score := auth.userScore(user) + auth.violationMtx.Unlock() + + client.mtx.Lock() + defer client.mtx.Unlock() + + bondTier := client.updateAssetBonds(assetID, bonds) + rep := auth.userReputation(bondTier, score, client.legacyFeePaid) + client.tier = rep.EffectiveTier() + client.score = score + + return rep +} + // addClient adds the client to the users and conns maps, and stops any unbook // timers started when they last disconnected. func (auth *AuthManager) addClient(client *clientInfo) { diff --git a/server/auth/auth_test.go b/server/auth/auth_test.go index f7f4cc6028..b266164fe8 100644 --- a/server/auth/auth_test.go +++ b/server/auth/auth_test.go @@ -76,7 +76,10 @@ func (s *TStorage) Account(acct account.AccountID, lockTimeThresh time.Time) (*a } func (s *TStorage) CreateAccountWithBond(acct *account.Account, bond *db.Bond) error { return nil } func (s *TStorage) AddBond(acct account.AccountID, bond *db.Bond) error { return nil } -func (s *TStorage) DeleteBond(assetID uint32, coinID []byte) error { return nil } +func (s *TStorage) UpdateAssetBonds(acct *account.Account, bonds []*db.Bond, newAcct bool) error { + return nil +} +func (s *TStorage) DeleteBond(assetID uint32, coinID []byte) error { return nil } func (s *TStorage) CompletedAndAtFaultMatchStats(aid account.AccountID, lastN int) ([]*db.MatchOutcome, error) { return s.userMatchOutcomes, nil } diff --git a/server/auth/registrar.go b/server/auth/registrar.go index 055b45235f..a80505e5d5 100644 --- a/server/auth/registrar.go +++ b/server/auth/registrar.go @@ -301,12 +301,114 @@ func (auth *AuthManager) handlePostBond(conn comms.Link, msg *msgjson.Message) * return nil } +func (auth *AuthManager) sendPostBondRes(conn comms.Link, reqID uint64, postBondRes *msgjson.PostBondResult, acctID account.AccountID) { + resp, err := msgjson.NewResponse(reqID, postBondRes, nil) + if err != nil { // shouldn't be possible + return + } + err = conn.Send(resp) + if err != nil { + log.Warnf("Error sending postbond result to user %v: %v", acctID, err) + if err = auth.Send(acctID, resp); err != nil { + log.Warnf("Error sending feepaid notification to account %v: %v", acctID, err) + // The user will need to either 'connect' to see confirmed status, + // or postbond again. If they reconnected before it was confirmed, + // they must retry postbond until it confirms and is added to the DB + // with their new account. + } + } +} + +// storeUpdaterBondsAndRespond is called for assets that support updating of +// bonds. Since previous bonds that were posted may have been updated by the +// new bond that is currently being posted, we need to check the blockchain +// for all of the bonds that are currently active for the account and determine +// the user's tier based on them. +func (auth *AuthManager) storeUpdaterBondsAndRespond(conn comms.Link, acct *account.Account, newAcct bool, assetID uint32, reqID uint64, postBondRes *msgjson.PostBondResult) { + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + + acctID := acct.ID + + bonds, err := auth.checkAllBonds(ctx, assetID, 0, acctID) + if err != nil { + conn.SendError(reqID, &msgjson.Error{ + Code: msgjson.RPCInternalError, + Message: "error checking bonds", + }) + return + } + + bondAsset, ok := auth.bondAssets[assetID] + if !ok { + conn.SendError(reqID, &msgjson.Error{ + Code: msgjson.RPCInternalError, + Message: fmt.Sprintf("%s is not a bond asset", dex.BipIDSymbol(assetID)), + }) + return + } + + dbBonds := make([]*db.Bond, 0, len(bonds)) + for _, bond := range bonds { + if bond.Amount < bondAsset.Amt { + continue + } + if time.Until(time.Unix(int64(bond.LockTime), 0)) < auth.bondExpiry { + continue + } + dbBonds = append(dbBonds, &db.Bond{ + Version: 0, + AssetID: assetID, + CoinID: bond.CoinID, + Amount: int64(bond.Amount), + Strength: uint32(bond.Amount / bondAsset.Amt), + LockTime: int64(bond.LockTime), + }) + } + + if len(dbBonds) == 0 { + conn.SendError(reqID, &msgjson.Error{ + Code: msgjson.RPCPostBondError, + Message: "no active bonds for account", + }) + return + } + + err = auth.storage.UpdateAssetBonds(acct, dbBonds, newAcct) + if err != nil { + conn.SendError(reqID, &msgjson.Error{ + Code: msgjson.RPCInternalError, + Message: "failed to store bond", + }) + return + } + + // Integrate active bonds and score to report tier. + rep := auth.updateAssetBonds(acctID, assetID, dbBonds) + if rep == nil { // user not authenticated, use DB + rep = auth.ComputeUserReputation(acctID) + } + postBondRes.Tier = rep.EffectiveTier() + postBondRes.Reputation = rep + + log.Infof("Bonds for asset %d updated: acct %v. Bond total %d, tier %d", + assetID, acctID, rep.BondedTier, rep.EffectiveTier()) + + auth.sendPostBondRes(conn, reqID, postBondRes, acctID) +} + func (auth *AuthManager) storeBondAndRespond(conn comms.Link, bond *db.Bond, acct *account.Account, newAcct bool, reqID uint64, postBondRes *msgjson.PostBondResult) { acctID := acct.ID assetID, coinID := bond.AssetID, bond.CoinID bondStr := coinIDString(assetID, coinID) bondAssetSym := dex.BipIDSymbol(assetID) + + if auth.isBondUpdater(assetID) { + auth.storeUpdaterBondsAndRespond(conn, acct, newAcct, assetID, reqID, postBondRes) + return + } + var err error if newAcct { log.Infof("Creating new user account %v from %v, posted first bond in %v (%s)", @@ -337,22 +439,7 @@ func (auth *AuthManager) storeBondAndRespond(conn comms.Link, bond *db.Bond, acc log.Infof("Bond accepted: acct %v from %v locked %d in %v. Bond total %d, tier %d", acctID, conn.Addr(), bond.Amount, coinIDString(bond.AssetID, coinID), rep.BondedTier, rep.EffectiveTier()) - // Respond - resp, err := msgjson.NewResponse(reqID, postBondRes, nil) - if err != nil { // shouldn't be possible - return - } - err = conn.Send(resp) - if err != nil { - log.Warnf("Error sending postbond result to user %v: %v", acctID, err) - if err = auth.Send(acctID, resp); err != nil { - log.Warnf("Error sending feepaid notification to account %v: %v", acctID, err) - // The user will need to either 'connect' to see confirmed status, - // or postbond again. If they reconnected before it was confirmed, - // they must retry postbond until it confirms and is added to the DB - // with their new account. - } - } + auth.sendPostBondRes(conn, reqID, postBondRes, acctID) } // waitBondConfs is a coin waiter that should be started after validating a bond diff --git a/server/db/driver/pg/accounts.go b/server/db/driver/pg/accounts.go index 59e4c33922..b8e322ad8d 100644 --- a/server/db/driver/pg/accounts.go +++ b/server/db/driver/pg/accounts.go @@ -155,6 +155,58 @@ func (a *Archiver) DeleteBond(assetID uint32, coinID []byte) error { return deleteBond(a.db, a.tables.bonds, assetID, coinID) } +// UpdateAssetBonds deletes all of the bonds for an account for a certain +// asset, and loads the provided bonds into the db. All of the provided +// bonds must have the same asset ID. A new account will be created if +// newAcct is true. +func (a *Archiver) UpdateAssetBonds(acct *account.Account, bonds []*db.Bond, newAcct bool) error { + if len(bonds) == 0 { + return fmt.Errorf("no bonds provided") + } + + assetID := bonds[0].AssetID + for _, bond := range bonds { + if bond.AssetID != assetID { + return fmt.Errorf("asset ID mismatch for bond %v", bond) + } + } + + dbTx, err := a.db.BeginTx(a.ctx, nil) + if err != nil { + return err + } + defer func() { + if err == nil || errors.Is(err, sql.ErrTxDone) { + return + } + if errR := dbTx.Rollback(); errR != nil { + log.Errorf("Rollback failed: %v", errR) + } + }() + + if newAcct { + err = createAccountForBond(dbTx, a.tables.accounts, acct) + if err != nil { + return err + } + } + + err = deleteAssetBondsForAccount(dbTx, a.tables.bonds, acct.ID, assetID) + if err != nil { + return err + } + + for _, bond := range bonds { + err = addBond(dbTx, a.tables.bonds, acct.ID, bond) + if err != nil { + return err + } + } + + err = dbTx.Commit() // for the defer + return err +} + // AccountRegAddr retrieves the registration fee address and the corresponding // asset ID created for the the specified account. func (a *Archiver) AccountRegAddr(aid account.AccountID) (string, uint32, error) { @@ -309,6 +361,14 @@ func getBondsForAccount(dbe sqlQueryer, tableName string, acct account.AccountID return bonds, nil } +// deleteAssetBondsForAccount deletes all bonds for the specified account and +// asset. +func deleteAssetBondsForAccount(dbe sqlExecutor, tableName string, acct account.AccountID, assetID uint32) error { + stmt := fmt.Sprintf(internal.DeleteAssetBondsForUser, tableName) + _, err := dbe.Exec(stmt, acct, assetID) + return err +} + // accountRegAddr gets the registration fee address and its asset ID created for // the specified account. func accountRegAddr(dbe sqlQueryer, tableName string, aid account.AccountID) (string, uint32, error) { diff --git a/server/db/driver/pg/internal/accounts.go b/server/db/driver/pg/internal/accounts.go index df7a158855..e004b95b67 100644 --- a/server/db/driver/pg/internal/accounts.go +++ b/server/db/driver/pg/internal/accounts.go @@ -43,6 +43,8 @@ const ( DeleteBond = `DELETE FROM %s WHERE bond_coin_id = $1 AND asset_id = $2;` + DeleteAssetBondsForUser = `DELETE FROM %s WHERE account_id = $1 AND asset_id = $2;` + SelectActiveBondsForUser = `SELECT version, bond_coin_id, asset_id, amount, strength, lock_time FROM %s WHERE account_id = $1 AND lock_time >= $2 ORDER BY lock_time;` diff --git a/server/db/interface.go b/server/db/interface.go index 135c3ca972..75db36feb8 100644 --- a/server/db/interface.go +++ b/server/db/interface.go @@ -269,6 +269,12 @@ type AccountArchiver interface { // coin ID), for an existing account. AddBond(acct account.AccountID, bond *Bond) error + // UpdateAssetBonds deletes all of the bonds for an account for a certain + // asset, and loads the provided bonds into the db. All of the provided + // bonds must have the same asset ID. A new account will be created if + // newAcct is true. + UpdateAssetBonds(acct *account.Account, bonds []*Bond, newAcct bool) error + // DeleteBond deletes a bond which should generally be expired. DeleteBond(assetID uint32, coinID []byte) error From f374f4c450c0c6e6e2c045636da23ba80c20da6a Mon Sep 17 00:00:00 2001 From: martonp Date: Tue, 13 Feb 2024 16:02:51 -0500 Subject: [PATCH 6/6] app: Update UI to support bond updaters The transaction details popup now shows change and replaced bonds. Also in many placed the bond amount was multiplied by two to handle the bond reserves requirement which bond updaters do not have, so this needed to be updated. --- client/core/bond.go | 7 +- client/webserver/locales/en-us.go | 5 ++ client/webserver/site/src/css/wallets.scss | 6 +- client/webserver/site/src/html/wallets.tmpl | 34 ++++++++- client/webserver/site/src/js/dexsettings.ts | 21 ++++-- client/webserver/site/src/js/forms.ts | 21 ++++-- client/webserver/site/src/js/locales.ts | 2 + client/webserver/site/src/js/register.ts | 10 ++- client/webserver/site/src/js/registry.ts | 11 ++- client/webserver/site/src/js/settings.ts | 10 ++- client/webserver/site/src/js/wallets.ts | 77 ++++++++++++++++----- 11 files changed, 163 insertions(+), 41 deletions(-) diff --git a/client/core/bond.go b/client/core/bond.go index 02a1bffb28..4eafd3fa7e 100644 --- a/client/core/bond.go +++ b/client/core/bond.go @@ -1771,15 +1771,16 @@ func (c *Core) makeAndPostBond(dc *dexConnection, acctExists bool, wallet *xcWal coinIDString(bond.AssetID, bondCoinCast), bondCoinStr) } + // Set up the coin waiter, which watches confirmations so the user knows + // when to expect their account to be marked paid by the server. + c.monitorBondConfs(dc, bond, reqConfs) + c.updateAssetBalance(bond.AssetID) // Start waiting for reqConfs. subject, details := c.formatDetails(TopicBondConfirming, reqConfs, makeCoinIDToken(bondCoinStr, bond.AssetID), unbip(bond.AssetID), dc.acct.host) c.notify(newBondPostNoteWithConfirmations(TopicBondConfirming, subject, details, db.Success, bond.AssetID, bondCoinStr, 0, dc.acct.host, c.exchangeAuth(dc))) - // Set up the coin waiter, which watches confirmations so the user knows - // when to expect their account to be marked paid by the server. - c.monitorBondConfs(dc, bond, reqConfs) return bond.CoinID, nil } diff --git a/client/webserver/locales/en-us.go b/client/webserver/locales/en-us.go index 4e096a7a65..5f1787c83d 100644 --- a/client/webserver/locales/en-us.go +++ b/client/webserver/locales/en-us.go @@ -524,6 +524,11 @@ var EnUS = map[string]string{ "fee": "Fee", "tx_id": "Transaction ID", "bond_id": "Bond ID", + "change_bond_id": "Change Bond ID", + "value": "Value", + "replaced_bonds": "Replaced Bonds", + "change_bond_tooltip": `The new bond required is smaller than the combined value of the replaced bonds, so a change bond that can be refunded sooner is created.`, + "replaced_bonds_tooptip": "This asset allows existing bonds to fund new bonds without having to be refunded first.", "locktime": "Lock Time", "recipient": "Recipient", "block": "Block", diff --git a/client/webserver/site/src/css/wallets.scss b/client/webserver/site/src/css/wallets.scss index 9f1cd8f706..8be6f2ec9b 100644 --- a/client/webserver/site/src/css/wallets.scss +++ b/client/webserver/site/src/css/wallets.scss @@ -370,7 +370,11 @@ transition: color 1s ease; } -#txDetailsBondSection, #txDetailsRecipientSection, #txDetailsNonceSection { +#txDetailsBondSection, +#txDetailsRecipientSection, +#txDetailsNonceSection, +#txDetailsChangeBondSection, +#txDetailsReplacedBondsSection { margin-top: 10px; padding-top: 10px; border-top: 1px solid #777; diff --git a/client/webserver/site/src/html/wallets.tmpl b/client/webserver/site/src/html/wallets.tmpl index 958c6bfff3..44e2f7cb29 100644 --- a/client/webserver/site/src/html/wallets.tmpl +++ b/client/webserver/site/src/html/wallets.tmpl @@ -1011,19 +1011,47 @@
+ + [[[Account ID]]] +
+
[[[bond_id]]]
+ + [[[value]]] +
+
[[[locktime]]] - - [[[Account ID]]] -
+
+
+ + [[[change_bond_id]]] +
+
+ + [[[value]]] +
+
+ + [[[locktime]]] +
+
+ + [[[replaced_bonds]]] + +
+ + + +
+
[[[nonce]]] diff --git a/client/webserver/site/src/js/dexsettings.ts b/client/webserver/site/src/js/dexsettings.ts index 6fcc0cc32f..b758fb7632 100644 --- a/client/webserver/site/src/js/dexsettings.ts +++ b/client/webserver/site/src/js/dexsettings.ts @@ -4,7 +4,7 @@ import State from './state' import { postJSON } from './http' import * as forms from './forms' import * as intl from './locales' -import { ReputationMeter, strongTier } from './account' +import { ReputationMeter, strongTier, bondReserveMultiplier } from './account' import { app, PageElement, @@ -13,6 +13,7 @@ import { PasswordCache, WalletState } from './registry' +import { traitBondUpdater } from './wallets' interface Animator { animate: (() => Promise) @@ -229,11 +230,21 @@ export default class DexSettingsPage extends BasePage { return } } - if (wallet.synced && wallet.balance.available >= 2 * bondAsset.amount + fees) { - // If we are raising our tier, we'll show a confirmation form + + const isBondUpdater = (wallet.traits & traitBondUpdater) !== 0 + + let multiplier = bondReserveMultiplier + if (isBondUpdater) multiplier = 1 + const walletFunded = wallet.balance.available >= multiplier * bondAsset.amount + fees + + const loweringTier = this.confirmRegisterForm.tier < xc.auth.targetTier + const stillSameUpdater = isBondUpdater && (xc.auth.bondAssetID === assetID) + + if (wallet.synced && (walletFunded || loweringTier || stillSameUpdater)) { this.progressTierFormWithSyncedFundedWallet(assetID) return } + this.walletWaitForm.setWallet(assetID, fees, this.confirmRegisterForm.tier) this.showForm(page.walletWait) } @@ -477,7 +488,9 @@ export default class DexSettingsPage extends BasePage { const bondsFeeBuffer = await this.getBondsFeeBuffer(assetID, page.newWalletForm) this.confirmRegisterForm.setFees(assetID, bondsFeeBuffer) - if (wallet.synced && wallet.balance.available >= 2 * bondAmt + bondsFeeBuffer) { + let multiplier = bondReserveMultiplier + if ((wallet.traits & traitBondUpdater) !== 0) multiplier = 1 + if (wallet.synced && wallet.balance.available >= multiplier * bondAmt + bondsFeeBuffer) { this.progressTierFormWithSyncedFundedWallet(assetID) return } diff --git a/client/webserver/site/src/js/forms.ts b/client/webserver/site/src/js/forms.ts index 2b2abde0ad..a73b3c8554 100644 --- a/client/webserver/site/src/js/forms.ts +++ b/client/webserver/site/src/js/forms.ts @@ -32,6 +32,7 @@ import { CoreNote } from './registry' import { XYRangeHandler } from './opts' +import { traitNewAddresser, traitBondUpdater } from './wallets' interface ConfigOptionInput extends HTMLInputElement { configOpt: ConfigOption @@ -838,7 +839,9 @@ export class ConfirmRegistrationForm { const page = this.page const xc = this.xc const bondAsset = xc.bondAssets[asset.symbol] - const bondLock = bondAsset.amount * tier * bondReserveMultiplier + let multiplier = bondReserveMultiplier + if (asset.wallet && (asset.wallet.traits & traitBondUpdater) !== 0) multiplier = 1 + const bondLock = bondAsset.amount * tier * multiplier const bondLockConventional = bondLock / conversionFactor page.tradingTier.textContent = String(tier) page.logo.src = Doc.logoPath(asset.symbol) @@ -1109,7 +1112,9 @@ export class FeeAssetSelectionForm { return } setReadyMessage(tmpl.ready, asset) - const bondLock = bondAsset.amount * bondReserveMultiplier * tier + let multiplier = bondReserveMultiplier + if (asset.wallet && (asset.wallet.traits & traitBondUpdater) !== 0) multiplier = 1 + const bondLock = bondAsset.amount * multiplier * tier const fee = Doc.formatCoinValue(bondLock, unitInfo) tmpl.feeAmt.textContent = String(fee) if (r) tmpl.fiatBondAmount.textContent = Doc.formatFiatConversion(bondLock, r, asset.unitInfo) @@ -1290,7 +1295,9 @@ export class WalletWaitForm { Doc.hide(page.syncUncheck, page.syncCheck, page.balUncheck, page.balCheck, page.syncRemainBox, page.bondCostBreakdown) Doc.show(page.balanceBox) - let bondLock = 2 * bondAsset.amount * tier + let multiplier = bondReserveMultiplier + if ((asset.wallet.traits & traitBondUpdater) !== 0) multiplier = 1 + let bondLock = multiplier * bondAsset.amount * tier if (bondFeeBuffer > 0) { Doc.show(page.bondCostBreakdown) page.bondLockNoFees.textContent = Doc.formatCoinValue(bondLock, ui) @@ -1321,7 +1328,7 @@ export class WalletWaitForm { } Doc.show(synced ? page.syncCheck : syncProgress >= 1 ? page.syncSpinner : page.syncUncheck) - Doc.show(bal.available >= 2 * bondAsset.amount + bondFeeBuffer ? page.balCheck : page.balUncheck) + Doc.show(bal.available >= multiplier * bondAsset.amount + bondFeeBuffer ? page.balCheck : page.balUncheck) page.progress.textContent = (syncProgress * 100).toFixed(1) @@ -1364,7 +1371,9 @@ export class WalletWaitForm { // NOTE: when/if we allow one-time bond post (no maintenance) from the UI we // may allow to proceed as long as they have enough for tx fees. For now, // the balance check box will remain unchecked and we will not proceed. - if (avail < 2 * this.bondAsset.amount + this.bondFeeBuffer) return + let multiplier = bondReserveMultiplier + if ((asset.wallet.traits & traitBondUpdater) !== 0) multiplier = 1 + if (avail < multiplier * this.bondAsset.amount + this.bondFeeBuffer) return Doc.show(page.balCheck) Doc.hide(page.balUncheck, page.balanceBox, page.sendEnough) @@ -1968,8 +1977,6 @@ export class LoginForm { } } -const traitNewAddresser = 1 << 1 - /* * DepositAddress displays a deposit address, a QR code, and a button to * generate a new address (if supported). diff --git a/client/webserver/site/src/js/locales.ts b/client/webserver/site/src/js/locales.ts index 83bae05c89..62173cc866 100644 --- a/client/webserver/site/src/js/locales.ts +++ b/client/webserver/site/src/js/locales.ts @@ -174,6 +174,7 @@ export const ID_TX_TYPE_REVOKE_TOKEN_APPROVAL = 'TX_TYPE_REVOKE_TOKEN_APPROVAL' export const ID_TX_TYPE_TICKET_PURCHASE = 'TX_TYPE_TICKET_PURCHASE' export const ID_TX_TYPE_TICKET_VOTE = 'TX_TYPE_TICKET_VOTE' export const ID_TX_TYPE_TICKET_REVOCATION = 'TX_TYPE_TICKET_REVOCATION' +export const ID_TX_TYPE_UPDATE_BOND = 'TX_TYPE_UPDATE_BOND' export const ID_MISSING_CEX_CREDS = 'MISSING_CEX_CREDS' export const ID_MULTIPLIER = 'MULTIPLIER' export const ID_NO_PLACEMENTS = 'NO_PLACEMENTS' @@ -360,6 +361,7 @@ export const enUS: Locale = { [ID_TX_TYPE_TICKET_PURCHASE]: 'Ticket purchase', [ID_TX_TYPE_TICKET_VOTE]: 'Ticket vote', [ID_TX_TYPE_TICKET_REVOCATION]: 'Ticket revocation', + [ID_TX_TYPE_UPDATE_BOND]: 'Update bond', [ID_MISSING_CEX_CREDS]: 'specify both key and secret', [ID_MULTIPLIER]: 'Multiplier', [ID_NO_PLACEMENTS]: 'must specify 1 or more placements', diff --git a/client/webserver/site/src/js/register.ts b/client/webserver/site/src/js/register.ts index 061bcae4dd..59f4a61142 100644 --- a/client/webserver/site/src/js/register.ts +++ b/client/webserver/site/src/js/register.ts @@ -19,6 +19,8 @@ import { PageElement } from './registry' import State from './state' +import { bondReserveMultiplier } from './account' +import { traitBondUpdater } from './wallets' export default class RegistrationPage extends BasePage { body: HTMLElement @@ -101,7 +103,9 @@ export default class RegistrationPage extends BasePage { const bondAsset = this.currentDEX.bondAssets[asset.symbol] const bondsFeeBuffer = await this.getBondsFeeBuffer(assetID, page.regAssetForm) this.confirmRegisterForm.setAsset(assetID, tier, bondsFeeBuffer) - if (wallet.synced && wallet.balance.available >= 2 * bondAsset.amount + bondsFeeBuffer) { + let multiplier = bondReserveMultiplier + if ((wallet.traits & traitBondUpdater) !== 0) multiplier = 1 + if (wallet.synced && wallet.balance.available >= multiplier * bondAsset.amount + bondsFeeBuffer) { this.animateConfirmForm(page.regAssetForm) return } @@ -216,7 +220,9 @@ export default class RegistrationPage extends BasePage { const bondAmt = this.currentDEX.bondAssets[asset.symbol].amount const bondsFeeBuffer = await this.getBondsFeeBuffer(assetID, page.newWalletForm) - if (wallet.synced && wallet.balance.available >= 2 * bondAmt + bondsFeeBuffer) { + let multiplier = bondReserveMultiplier + if ((wallet.traits & traitBondUpdater) !== 0) multiplier = 1 + if (wallet.synced && wallet.balance.available >= multiplier * bondAmt + bondsFeeBuffer) { await this.animateConfirmForm(page.newWalletForm) return } diff --git a/client/webserver/site/src/js/registry.ts b/client/webserver/site/src/js/registry.ts index 1eea588fe3..bca22e5837 100644 --- a/client/webserver/site/src/js/registry.ts +++ b/client/webserver/site/src/js/registry.ts @@ -891,10 +891,17 @@ export interface VotingServiceProvider { netShare: number } -export interface BondTxInfo { - bondID: string +export interface BondInfo { + id : string + amount: number lockTime: number +} + +export interface BondTxInfo { accountID: string + bond: BondInfo + changeBond?: BondInfo + replacedBond?: BondInfo[] } export interface WalletTransaction { diff --git a/client/webserver/site/src/js/settings.ts b/client/webserver/site/src/js/settings.ts index 695633ba3e..c71cecd18f 100644 --- a/client/webserver/site/src/js/settings.ts +++ b/client/webserver/site/src/js/settings.ts @@ -17,6 +17,8 @@ import { PageElement, PasswordCache } from './registry' +import { bondReserveMultiplier } from './account' +import { traitBondUpdater } from './wallets' const animationLength = 300 @@ -89,7 +91,9 @@ export default class SettingsPage extends BasePage { const bondAsset = this.currentDEX.bondAssets[asset.symbol] const bondsFeeBuffer = await this.getBondsFeeBuffer(assetID, page.regAssetForm) this.confirmRegisterForm.setAsset(assetID, tier, bondsFeeBuffer) - if (wallet.synced && wallet.balance.available >= 2 * bondAsset.amount + bondsFeeBuffer) { + let multiplier = bondReserveMultiplier + if ((wallet.traits & traitBondUpdater) !== 0) multiplier = 1 + if (wallet.synced && wallet.balance.available >= multiplier * bondAsset.amount + bondsFeeBuffer) { this.animateConfirmForm(page.regAssetForm) return } @@ -269,7 +273,9 @@ export default class SettingsPage extends BasePage { const bondsFeeBuffer = await this.getBondsFeeBuffer(assetID, page.newWalletForm) this.confirmRegisterForm.setFees(assetID, bondsFeeBuffer) - if (wallet.synced && wallet.balance.available >= 2 * bondAmt + bondsFeeBuffer) { + let multiplier = bondReserveMultiplier + if ((wallet.traits & traitBondUpdater) !== 0) multiplier = 1 + if (wallet.synced && wallet.balance.available >= multiplier * bondAmt + bondsFeeBuffer) { await this.animateConfirmForm(page.newWalletForm) return } diff --git a/client/webserver/site/src/js/wallets.ts b/client/webserver/site/src/js/wallets.ts index a822b7e5c2..1bdf449f2a 100644 --- a/client/webserver/site/src/js/wallets.ts +++ b/client/webserver/site/src/js/wallets.ts @@ -60,16 +60,18 @@ interface TicketPurchaseUpdate extends BaseWalletNote { } const animationLength = 300 -const traitRescanner = 1 -const traitLogFiler = 1 << 2 -const traitRecoverer = 1 << 5 -const traitWithdrawer = 1 << 6 -const traitRestorer = 1 << 8 -const traitTxFeeEstimator = 1 << 9 -const traitPeerManager = 1 << 10 -const traitTokenApprover = 1 << 13 -const traitTicketBuyer = 1 << 15 -const traitFundsMixer = 1 << 17 +export const traitRescanner = 1 +export const traitNewAddresser = 1 << 1 +export const traitLogFiler = 1 << 2 +export const traitRecoverer = 1 << 5 +export const traitWithdrawer = 1 << 6 +export const traitRestorer = 1 << 8 +export const traitTxFeeEstimator = 1 << 9 +export const traitPeerManager = 1 << 10 +export const traitTokenApprover = 1 << 13 +export const traitTicketBuyer = 1 << 15 +export const traitFundsMixer = 1 << 17 +export const traitBondUpdater = 1 << 18 const traitsExtraOpts = traitLogFiler & traitRecoverer & traitRestorer & traitRescanner & traitPeerManager & traitTokenApprover @@ -111,6 +113,7 @@ const txTypeRevokeTokenApproval = 12 const txTypeTicketPurchase = 13 const txTypeTicketVote = 14 const txTypeTicketRevocation = 15 +const txTypeUpdateBond = 16 const positiveTxTypes : number[] = [ txTypeReceive, @@ -125,7 +128,8 @@ const negativeTxTypes : number[] = [ txTypeSend, txTypeSwap, txTypeCreateBond, - txTypeTicketPurchase + txTypeTicketPurchase, + txTypeUpdateBond ] const noAmtTxTypes : number[] = [ @@ -157,7 +161,8 @@ const txTypeTranslationKeys = [ intl.ID_TX_TYPE_REVOKE_TOKEN_APPROVAL, intl.ID_TX_TYPE_TICKET_PURCHASE, intl.ID_TX_TYPE_TICKET_VOTE, - intl.ID_TX_TYPE_TICKET_REVOCATION + intl.ID_TX_TYPE_TICKET_REVOCATION, + intl.ID_TX_TYPE_UPDATE_BOND ] const ticketPageSize = 10 @@ -232,7 +237,7 @@ export default class WalletsPage extends BasePage { const page = this.page = Doc.idDescendants(body) net = app().user.net - Doc.cleanTemplates(page.restoreInfoCard, page.connectedIconTmpl, page.disconnectedIconTmpl, page.removeIconTmpl) + Doc.cleanTemplates(page.restoreInfoCard, page.connectedIconTmpl, page.disconnectedIconTmpl, page.removeIconTmpl, page.replacedBondTmpl) this.restoreInfoCard = page.restoreInfoCard.cloneNode(true) as HTMLElement Doc.show(page.connectedIconTmpl, page.disconnectedIconTmpl, page.removeIconTmpl) @@ -261,7 +266,8 @@ export default class WalletsPage extends BasePage { Doc.bind(page.copyTxIDBtn, 'click', () => { this.copyTxDetail(this.currTx?.id || '', page.txDetailsID, page.copyTxIDBtn) }) Doc.bind(page.copyRecipientBtn, 'click', () => { this.copyTxDetail(this.currTx?.recipient || '', page.txDetailsRecipient, page.copyRecipientBtn) }) - Doc.bind(page.copyBondIDBtn, 'click', () => { this.copyTxDetail(this.currTx?.bondInfo?.bondID || '', page.txDetailsBondID, page.copyBondIDBtn) }) + Doc.bind(page.copyBondIDBtn, 'click', () => { this.copyTxDetail(this.currTx?.bondInfo?.bond.id || '', page.txDetailsBondID, page.copyBondIDBtn) }) + Doc.bind(page.copyChangeBondIDBtn, 'click', () => { this.copyTxDetail(this.currTx?.bondInfo?.changeBond?.id || '', page.txDetailsChangeBondID, page.copyChangeBondIDBtn) }) Doc.bind(page.copyBondAccountIDBtn, 'click', () => { this.copyTxDetail(this.currTx?.bondInfo?.accountID || '', page.txDetailsBondAccountID, page.copyBondAccountIDBtn) }) // Bind the new wallet form. @@ -1837,19 +1843,56 @@ export default class WalletsPage extends BasePage { // Bond Info if (tx.bondInfo) { Doc.show(page.txDetailsBondSection) - page.txDetailsBondID.textContent = trimStringWithEllipsis(tx.bondInfo.bondID, 20) - page.txDetailsBondID.setAttribute('title', tx.bondInfo.bondID) - const date = new Date(tx.bondInfo.lockTime * 1000) + page.txDetailsBondID.textContent = trimStringWithEllipsis(tx.bondInfo.bond.id, 20) + page.txDetailsBondID.setAttribute('title', tx.bondInfo.bond.id) + const date = new Date(tx.bondInfo.bond.lockTime * 1000) const dateStr = date.toLocaleDateString() const timeStr = date.toLocaleTimeString() page.txDetailsBondLocktime.textContent = `${dateStr} ${timeStr}` Doc.setVis(tx.bondInfo.accountID !== '', page.txDetailsBondAccountIDSection) page.txDetailsBondAccountID.textContent = trimStringWithEllipsis(tx.bondInfo.accountID, 20) page.txDetailsBondAccountID.setAttribute('title', tx.bondInfo.accountID) + const value = Doc.formatCoinValue(tx.bondInfo.bond.amount, app().unitInfo(this.selectedAssetID)) + const unit = app().assets[this.selectedAssetID].symbol.split('.')[0].toUpperCase() + page.txDetailsBondValue.textContent = `${value} ${unit}` } else { Doc.hide(page.txDetailsBondSection) } + // Change Bond + if (tx.bondInfo && tx.bondInfo.changeBond) { + Doc.show(page.txDetailsChangeBondSection) + page.txDetailsChangeBondID.textContent = trimStringWithEllipsis(tx.bondInfo.changeBond.id, 20) + page.txDetailsChangeBondID.setAttribute('title', tx.bondInfo.changeBond.id) + const date = new Date(tx.bondInfo.changeBond.lockTime * 1000) + const dateStr = date.toLocaleDateString() + const timeStr = date.toLocaleTimeString() + page.txDetailsChangeBondLocktime.textContent = `${dateStr} ${timeStr}` + const value = Doc.formatCoinValue(tx.bondInfo.changeBond.amount, app().unitInfo(this.selectedAssetID)) + const unit = app().assets[this.selectedAssetID].symbol.split('.')[0].toUpperCase() + page.txDetailsChangeBondValue.textContent = `${value} ${unit}` + } else { + Doc.hide(page.txDetailsChangeBondSection) + } + + // Replaced bonds + if (tx.bondInfo?.replacedBond && tx.bondInfo.replacedBond.length > 0) { + Doc.show(page.txDetailsReplacedBondsSection) + Doc.empty(page.replacedBonds) + const unit = app().assets[this.selectedAssetID].symbol.split('.')[0].toUpperCase() + for (const bond of tx.bondInfo.replacedBond) { + console.log(bond) + const row = page.replacedBondTmpl.cloneNode(true) as PageElement + page.replacedBonds.appendChild(row) + const tmpl = Doc.parseTemplate(row) + const amt = Doc.formatCoinValue(bond.amount, app().unitInfo(this.selectedAssetID)) + tmpl.info.textContent = `${trimStringWithEllipsis(bond.id, 20)} (${amt} ${unit})` + tmpl.info.setAttribute('title', bond.id) + } + } else { + Doc.hide(page.txDetailsReplacedBondsSection) + } + // Nonce if (tx.additionalData && tx.additionalData.Nonce) { Doc.show(page.txDetailsNonceSection)