diff --git a/.gitignore b/.gitignore index d7393dfc..41017a1e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ node_modules *.tgz dist .env +out +cache +tmp +ts-build diff --git a/deployment/.gitignore b/deployment/.gitignore new file mode 100644 index 00000000..4da2edd1 --- /dev/null +++ b/deployment/.gitignore @@ -0,0 +1,2 @@ +contract-bindings +**.env \ No newline at end of file diff --git a/deployment/README.md b/deployment/README.md new file mode 100644 index 00000000..08d98721 --- /dev/null +++ b/deployment/README.md @@ -0,0 +1,39 @@ +# Contracts scrips + +### Before start + +- Install & Build + +``` +npm ci +npm run build-evm +``` + +- Add the desired networks where you want to work on the [ecosystem file](./config/testnet/ecosystem.json) with the format: + +``` +type ChainInfo = { + name: string; + chainId: number; // EVM ChainId + rpc: string; + type: "Mainnet" | "Testnet" | "Devnet"; + externalId?: string; +} +``` + +- Configure the dependencies on the [dependencies file](./config/testnet/dependencies.json). + +- Add the config for each chain in the [MatchingEngine](./config/testnet/matching-engine.json) config file or the [TokenRouter](./config/testnet/token-router.json) config file. + + +### EVM scripts + +``` +npx tsx ./scripts/evm//.ts +``` + +### Solana scripts + +``` +npx tsx ./scripts/solana//.ts +``` \ No newline at end of file diff --git a/deployment/config/config-types.ts b/deployment/config/config-types.ts new file mode 100644 index 00000000..2bff6cd0 --- /dev/null +++ b/deployment/config/config-types.ts @@ -0,0 +1,99 @@ +import { ChainId } from "@wormhole-foundation/sdk-base"; + +// TODO: check if solana has different needs for the TokenRouter +export type TokenRouterConfiguration = { + // Wormhole Chain ID of the token router configuration + chainId: ChainId; + + // Mutable values + /** + * Account with the authority to add + * new token routers among other operations. + */ + ownerAssistant: string; + fastTransferParameters: { + enabled: boolean; + /** + * Expressed in μUSDC. + * E.g. 1000000000 is 1000 USDC. + */ + maxAmount: string; + /** + * Expressed in μUSDC. + * E.g. 1250000 is 1.25 USDC. + */ + baseFee: string; + /** + * Expressed in μUSDC. + * E.g. 950000 is 0.95 USDC. + */ + initAuctionFee: string; + }; + cctpAllowance: string; + disableRouterEndpoints?: ChainId[]; +}; + +export type MatchingEngineConfiguration = { + /** + * Wormhole Chain ID of the matching engine configuration + */ + chainId: ChainId; + + // Immutable values + /** + * The part of the penalty that is awarded to the user when the auction is completed. + * E.g. 400000 is 40%. + */ + userPenaltyRewardBps: string; + /** + * The initial penalty proportion that is incurred once the grace period is over. + * E.g. 250000 is 25%. + */ + initialPenaltyBps: string; + /** + * Auction duration in Solana slots. + */ + auctionDuration: string; + /** + * Auction grace period in Solana slots. + * The grace period of the auction in slots. This is the number of slots the highest bidder + * has to execute the fast order before incurring a penalty. + * This value INCLUDES the `auctionDuration`. + */ + auctionGracePeriod: string; + /** + * The `securityDeposit` decays over this period. + * Expressed in Solana slots. + */ + auctionPenaltySlots: string; + /** + * minimum offer increment for auctions. + * New offers need to surpass a threshold given by this parameter. + * E.g. 50000 is 5%. + */ + minOfferDeltaBps: string; + /** + * The base security deposit, which will the the additional amount an auction participant must + * deposit to participate in an auction. Expressed in μUSDC. + * E.g. 1000000 is 1 USDC. + */ + securityDepositBase: string; + /** + * Additional security deposit based on the notional of the order amount. + * E.g. 5000 is 0.5%. + */ + securityDepositBps: string; + + // Mutable values + /** + * Solana account with the authority to add + * new token routers among other operations. + */ + ownerAssistant: string; + /** + * Fee recipient for relayer service of slow orders, i.e. those that do not + * have an associated auction. + */ + feeRecipient: string; + cctpAllowance: string; +}; \ No newline at end of file diff --git a/deployment/config/mainnet/contracts.json b/deployment/config/mainnet/contracts.json new file mode 100644 index 00000000..504b16dc --- /dev/null +++ b/deployment/config/mainnet/contracts.json @@ -0,0 +1,142 @@ +{ + "TokenRouterProxy": [ + { + "chainId": 1, + "address": "28topqjtJzMnPaGFmmZk68tzGmj9W9aMntaEK3QkgtRe" + }, + { + "chainId": 30, + "address": "0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47", + "constructorArgs": [ + "0xE33C682aA6F7F6E31F0E861aAcCd7dB9C002B965", + "0x439fab9100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000014420e8aa32c31626f7f31d6fcc154eeccd6e6e9cb000000000000000000000000" + ] + }, + { + "chainId": 23, + "address": "0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47", + "constructorArgs": [ + "0xE33C682aA6F7F6E31F0E861aAcCd7dB9C002B965", + "0x439fab9100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000014420e8aa32c31626f7f31d6fcc154eeccd6e6e9cb000000000000000000000000" + ] + }, + { + "chainId": 24, + "address": "0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47", + "constructorArgs": [ + "0xE33C682aA6F7F6E31F0E861aAcCd7dB9C002B965", + "0x439fab9100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000014420e8aa32c31626f7f31d6fcc154eeccd6e6e9cb000000000000000000000000" + ] + }, + { + "chainId": 6, + "address": "0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47", + "constructorArgs": [ + "0xE33C682aA6F7F6E31F0E861aAcCd7dB9C002B965", + "0x439fab9100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000014420e8aa32c31626f7f31d6fcc154eeccd6e6e9cb000000000000000000000000" + ] + }, + { + "chainId": 2, + "address": "0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47", + "constructorArgs": [ + "0xE33C682aA6F7F6E31F0E861aAcCd7dB9C002B965", + "0x439fab9100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000014420e8aa32c31626f7f31d6fcc154eeccd6e6e9cb000000000000000000000000" + ] + }, + { + "chainId": 5, + "address": "0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47", + "constructorArgs": [ + "0xE33C682aA6F7F6E31F0E861aAcCd7dB9C002B965", + "0x439fab9100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000014420e8aa32c31626f7f31d6fcc154eeccd6e6e9cb000000000000000000000000" + ] + } + ], + "UpgradeManager": [ + { + "chainId": 1, + "address": "4jyJ7EEsYa72REdD8ZMBvHFTXZ4VYGQPUHaJTajsK8SN" + } + ], + "TokenRouterImplementation": [ + { + "chainId": 30, + "address": "0xB2BCa2A79f7C99aA684A14303d368ffDbc4307e9", + "constructorArgs": [ + "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6", + "0x1682Ae6375C4E4A97e4B583BC394c861A46D8962", + 1, + "0x74e70ed52464f997369bbefd141d8a2d9dd3cd15e1f21b37bce18f45e0e923b2", + "0xf4c8473a0e8fb093ca12970ed615db09f7ebbbb3d00f40b3e285e12f40e5c9a6", + 5 + ] + }, + { + "chainId": 23, + "address": "0xB2BCa2A79f7C99aA684A14303d368ffDbc4307e9", + "constructorArgs": [ + "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", + "0xa5f208e072434bC67592E4C49C1B991BA79BCA46", + "0x19330d10D9Cc8751218eaf51E8885D058642E08A", + 1, + "0x74e70ed52464f997369bbefd141d8a2d9dd3cd15e1f21b37bce18f45e0e923b2", + "0xf4c8473a0e8fb093ca12970ed615db09f7ebbbb3d00f40b3e285e12f40e5c9a6", + 5 + ] + }, + { + "chainId": 2, + "address": "0xE33C682aA6F7F6E31F0E861aAcCd7dB9C002B965", + "constructorArgs": [ + "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B", + "0xBd3fa81B58Ba92a82136038B25aDec7066af3155", + 1, + "0x74e70ed52464f997369bbefd141d8a2d9dd3cd15e1f21b37bce18f45e0e923b2", + "0xf4c8473a0e8fb093ca12970ed615db09f7ebbbb3d00f40b3e285e12f40e5c9a6", + 5 + ] + }, + { + "chainId": 6, + "address": "0xE33C682aA6F7F6E31F0E861aAcCd7dB9C002B965", + "constructorArgs": [ + "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", + "0x54a8e5f9c4CbA08F9943965859F6c34eAF03E26c", + "0x6B25532e1060CE10cc3B0A99e5683b91BFDe6982", + 1, + "0x74e70ed52464f997369bbefd141d8a2d9dd3cd15e1f21b37bce18f45e0e923b2", + "0xf4c8473a0e8fb093ca12970ed615db09f7ebbbb3d00f40b3e285e12f40e5c9a6", + 5 + ] + }, + { + "chainId": 24, + "address": "0xE33C682aA6F7F6E31F0E861aAcCd7dB9C002B965", + "constructorArgs": [ + "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", + "0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722", + "0x2B4069517957735bE00ceE0fadAE88a26365528f", + 1, + "0x74e70ed52464f997369bbefd141d8a2d9dd3cd15e1f21b37bce18f45e0e923b2", + "0xf4c8473a0e8fb093ca12970ed615db09f7ebbbb3d00f40b3e285e12f40e5c9a6", + 5 + ] + }, + { + "chainId": 5, + "address": "0xE33C682aA6F7F6E31F0E861aAcCd7dB9C002B965", + "constructorArgs": [ + "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", + "0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7", + "0x9daF8c91AEFAE50b9c0E69629D3F6Ca40cA3B3FE", + 1, + "0x74e70ed52464f997369bbefd141d8a2d9dd3cd15e1f21b37bce18f45e0e923b2", + "0xf4c8473a0e8fb093ca12970ed615db09f7ebbbb3d00f40b3e285e12f40e5c9a6", + 5 + ] + } + ] +} \ No newline at end of file diff --git a/deployment/config/mainnet/dependencies.json b/deployment/config/mainnet/dependencies.json new file mode 100644 index 00000000..518cfa9c --- /dev/null +++ b/deployment/config/mainnet/dependencies.json @@ -0,0 +1,44 @@ +[ + { + "chainId": 1, + "matchingEngineProxy": "HtkeCDdYY4i9ncAxXKjYTx8Uu3WM8JbtiLRYjtHwaVXb", + "custodianMatchingEngine": "8sLeDrpnUfSv69KXzKMKMVTpxP7D8iPue5QrHJgyu5XP", + "matchingEngineMintRecipient": "HUXc7MBf55vWrrkevVbmJN8HAyfFtjLcPLBt9yWngKzm" + }, + { + "chainId": 2, + "wormhole": "0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B", + "token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "tokenMessenger": "0xBd3fa81B58Ba92a82136038B25aDec7066af3155" + }, + { + "chainId": 5, + "wormhole": "0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7", + "token": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", + "tokenMessenger": "0x9daF8c91AEFAE50b9c0E69629D3F6Ca40cA3B3FE" + }, + { + "chainId": 6, + "wormhole": "0x54a8e5f9c4CbA08F9943965859F6c34eAF03E26c", + "token": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", + "tokenMessenger": "0x6B25532e1060CE10cc3B0A99e5683b91BFDe6982" + }, + { + "chainId": 23, + "wormhole": "0xa5f208e072434bC67592E4C49C1B991BA79BCA46", + "token": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", + "tokenMessenger": "0x19330d10D9Cc8751218eaf51E8885D058642E08A" + }, + { + "chainId": 24, + "wormhole": "0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722", + "token": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", + "tokenMessenger": "0x2B4069517957735bE00ceE0fadAE88a26365528f" + }, + { + "chainId": 30, + "wormhole": "0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6", + "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "tokenMessenger": "0x1682Ae6375C4E4A97e4B583BC394c861A46D8962" + } +] \ No newline at end of file diff --git a/deployment/config/mainnet/ecosystem.json b/deployment/config/mainnet/ecosystem.json new file mode 100644 index 00000000..4938b455 --- /dev/null +++ b/deployment/config/mainnet/ecosystem.json @@ -0,0 +1,59 @@ +{ + "operatingChains": [1], + "evm": { + "networks": [ + { + "name": "Ethereum", + "network": "Mainnet", + "externalId": "1", + "chainId": 2, + "rpc": "https://rpc.ankr.com/eth" + }, + { + "name": "Polygon", + "network": "Mainnet", + "externalId": "137", + "chainId": 5, + "rpc": "https://rpc.ankr.com/polygon" + }, + { + "name": "Avalanche", + "network": "Mainnet", + "externalId": "43114", + "chainId": 6, + "rpc": "https://rpc.ankr.com/avalanche" + }, + { + "name": "Arbitrum", + "network": "Mainnet", + "externalId": "42161", + "chainId": 23, + "rpc": "https://rpc.ankr.com/arbitrum" + }, + { + "name": "Optimism", + "network": "Mainnet", + "externalId": "10", + "chainId": 24, + "rpc": "https://rpc.ankr.com/optimism" + }, + { + "name": "Base", + "network": "Mainnet", + "externalId": "8453", + "chainId": 30, + "rpc": "https://mainnet.base.org" + } + ] + }, + "solana": { + "networks": [ + { + "name": "Solana", + "network": "Mainnet", + "chainId": 1, + "rpc": "https://api.mainnet-beta.solana.com" + } + ] + } +} \ No newline at end of file diff --git a/deployment/config/mainnet/matching-engine.json b/deployment/config/mainnet/matching-engine.json new file mode 100644 index 00000000..4ea472c4 --- /dev/null +++ b/deployment/config/mainnet/matching-engine.json @@ -0,0 +1,16 @@ +[ + { + "chainId": 1, + "ownerAssistant": "DNuVesmYQizpEVXYJZGECSeshqAxHB4fbqX2UC6ehpK4", + "feeRecipient": "AdAVF5KmmGmpNQhjY7FL96wZLEynD6Mx3VXJTZf2yFps", + "userPenaltyRewardBps": "100", + "initialPenaltyBps": "100", + "auctionDuration": "10", + "auctionGracePeriod": "20", + "auctionPenaltySlots": "20", + "minOfferDeltaBps": "50000", + "securityDepositBase": "1000000", + "securityDepositBps": "1000", + "cctpAllowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935" + } +] \ No newline at end of file diff --git a/deployment/config/mainnet/token-router.json b/deployment/config/mainnet/token-router.json new file mode 100644 index 00000000..0ff350ad --- /dev/null +++ b/deployment/config/mainnet/token-router.json @@ -0,0 +1,79 @@ +[ + { + "chainId": 1, + "ownerAssistant": "DNuVesmYQizpEVXYJZGECSeshqAxHB4fbqX2UC6ehpK4", + "fastTransferParameters": { + "enabled": true, + "maxAmount": "1000000000", + "baseFee": "1250000", + "initAuctionFee": "950000" + }, + "cctpAllowance": "18446744073709551615" + }, + { + "chainId": 2, + "ownerAssistant": "0x420E8AA32c31626F7F31D6fcC154eeccd6E6e9cB", + "fastTransferParameters": { + "enabled": true, + "maxAmount": "1000000000", + "baseFee": "1250000", + "initAuctionFee": "950000" + }, + "cctpAllowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935" + }, + { + "chainId": 5, + "ownerAssistant": "0x420E8AA32c31626F7F31D6fcC154eeccd6E6e9cB", + "fastTransferParameters": { + "enabled": true, + "maxAmount": "1000000000", + "baseFee": "1250000", + "initAuctionFee": "950000" + }, + "cctpAllowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935" + }, + { + "chainId": 6, + "ownerAssistant": "0x420E8AA32c31626F7F31D6fcC154eeccd6E6e9cB", + "fastTransferParameters": { + "enabled": true, + "maxAmount": "1000000000", + "baseFee": "1250000", + "initAuctionFee": "950000" + }, + "cctpAllowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935" + }, + { + "chainId": 23, + "ownerAssistant": "0x420E8AA32c31626F7F31D6fcC154eeccd6E6e9cB", + "fastTransferParameters": { + "enabled": true, + "maxAmount": "1000000000", + "baseFee": "1250000", + "initAuctionFee": "950000" + }, + "cctpAllowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935" + }, + { + "chainId": 24, + "ownerAssistant": "0x420E8AA32c31626F7F31D6fcC154eeccd6E6e9cB", + "fastTransferParameters": { + "enabled": true, + "maxAmount": "1000000000", + "baseFee": "1250000", + "initAuctionFee": "950000" + }, + "cctpAllowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935" + }, + { + "chainId": 30, + "ownerAssistant": "0x420E8AA32c31626F7F31D6fcC154eeccd6E6e9cB", + "fastTransferParameters": { + "enabled": true, + "maxAmount": "1000000000", + "baseFee": "1250000", + "initAuctionFee": "950000" + }, + "cctpAllowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935" + } +] \ No newline at end of file diff --git a/deployment/config/mainnet/verification-api-keys.json b/deployment/config/mainnet/verification-api-keys.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/deployment/config/mainnet/verification-api-keys.json @@ -0,0 +1 @@ +{} diff --git a/deployment/config/testnet/chains.json b/deployment/config/testnet/chains.json new file mode 100644 index 00000000..7213ba0c --- /dev/null +++ b/deployment/config/testnet/chains.json @@ -0,0 +1,53 @@ +{ + "guardianSetIndex": 3, + "evm": { + "operatingChains": [], + "networks": [ + { + "description": "Ethereum", + "externalId": 1, + "chainId": 2, + "rpc": "https://eth.llamarpc.com" + }, + { + "description": "Polygon (amoy)", + "externalId": 80002, + "chainId": 5, + "rpc": "https://polygon-amoy-bor-rpc.publicnode.com" + }, + { + "description": "Avalanche", + "externalId": 43113, + "chainId": 6, + "rpc": "https://rpc.ankr.com/avalanche_fuji" + }, + { + "description": "Arbitrum", + "externalId": 42161, + "chainId": 23, + "rpc": "https://arbitrum.llamarpc.com" + }, + { + "description": "Optimism", + "externalId": 10, + "chainId": 24, + "rpc": "https://optimism-rpc.publicnode.com" + }, + { + "description": "Base", + "externalId": 8453, + "chainId": 30, + "rpc": "https://mainnet.base.org" + } + ] + }, + "solana": { + "networks": [ + { + "description": "Solana", + "chainId": 1, + "rpc": "https://solana.llamarpc.com" + } + ] + } +} \ No newline at end of file diff --git a/deployment/config/testnet/contracts.json b/deployment/config/testnet/contracts.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/deployment/config/testnet/contracts.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/deployment/config/testnet/dependencies.json b/deployment/config/testnet/dependencies.json new file mode 100644 index 00000000..b07e3a94 --- /dev/null +++ b/deployment/config/testnet/dependencies.json @@ -0,0 +1,38 @@ +[ + { + "chainId": 2, + "wormhole": "", + "token": "", + "tokenMessenger": "" + }, + { + "chainId": 5, + "wormhole": "", + "token": "", + "tokenMessenger": "" + }, + { + "chainId": 6, + "wormhole": "", + "token": "", + "tokenMessenger": "" + }, + { + "chainId": 23, + "wormhole": "", + "token": "", + "tokenMessenger": "" + }, + { + "chainId": 24, + "wormhole": "", + "token": "", + "tokenMessenger": "" + }, + { + "chainId": 30, + "wormhole": "", + "token": "", + "tokenMessenger": "" + } +] \ No newline at end of file diff --git a/deployment/config/testnet/ecosystem.json b/deployment/config/testnet/ecosystem.json new file mode 100644 index 00000000..1644993f --- /dev/null +++ b/deployment/config/testnet/ecosystem.json @@ -0,0 +1,9 @@ +{ + "evm": { + "operatingChains": [], + "networks": [] + }, + "solana": { + "networks": [] + } +} \ No newline at end of file diff --git a/deployment/config/testnet/matching-engine.json b/deployment/config/testnet/matching-engine.json new file mode 100644 index 00000000..7b04f2b7 --- /dev/null +++ b/deployment/config/testnet/matching-engine.json @@ -0,0 +1,62 @@ +[ + { + "chainId": 2, + "ownerAssistant": "", + "feeRecipient": "", + "userPenaltyRewardBps": "", + "initialPenaltyBps": "", + "auctionDuration": "", + "auctionGracePeriod": "", + "auctionPenaltySlots": "" + }, + { + "chainId": 5, + "ownerAssistant": "", + "feeRecipient": "", + "userPenaltyRewardBps": "", + "initialPenaltyBps": "", + "auctionDuration": "", + "auctionGracePeriod": "", + "auctionPenaltySlots": "" + }, + { + "chainId": 6, + "ownerAssistant": "", + "feeRecipient": "", + "userPenaltyRewardBps": "", + "initialPenaltyBps": "", + "auctionDuration": "", + "auctionGracePeriod": "", + "auctionPenaltySlots": "" + }, + { + "chainId": 23, + "ownerAssistant": "", + "feeRecipient": "", + "userPenaltyRewardBps": "", + "initialPenaltyBps": "", + "auctionDuration": "", + "auctionGracePeriod": "", + "auctionPenaltySlots": "" + }, + { + "chainId": 24, + "ownerAssistant": "", + "feeRecipient": "", + "userPenaltyRewardBps": "", + "initialPenaltyBps": "", + "auctionDuration": "", + "auctionGracePeriod": "", + "auctionPenaltySlots": "" + }, + { + "chainId": 30, + "ownerAssistant": "", + "feeRecipient": "", + "userPenaltyRewardBps": "", + "initialPenaltyBps": "", + "auctionDuration": "", + "auctionGracePeriod": "", + "auctionPenaltySlots": "" + } +] \ No newline at end of file diff --git a/deployment/config/testnet/token-router.json b/deployment/config/testnet/token-router.json new file mode 100644 index 00000000..d42f3e82 --- /dev/null +++ b/deployment/config/testnet/token-router.json @@ -0,0 +1,44 @@ +[ + { + "chainId": 2, + "ownerAssistant": "", + "matchingEngineMintRecipient": "", + "matchingEngineChain": "", + "matchingEngineDomain": "" + }, + { + "chainId": 5, + "ownerAssistant": "", + "matchingEngineMintRecipient": "", + "matchingEngineChain": "", + "matchingEngineDomain": "" + }, + { + "chainId": 6, + "ownerAssistant": "", + "matchingEngineMintRecipient": "", + "matchingEngineChain": "", + "matchingEngineDomain": "" + }, + { + "chainId": 23, + "ownerAssistant": "", + "matchingEngineMintRecipient": "", + "matchingEngineChain": "", + "matchingEngineDomain": "" + }, + { + "chainId": 24, + "ownerAssistant": "", + "matchingEngineMintRecipient": "", + "matchingEngineChain": "", + "matchingEngineDomain": "" + }, + { + "chainId": 30, + "ownerAssistant": "", + "matchingEngineMintRecipient": "", + "matchingEngineChain": "", + "matchingEngineDomain": "" + } +] \ No newline at end of file diff --git a/deployment/config/verification-api-keys.sample.json b/deployment/config/verification-api-keys.sample.json new file mode 100644 index 00000000..377e93f8 --- /dev/null +++ b/deployment/config/verification-api-keys.sample.json @@ -0,0 +1,7 @@ +{ + "": { "etherscan": "", "blockscout": {"key": "", "apiUrl": "https://.blockscout.com/api"}, "sourcify": ""}, + "": { "etherscan": "", "blockscout": {"key": "", "apiUrl": "https://.blockscout.com/api"}}, + "": { "blockscout": {"key": "", "apiUrl": "https://.blockscout.com/api"}, "sourcify": ""}, + "": { "etherscan": "", "sourcify": ""}, + "": { "etherscan": ""} +} diff --git a/deployment/helpers/env.ts b/deployment/helpers/env.ts new file mode 100644 index 00000000..10a0c128 --- /dev/null +++ b/deployment/helpers/env.ts @@ -0,0 +1,208 @@ +import fs from "fs"; +import { ethers, utils } from "ethers"; +import { validateSolAddress } from "./solana"; +import { ChainConfig, ChainInfo, ContractsJson, Dependencies, DependenciesConfig, Ecosystem, UncheckedConstructorArgs, VerificationApiKeys } from "./interfaces"; +import { getSigner } from "./evm"; +// TODO: support different env files +import 'dotenv/config'; +import { ChainId, Token, contracts as connectDependencies, toChain } from "@wormhole-foundation/sdk-base"; +import { getTokensBySymbol } from "@wormhole-foundation/sdk-base/tokens"; +import { MatchingEngineConfiguration } from "../config/config-types"; +import { AuctionParameters } from "../../solana/ts/src/matchingEngine/state/AuctionConfig"; +import { BN } from "@coral-xyz/anchor"; + +export const env = getEnv("ENV"); +export const contracts = loadContracts(); +export const dependencies = loadDependencies(); +export const ecosystemChains = loadEcosystem(); +export const verificationApiKeys = loadVerificationApiKeys(); +export const matchingEngineParameters = loadMatchingEngineParameters(); + +function loadJson(filename: string): T { + const fileContent = fs.readFileSync( + `./config/${env}/${filename}.json` + ); + + return JSON.parse(fileContent.toString()) as T; +} + +function loadDependencies(): DependenciesConfig[] { + return loadJson("dependencies"); +} + +function loadContracts() { + return loadJson("contracts"); +} + +function loadEcosystem(): Ecosystem { + return loadJson("ecosystem"); +} + +function loadVerificationApiKeys() { + return loadJson("verification-api-keys"); +} + +function loadMatchingEngineParameters(): MatchingEngineConfiguration[] { + return loadJson("matching-engine"); +} + +export function getEnv(env: string): string { + const v = process.env[env]; + if (!v) { + throw Error(`Env var not set: ${env}`); + } + return v; +} + +export function getChainInfo(chainId: ChainId): ChainInfo { + if (ecosystemChains.solana.networks.length > 1) { + throw Error("Unexpected number of Solana networks."); + } + + const chains = [ + ...ecosystemChains.evm.networks, + ...ecosystemChains.solana.networks, + ]; + + const chain = chains.find((c) => c.chainId === chainId); + if (chain === undefined) { + throw Error(`Failed to find chain info for chain id: ${chainId}`); + } + + return chain; +} + +export async function getChainConfig(filename: string, whChainId: ChainId): Promise { + const scriptConfig: T[] = await loadJson(filename); + + const chainConfig = scriptConfig.find((x) => x.chainId == whChainId); + + if (!chainConfig) { + throw Error(`Failed to find chain config for chain ${whChainId}`); + } + + return chainConfig; +} + +export function getContractAddress(contractName: string, whChainId: ChainId): string { + const contract = contracts[contractName]?.find((c) => c.chainId === whChainId)?.address; + + if (!contract) { + throw new Error(`No ${contractName} contract found for chain ${whChainId}`); + } + + if (!utils.isAddress(contract) && !validateSolAddress(contract)){ + throw new Error(`Invalid address for ${contractName} contract found for chain ${whChainId}`); + } + + return contract; + +} +export function getLocalDependencyAddress(dependencyName: string, chain: ChainInfo): string { + const chainDependencies = dependencies.find((d) => d.chainId === chain.chainId); + + if (chainDependencies === undefined ) { + throw new Error(`No dependencies found for chain ${chain.chainId}`); + } + + const dependency = chainDependencies[dependencyName as keyof Dependencies] as string; + if (dependency === undefined) { + throw new Error(`No dependency found for ${dependencyName} for chain ${chain.chainId}`); + } + + return dependency; +} + +export function getDependencyAddress(dependencyName: keyof Dependencies, chain: ChainInfo): string { + const { + coreBridge, + circleContracts + } = connectDependencies; + + const symbol = "USDC"; + const nativeUSDC = (t: Token) => t.symbol === symbol && t.original === undefined + const token = getTokensBySymbol(chain.network, toChain(chain.chainId), symbol)?.find(nativeUSDC)?.address; + + const dependencies = { + wormhole: coreBridge.get(chain.network, toChain(chain.chainId)), + tokenMessenger: circleContracts.get(chain.network, toChain(chain.chainId))?.tokenMessenger, + token + } as Dependencies; + const connectDependency = dependencies[dependencyName as keyof Dependencies]; + + try { + const localDependency = getLocalDependencyAddress(dependencyName, chain); + return localDependency === connectDependency ? connectDependency : localDependency; + } catch (e) { + if (connectDependency === undefined) { + throw new Error(`No dependency found for ${dependencyName} for chain ${chain.chainId} on connect sdk`); + } + + return connectDependency; + } +} + +export async function getContractInstance( + contractName: string, + contractAddress: string, + chain: ChainInfo, +): Promise { + const factory = require("../contract-bindings")[`${contractName}__factory`]; + const signer = await getSigner(chain); + return factory.connect(contractAddress, signer); +} + +export function getDeploymentArgs(contractName: string, whChainId: ChainId): UncheckedConstructorArgs { + const constructorArgs = contracts[contractName]?.find((c) => c.chainId === whChainId)?.constructorArgs; + + if (!constructorArgs) { + throw new Error(`No constructorArgs found for ${contractName} contract for chain ${whChainId}`); + } + + return constructorArgs; +} + +export function getMatchingEngineAuctionParameters(chain: ChainInfo): AuctionParameters { + const engineParameters = matchingEngineParameters.find((x) => x.chainId === chain.chainId); + if (engineParameters === undefined) { + throw Error(`Failed to find matching engine parameters for chain ${chain.chainId}`); + } + + return { + userPenaltyRewardBps: Number(engineParameters.userPenaltyRewardBps), + initialPenaltyBps: Number(engineParameters.initialPenaltyBps), + duration: Number(engineParameters.auctionDuration), + gracePeriod: Number(engineParameters.auctionGracePeriod), + penaltyPeriod: Number(engineParameters.auctionPenaltySlots), + minOfferDeltaBps: Number(engineParameters.minOfferDeltaBps), + securityDepositBase: new BN(engineParameters.securityDepositBase), + securityDepositBps: Number(engineParameters.securityDepositBps) + } +} + +export function writeDeployedContract(whChainId: ChainId, contractName: string, address: string, constructorArgs: UncheckedConstructorArgs ) { + const contracts = loadContracts(); + if (!contracts[contractName]) { + contracts[contractName] = [{ chainId: whChainId, address, constructorArgs }]; + } + + else if (!contracts[contractName].find((c) => c.chainId === whChainId)) { + contracts[contractName].push({ chainId: whChainId, address, constructorArgs }); + } + + else { + contracts[contractName] = contracts[contractName].map((c) => { + if (c.chainId === whChainId) { + return { chainId: whChainId, address, constructorArgs }; + } + + return c; + }); + } + + fs.writeFileSync( + `./config/${env}/contracts.json`, + JSON.stringify(contracts), + { flag: "w" } + ); +} \ No newline at end of file diff --git a/deployment/helpers/evm.ts b/deployment/helpers/evm.ts new file mode 100644 index 00000000..3a0c6090 --- /dev/null +++ b/deployment/helpers/evm.ts @@ -0,0 +1,79 @@ +import { LedgerSigner } from "@xlabs-xyz/ledger-signer"; +import { ethers } from "ethers"; +import { ChainInfo, ecosystemChains, EvmScriptCb, getEnv } from "./index"; +import { toChain } from "@wormhole-foundation/sdk-base"; + +export async function runOnEvms(scriptName: string, cb: EvmScriptCb) { + const chains = evmOperatingChains(); + + console.log(`Running script on EVMs (${chains.map(c => c.chainId).join(", ")}):`, scriptName); + + const result = chains.map(async chain => { + const log = (...args: any[]) => console.log(`[${chain.chainId}]`, ...args); + const signer = await getSigner(chain); + log(`Starting script. Signer: ${await signer.getAddress()}. Chain: ${toChain(chain.chainId)}`); + + try { + await cb(chain, signer, log); + log("Success"); + } catch (error) { + log("Error: ", (error as any)?.stack || error); + } + console.log(); + }); + + await Promise.all(result); +} + +export async function runOnEvmsSequentially(scriptName: string, cb: EvmScriptCb) { + const chains = evmOperatingChains(); + + console.log(`Running script on EVMs (${chains.map(c => c.chainId).join(", ")}):`, scriptName); + + for (const chain of chains) { + const log = (...args: any[]) => console.log(`[${chain.chainId}]`, ...args); + const signer = await getSigner(chain); + log(`Starting script. Signer: ${await signer.getAddress()}`); + + try { + await cb(chain, signer, log); + log("Success"); + } catch (error) { + log("Error: ", (error as any)?.stack || error); + } + console.log(); + } +} + +export function evmOperatingChains() { + const { operatingChains } = ecosystemChains; + if (Array.isArray(operatingChains) && operatingChains.length >= 1) { + return ecosystemChains.evm.networks.filter((x) => { + return operatingChains.includes(x.chainId); + }); + } + return ecosystemChains.evm.networks; +}; + +export async function getSigner(chain: ChainInfo): Promise { + const derivationPath = getEnv("EVM_LEDGER_BIP32_PATH"); + const provider = getProvider(chain); + return LedgerSigner.create(provider, derivationPath); +} + +export function getProvider( + chain: ChainInfo +): ethers.providers.StaticJsonRpcProvider { + const providerRpc = ecosystemChains.evm.networks.find((x: any) => x.chainId == chain.chainId)?.rpc || ""; + + if (!providerRpc) { + throw new Error("Failed to find a provider RPC for chain " + chain.chainId); + } + + let provider = new ethers.providers.StaticJsonRpcProvider( + providerRpc, + ); + + return provider; +} + diff --git a/deployment/helpers/index.ts b/deployment/helpers/index.ts new file mode 100644 index 00000000..90135deb --- /dev/null +++ b/deployment/helpers/index.ts @@ -0,0 +1,5 @@ +export * from "./env"; +export * as evm from "./evm"; +export * as solana from "./solana"; +export * from "./interfaces"; +export * from "./utils"; \ No newline at end of file diff --git a/deployment/helpers/interfaces.ts b/deployment/helpers/interfaces.ts new file mode 100644 index 00000000..2bbaab52 --- /dev/null +++ b/deployment/helpers/interfaces.ts @@ -0,0 +1,92 @@ +import { Commitment } from "@solana/web3.js"; +import { ChainId, Network } from "@wormhole-foundation/sdk-base"; +import { SolanaLedgerSigner } from "@xlabs-xyz/ledger-signer-solana"; +import { BigNumber, BytesLike, ethers } from "ethers"; + +export type EvmScriptCb = (chain: ChainInfo, signer: ethers.Signer, logFn: LoggerFn) => Promise; +export type SolanaScriptCb = (chain: ChainInfo, signer: SolanaLedgerSigner, logFn: LoggerFn) => Promise; + +export type LoggerFn = (...args: any[]) => void; + +export type ChainInfo = { + name: string; + /** + * Wormhole ChainId + */ + chainId: ChainId; + rpc: string; + /** + * Native (e.g. EIP-155) ChainId + */ + externalId?: string; + network: Network; + commitmentLevel?: Commitment; +}; + +export type Deployment = { + /** + * Wormhole ChainId + */ + chainId: number; + address: string; + constructorArgs?: UncheckedConstructorArgs; +}; + +export type Ecosystem = { + operatingChains?: number[]; + evm: { + networks: ChainInfo[]; + }, + solana: { + networks: ChainInfo[]; + } +}; + +export type ContractsJson = Record; + +export interface ChainConfig { + /** + * Wormhole ChainId + */ + chainId: ChainId; +} + +export interface Dependencies { + wormhole: string; + token: string; + tokenMessenger: string; +}; + +export interface DependenciesConfig extends ChainConfig, Dependencies {}; + +export interface ValueDiff { + onChain: T; + offChain: T; +} + +export type BooleanDiff = ValueDiff; +export type BigNumberDiff = ValueDiff; +export type StringDiff = ValueDiff; + +export interface VerificationApiKeys extends ChainConfig { + etherscan: string; + blockscout?: { + mainnet: string; + testnet: string; + }; + sourcify?: string; +} + +export type RouterEndpoint = { + /** + * Wormhole ChainId + */ + chainId: ChainId; + endpoint: { + router: BytesLike; + mintRecipient: BytesLike; + }, + circleDomain: number; +} + +export type UncheckedConstructorArgs = readonly any[]; \ No newline at end of file diff --git a/deployment/helpers/solana.ts b/deployment/helpers/solana.ts new file mode 100644 index 00000000..d8b2303a --- /dev/null +++ b/deployment/helpers/solana.ts @@ -0,0 +1,117 @@ +import { + Transaction, + TransactionInstruction, + Keypair, + PublicKey, + Connection, + Commitment +} from "@solana/web3.js"; +import { SolanaLedgerSigner } from "@xlabs-xyz/ledger-signer-solana"; +import { ecosystemChains, env, getContractAddress, getEnv, getLocalDependencyAddress } from "./env"; +import type { ChainInfo, SolanaScriptCb } from "./interfaces"; +import { inspect } from "util"; +import { circle, toChainId } from "@wormhole-foundation/sdk-base"; +import { MatchingEngineProgram, ProgramId as MatchingEngineProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine"; +import { TokenRouterProgram, ProgramId as TokenRouterProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/tokenRouter"; + +export const connectionCommitmentLevel = (process.env.SOLANA_COMMITMENT || "confirmed") as Commitment; +export const priorityMicrolamports = process.env.PRIORITY_MICROLAMPORTS !== undefined? Number(process.env.PRIORITY_MICROLAMPORTS) : 1; + +export function validateSolAddress(address: string){ + try { + const pubkey = new PublicKey(address); + return PublicKey.isOnCurve(pubkey.toBuffer()); + } catch (error) { + return false; + } +} + +export function solanaOperatingChains() { + const { operatingChains } = ecosystemChains; + if (Array.isArray(operatingChains) && operatingChains.length >= 1) { + return ecosystemChains.solana.networks.filter((x) => { + return operatingChains.includes(x.chainId); + }); + } + return ecosystemChains.solana.networks; +}; + +export async function runOnSolana(scriptName: string, cb: SolanaScriptCb) { + const chains = solanaOperatingChains(); + + if (chains.length === 0) { + console.log("No operating Solana chains found, check your ecosystem config file."); + return; + } + + console.log(`Running script on Solana:`, scriptName); + + const result = chains.map(async chain => { + const log = (...args: any[]) => console.log(`[${chain.chainId}]`, ...args); + const signer = await getSigner(); + // TODO: encode in base58 + const signerPubkey = new PublicKey(await signer.getAddress()).toBase58(); + log(`Starting script. Signer: ${signerPubkey}`); + + try { + await cb(chain, signer, log); + log("Success"); + } catch (error) { + log("Error: ", (error as any)?.stack || inspect(error, {depth: 5})); + } + console.log(); + }); + + await Promise.all(result); +} + +let signer: SolanaLedgerSigner | null; +export async function getSigner(): Promise { + if (!signer) { + const derivationPath = getEnv("SOLANA_LEDGER_BIP32_PATH"); + signer = await SolanaLedgerSigner.create(derivationPath); + } + + return signer; +} + +export async function ledgerSignAndSend(connection: Connection, instructions: TransactionInstruction[], signers: Keypair[]) { + const deployerSigner = await getSigner(); + const deployerPk = new PublicKey(await deployerSigner.getAddress()); + + const tx = new Transaction(); + + tx.add(...instructions); + + const recentBlockHash = await connection.getLatestBlockhash(); + + tx.recentBlockhash = recentBlockHash.blockhash; + tx.feePayer = deployerPk; + + signers.forEach((signer) => tx.partialSign(signer)); + + await addLedgerSignature(tx, deployerSigner, deployerPk); + + return connection.sendRawTransaction(tx.serialize()); +} + +async function addLedgerSignature(tx: Transaction, signer: SolanaLedgerSigner, signerPk: PublicKey) { + const signedByPayer = await signer.signTransaction(tx.compileMessage().serialize()); + tx.addSignature(signerPk, signedByPayer); +} + +export function getMatchingEngineProgram(connection: Connection) { + const matchingEngineId = getLocalDependencyAddress("matchingEngineProxy", { chainId: toChainId("Solana")} as ChainInfo) as MatchingEngineProgramId; + const network = env === "mainnet" ? "Mainnet" : "Testnet"; + + const usdcMint = new PublicKey(circle.usdcContract(network, "Solana")); + return new MatchingEngineProgram(connection, matchingEngineId, usdcMint); +}; + +export function getTokenRouterProgram(connection: Connection) { + const tokenRouterId = getContractAddress("TokenRouterProxy", toChainId("Solana")) as TokenRouterProgramId; + const network = env === "mainnet" ? "Mainnet" : "Testnet"; + + const usdcMint = new PublicKey(circle.usdcContract(network, "Solana")); + return new TokenRouterProgram(connection, tokenRouterId, usdcMint); +}; \ No newline at end of file diff --git a/deployment/helpers/utils.ts b/deployment/helpers/utils.ts new file mode 100644 index 00000000..f8348120 --- /dev/null +++ b/deployment/helpers/utils.ts @@ -0,0 +1,90 @@ +import chalk from 'chalk'; +import { ChainInfo, LoggerFn, UncheckedConstructorArgs, ValueDiff } from '.'; + +export const someoneIsDifferent = (values: ValueDiff[]) => values.some((value) => value.onChain.toString() !== value.offChain.toString() && Number(value.onChain) !== Number(value.offChain)); + +export function logComparison(name: string, diffValues: ValueDiff, log: LoggerFn) { + + // If the values are the same, do nothing + if (diffValues.onChain.toString() === diffValues.offChain.toString() || Number(diffValues.onChain) === Number(diffValues.offChain)) + return; + + // If the on chain value is not present or it is zero value, log it as an addition + if (!diffValues.onChain || Number(diffValues.onChain) === 0) + log(chalk.green(`+ ${name}: ${diffValues.offChain}`)); + + // If the off chain value is not present or it is zero value, log it as a removal + else if (!diffValues.offChain || Number(diffValues.offChain) === 0) + log(chalk.red(`- ${name}: ${diffValues.onChain}`)); + + // If both values are present and they are different, log it as a change + else + log(chalk.yellow(`~ ${name}: `) + chalk.red(`${diffValues.onChain}`) + ' -> ' + chalk.green(`${diffValues.offChain}`)); +} + +// Assuming that we'll only have two types of addresses: Ethereum and Solana +export function getAddressType(address: string): 'hex' | 'base58' { + const ETHEREUM_ADDRESS_LENGTH = 40; + const addressLength = address.length - (address.startsWith("0x") ? 2 : 0); + + if (address.length < ETHEREUM_ADDRESS_LENGTH) + throw new Error(`Invalid address length: ${address}`); + + return addressLength === ETHEREUM_ADDRESS_LENGTH ? 'hex' : 'base58'; +} + +export function flattenObject(obj: Record, parentKey = '', result: Record = {}) { + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + let newKey = parentKey ? `${parentKey}-${key}` : key; + + if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) { + flattenObject(obj[key], newKey, result); + } else { + result[newKey] = obj[key]; + } + } + } + return result; +} + +export function getVerifyCommand({ + chain, + contractName, + contractPath, + contractAddress, + constructorSignature, + constructorArgs, + verifier, + verifierUrl, + apiKey +}: { + chain: ChainInfo, + contractName: string, + contractPath: string, + contractAddress: string, + constructorSignature: string, + constructorArgs: UncheckedConstructorArgs, + verifier: string, + verifierUrl?: string, + apiKey?: string +}): string { + if (chain.externalId === undefined) + throw new Error(`Chain ${chain.chainId} does not have an external ID`); + + if (verifier === "blockscout" && verifierUrl === undefined) + throw new Error(`Verifier URL is required for Blockscout verifier`); + + let command = ` + forge verify-contract ${contractAddress} ${contractPath}:${contractName} \ + --verifier ${verifier} \ + ${ verifier === "blockscout" ? `--verifier-url ${verifierUrl}` : ''} \ + --watch --constructor-args $(cast abi-encode "${constructorSignature}" "${constructorArgs.join('" "')}") \ + --chain-id ${chain.externalId} \ + ${ apiKey === undefined || apiKey === "" ? '' : `--etherscan-api-key ${apiKey}` } + `; + + return command; +} + +export const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); diff --git a/deployment/package-lock.json b/deployment/package-lock.json new file mode 100644 index 00000000..a71e476f --- /dev/null +++ b/deployment/package-lock.json @@ -0,0 +1,4129 @@ +{ + "name": "deployment", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "deployment", + "dependencies": { + "@solana/spl-token": "^0.4.8" + }, + "devDependencies": { + "@coral-xyz/anchor": "^0.30.1", + "@inquirer/confirm": "^3.1.9", + "@solana/web3.js": "1.95.3", + "@typechain/ethers-v5": "^11.1.2", + "@types/node": "^20.11.22", + "@wormhole-foundation/example-liquidity-layer-solana": "file:../solana", + "@wormhole-foundation/sdk-base": "^0.7.0", + "@wormhole-foundation/sdk-definitions": "^0.7.0", + "@xlabs-xyz/ledger-signer": "^0.0.4", + "@xlabs-xyz/ledger-signer-solana": "^0.0.1", + "chalk": "^4.1.2", + "dotenv": "^16.4.5", + "ethers": "^5.7.2", + "tsx": "^4.7.2", + "typechain": "^8.3.2", + "typescript": "^5.4.5" + } + }, + "../solana": { + "name": "@wormhole-foundation/example-liquidity-layer-solana", + "version": "0.0.1", + "dev": true, + "dependencies": { + "@certusone/wormhole-spydk": "^0.0.1", + "@coral-xyz/anchor": "^0.30.1", + "@solana/spl-token": "^0.4.8", + "@solana/spl-token-group": "^0.0.6", + "@solana/spl-token-metadata": "^0.1.5", + "@solana/web3.js": "^1.95.3", + "@types/node-fetch": "^2.6.11", + "@wormhole-foundation/example-liquidity-layer-definitions": "0.0.1", + "@wormhole-foundation/sdk-base": "^0.10.9", + "@wormhole-foundation/sdk-definitions": "^0.10.9", + "@wormhole-foundation/sdk-evm": "^0.10.9", + "@wormhole-foundation/sdk-solana": "^0.10.9", + "@wormhole-foundation/sdk-solana-core": "^0.10.9", + "anchor-0.29.0": "npm:@coral-xyz/anchor@^0.29.0", + "bn.js": "^5.2.1", + "dotenv": "^16.4.1", + "sha3": "^2.1.4", + "winston": "^3.13.0", + "yargs": "^17.7.2" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.4", + "@types/chai-as-promised": "^7.1.5", + "@types/mocha": "^10.0.1", + "@types/node": "^18.14.5", + "@types/yargs": "^17.0.24", + "chai": "^4.3.7", + "chai-as-promised": "^7.1.1", + "mocha": "^10.0.0", + "ts-mocha": "^10.0.0", + "ts-results": "^3.3.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", + "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@coral-xyz/anchor": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@coral-xyz/anchor/-/anchor-0.30.1.tgz", + "integrity": "sha512-gDXFoF5oHgpriXAaLpxyWBHdCs8Awgf/gLHIo6crv7Aqm937CNdY+x+6hoj7QR5vaJV7MxWSQ0NGFzL3kPbWEQ==", + "dev": true, + "dependencies": { + "@coral-xyz/anchor-errors": "^0.30.1", + "@coral-xyz/borsh": "^0.30.1", + "@noble/hashes": "^1.3.1", + "@solana/web3.js": "^1.68.0", + "bn.js": "^5.1.2", + "bs58": "^4.0.1", + "buffer-layout": "^1.2.2", + "camelcase": "^6.3.0", + "cross-fetch": "^3.1.5", + "crypto-hash": "^1.3.0", + "eventemitter3": "^4.0.7", + "pako": "^2.0.3", + "snake-case": "^3.0.4", + "superstruct": "^0.15.4", + "toml": "^3.0.0" + }, + "engines": { + "node": ">=11" + } + }, + "node_modules/@coral-xyz/anchor-errors": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@coral-xyz/anchor-errors/-/anchor-errors-0.30.1.tgz", + "integrity": "sha512-9Mkradf5yS5xiLWrl9WrpjqOrAV+/W2RQHDlbnAZBivoGpOs1ECjoDCkVk4aRG8ZdiFiB8zQEVlxf+8fKkmSfQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/superstruct": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.15.5.tgz", + "integrity": "sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==", + "dev": true + }, + "node_modules/@coral-xyz/borsh": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.30.1.tgz", + "integrity": "sha512-aaxswpPrCFKl8vZTbxLssA2RvwX2zmKLlRCIktJOwW+VpVwYtXRtlWiIP+c2pPRKneiTiWCN2GEMSH9j1zTlWQ==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.2", + "buffer-layout": "^1.2.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@solana/web3.js": "^1.68.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "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/providers/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/@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/signing-key/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/@ethersproject/signing-key/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/@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/@inquirer/confirm": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.9.tgz", + "integrity": "sha512-UF09aejxCi4Xqm6N/jJAiFXArXfi9al52AFaSD+2uIHnhZGtd1d6lIGTRMPouVSJxbGEi+HkOWSYaiEY/+szUw==", + "dev": true, + "dependencies": { + "@inquirer/core": "^8.2.2", + "@inquirer/type": "^1.3.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.2.tgz", + "integrity": "sha512-K8SuNX45jEFlX3EBJpu9B+S2TISzMPGXZIuJ9ME924SqbdW6Pt6fIkKvXg7mOEOKJ4WxpQsxj0UTfcL/A434Ww==", + "dev": true, + "dependencies": { + "@inquirer/figures": "^1.0.3", + "@inquirer/type": "^1.3.3", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.12.13", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.3.tgz", + "integrity": "sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.3.3.tgz", + "integrity": "sha512-xTUt0NulylX27/zMx04ZYar/kr1raaiFTVvQ5feljQsiAgdm0WPj4S73/ye0fbslh+15QrIuDvfCXTek7pMY5A==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ledgerhq/cryptoassets": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/cryptoassets/-/cryptoassets-12.1.0.tgz", + "integrity": "sha512-KF9J0X5qmEpHyAy9FphAmDsuodQN/UA3xmjqBhmBSELt/8tAUHHWNOeEV4TfuJLmk2HzXF730aH+61lvVvIUVw==", + "dev": true, + "dependencies": { + "axios": "^1.6.0", + "bs58check": "^2.1.2", + "invariant": "2" + } + }, + "node_modules/@ledgerhq/devices": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.3.0.tgz", + "integrity": "sha512-h5Scr+yIae8yjPOViCHLdMjpqn4oC2Whrsq8LinRxe48LEGMdPqSV1yY7+3Ch827wtzNpMv+/ilKnd8rY+rTlg==", + "dev": true, + "dependencies": { + "@ledgerhq/errors": "^6.16.4", + "@ledgerhq/logs": "^6.12.0", + "rxjs": "^7.8.1", + "semver": "^7.3.5" + } + }, + "node_modules/@ledgerhq/domain-service": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/@ledgerhq/domain-service/-/domain-service-1.1.20.tgz", + "integrity": "sha512-+o1cEZj9HkJeIz2eL3r52tzkOiEKMs9w5aXF+Gy4mrmBjQ3Tw0OY9b69b3jz6PjlEHwAZsDRmcvF1/hSW6ITjw==", + "dev": true, + "dependencies": { + "@ledgerhq/errors": "^6.16.4", + "@ledgerhq/logs": "^6.12.0", + "@ledgerhq/types-live": "^6.46.0", + "axios": "^1.3.4", + "eip55": "^2.1.1", + "react": "^18.2.0", + "react-dom": "^18.2.0" + } + }, + "node_modules/@ledgerhq/errors": { + "version": "6.16.4", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.16.4.tgz", + "integrity": "sha512-M57yFaLYSN+fZCX0E0zUqOmrV6eipK+s5RhijHoUNlHUqrsvUz7iRQgpd5gRgHB5VkIjav7KdaZjKiWGcHovaQ==", + "dev": true + }, + "node_modules/@ledgerhq/evm-tools": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/@ledgerhq/evm-tools/-/evm-tools-1.0.18.tgz", + "integrity": "sha512-jF7H5kjnFp/ju+QvErHyjNtb9G6aaZ1/ne703SO9JwLf/p8fM3uWe5TvS93S8V2sFoO06aoInnwFTJ860ZQKmw==", + "dev": true, + "dependencies": { + "@ledgerhq/cryptoassets": "^12.1.0", + "@ledgerhq/live-env": "^2.0.1", + "axios": "^1.6.5", + "crypto-js": "4.2.0", + "ethers": "5.7.2" + } + }, + "node_modules/@ledgerhq/hw-app-eth": { + "version": "6.36.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-app-eth/-/hw-app-eth-6.36.0.tgz", + "integrity": "sha512-PnIUicutm3vGtsWMBPXvn24msFhfcxQc7iR+UOVK+h1pYVTkBwOOGvNMtPjrayfDIr+66eLtKBrQrAJpUDHF/A==", + "dev": true, + "dependencies": { + "@ethersproject/abi": "^5.5.0", + "@ethersproject/rlp": "^5.5.0", + "@ledgerhq/cryptoassets": "^12.1.0", + "@ledgerhq/domain-service": "^1.1.20", + "@ledgerhq/errors": "^6.16.4", + "@ledgerhq/evm-tools": "^1.0.18", + "@ledgerhq/hw-transport": "^6.30.6", + "@ledgerhq/hw-transport-mocker": "^6.28.6", + "@ledgerhq/logs": "^6.12.0", + "@ledgerhq/types-live": "^6.46.0", + "axios": "^1.3.4", + "bignumber.js": "^9.1.2" + } + }, + "node_modules/@ledgerhq/hw-app-solana": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-app-solana/-/hw-app-solana-7.1.4.tgz", + "integrity": "sha512-xOrCPKzF6RnqD9eRyjltJkWQDS39/Wev3GxvD4sKYuhERdZ+W8Gg0/nxKK468qGNPwhiDaRj7inPKGSMNCADqQ==", + "dev": true, + "dependencies": { + "@ledgerhq/errors": "^6.16.2", + "@ledgerhq/hw-transport": "^6.30.4", + "bip32-path": "^0.4.2" + } + }, + "node_modules/@ledgerhq/hw-transport": { + "version": "6.30.6", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.30.6.tgz", + "integrity": "sha512-fT0Z4IywiuJuZrZE/+W0blkV5UCotDPFTYKLkKCLzYzuE6javva7D/ajRaIeR+hZ4kTmKF4EqnsmDCXwElez+w==", + "dev": true, + "dependencies": { + "@ledgerhq/devices": "^8.3.0", + "@ledgerhq/errors": "^6.16.4", + "@ledgerhq/logs": "^6.12.0", + "events": "^3.3.0" + } + }, + "node_modules/@ledgerhq/hw-transport-mocker": { + "version": "6.28.6", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-mocker/-/hw-transport-mocker-6.28.6.tgz", + "integrity": "sha512-JDO2kqMOTRCQWNZr1KVlyX1AqE6WBzHjJDS3FnSI8Z/Bj2KSc2/1H/4lW6+Ap64yLtlmOW3GchdafFmLgYAgqw==", + "dev": true, + "dependencies": { + "@ledgerhq/hw-transport": "^6.30.6", + "@ledgerhq/logs": "^6.12.0", + "rxjs": "^7.8.1" + } + }, + "node_modules/@ledgerhq/hw-transport-node-hid": { + "version": "6.28.6", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.28.6.tgz", + "integrity": "sha512-USSTOO0zv9XtguWismP7/StnNS/s7Rz0JOGGaBhKe3Bzl7d5XPncUlmOvoNFzzY/QdasEoFs2QId1+ibJG71Vw==", + "dev": true, + "dependencies": { + "@ledgerhq/devices": "^8.3.0", + "@ledgerhq/errors": "^6.16.4", + "@ledgerhq/hw-transport": "^6.30.6", + "@ledgerhq/hw-transport-node-hid-noevents": "^6.29.6", + "@ledgerhq/logs": "^6.12.0", + "lodash": "^4.17.21", + "node-hid": "^2.1.2", + "usb": "2.9.0" + } + }, + "node_modules/@ledgerhq/hw-transport-node-hid-noevents": { + "version": "6.29.6", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-6.29.6.tgz", + "integrity": "sha512-H1cGC4TLwSCxve3rbV7qfPJBZfy7VD7k9Czc9HOMDwQ9zHFtaoeiIotIMGjzHjfPtAGauMpAYvrpmEdBBX5sHg==", + "dev": true, + "dependencies": { + "@ledgerhq/devices": "^8.3.0", + "@ledgerhq/errors": "^6.16.4", + "@ledgerhq/hw-transport": "^6.30.6", + "@ledgerhq/logs": "^6.12.0", + "node-hid": "^2.1.2" + } + }, + "node_modules/@ledgerhq/live-env": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/live-env/-/live-env-2.0.1.tgz", + "integrity": "sha512-fs13laLOvREtWb40JhNX9ImFPvPU/+pKhzs51UFXDMujCtk5VCA8s8bKCA4YJ6rD5Ebpg7aJRc423lMxPyVR2A==", + "dev": true, + "dependencies": { + "rxjs": "^7.8.1", + "utility-types": "^3.10.0" + } + }, + "node_modules/@ledgerhq/logs": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.12.0.tgz", + "integrity": "sha512-ExDoj1QV5eC6TEbMdLUMMk9cfvNKhhv5gXol4SmULRVCx/3iyCPhJ74nsb3S0Vb+/f+XujBEj3vQn5+cwS0fNA==", + "dev": true + }, + "node_modules/@ledgerhq/types-live": { + "version": "6.46.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/types-live/-/types-live-6.46.0.tgz", + "integrity": "sha512-UtI4qm13wJIv9FB/0g6Hi1NijU7PuJEGetqGQxELlKEOmjubXa52EfKVA9IVOngL25m6U8i7jzluwLsHiN2uQQ==", + "dev": true, + "dependencies": { + "bignumber.js": "^9.1.2", + "rxjs": "^7.8.1" + } + }, + "node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/base": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", + "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", + "dev": true, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@solana/buffer-layout": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", + "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", + "dependencies": { + "buffer": "~6.0.3" + }, + "engines": { + "node": ">=5.10" + } + }, + "node_modules/@solana/buffer-layout-utils": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz", + "integrity": "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==", + "dependencies": { + "@solana/buffer-layout": "^4.0.0", + "@solana/web3.js": "^1.32.0", + "bigint-buffer": "^1.1.5", + "bignumber.js": "^9.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@solana/codecs": { + "version": "2.0.0-preview.4", + "resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-2.0.0-preview.4.tgz", + "integrity": "sha512-gLMupqI4i+G4uPi2SGF/Tc1aXcviZF2ybC81x7Q/fARamNSgNOCUUoSCg9nWu1Gid6+UhA7LH80sWI8XjKaRog==", + "dependencies": { + "@solana/codecs-core": "2.0.0-preview.4", + "@solana/codecs-data-structures": "2.0.0-preview.4", + "@solana/codecs-numbers": "2.0.0-preview.4", + "@solana/codecs-strings": "2.0.0-preview.4", + "@solana/options": "2.0.0-preview.4" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-core": { + "version": "2.0.0-preview.4", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.0.0-preview.4.tgz", + "integrity": "sha512-A0VVuDDA5kNKZUinOqHxJQK32aKTucaVbvn31YenGzHX1gPqq+SOnFwgaEY6pq4XEopSmaK16w938ZQS8IvCnw==", + "dependencies": { + "@solana/errors": "2.0.0-preview.4" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-data-structures": { + "version": "2.0.0-preview.4", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-preview.4.tgz", + "integrity": "sha512-nt2k2eTeyzlI/ccutPcG36M/J8NAYfxBPI9h/nQjgJ+M+IgOKi31JV8StDDlG/1XvY0zyqugV3I0r3KAbZRJpA==", + "dependencies": { + "@solana/codecs-core": "2.0.0-preview.4", + "@solana/codecs-numbers": "2.0.0-preview.4", + "@solana/errors": "2.0.0-preview.4" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-numbers": { + "version": "2.0.0-preview.4", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.0.0-preview.4.tgz", + "integrity": "sha512-Q061rLtMadsO7uxpguT+Z7G4UHnjQ6moVIxAQxR58nLxDPCC7MB1Pk106/Z7NDhDLHTcd18uO6DZ7ajHZEn2XQ==", + "dependencies": { + "@solana/codecs-core": "2.0.0-preview.4", + "@solana/errors": "2.0.0-preview.4" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-strings": { + "version": "2.0.0-preview.4", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.0.0-preview.4.tgz", + "integrity": "sha512-YDbsQePRWm+xnrfS64losSGRg8Wb76cjK1K6qfR8LPmdwIC3787x9uW5/E4icl/k+9nwgbIRXZ65lpF+ucZUnw==", + "dependencies": { + "@solana/codecs-core": "2.0.0-preview.4", + "@solana/codecs-numbers": "2.0.0-preview.4", + "@solana/errors": "2.0.0-preview.4" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5" + } + }, + "node_modules/@solana/errors": { + "version": "2.0.0-preview.4", + "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.0.0-preview.4.tgz", + "integrity": "sha512-kadtlbRv2LCWr8A9V22On15Us7Nn8BvqNaOB4hXsTB3O0fU40D1ru2l+cReqLcRPij4znqlRzW9Xi0m6J5DIhA==", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/errors/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@solana/options": { + "version": "2.0.0-preview.4", + "resolved": "https://registry.npmjs.org/@solana/options/-/options-2.0.0-preview.4.tgz", + "integrity": "sha512-tv2O/Frxql/wSe3jbzi5nVicIWIus/BftH+5ZR+r9r3FO0/htEllZS5Q9XdbmSboHu+St87584JXeDx3xm4jaA==", + "dependencies": { + "@solana/codecs-core": "2.0.0-preview.4", + "@solana/codecs-data-structures": "2.0.0-preview.4", + "@solana/codecs-numbers": "2.0.0-preview.4", + "@solana/codecs-strings": "2.0.0-preview.4", + "@solana/errors": "2.0.0-preview.4" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/spl-token": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.4.8.tgz", + "integrity": "sha512-RO0JD9vPRi4LsAbMUdNbDJ5/cv2z11MGhtAvFeRzT4+hAGE/FUzRi0tkkWtuCfSIU3twC6CtmAihRp/+XXjWsA==", + "dependencies": { + "@solana/buffer-layout": "^4.0.0", + "@solana/buffer-layout-utils": "^0.2.0", + "@solana/spl-token-group": "^0.0.5", + "@solana/spl-token-metadata": "^0.1.3", + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.94.0" + } + }, + "node_modules/@solana/spl-token-group": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@solana/spl-token-group/-/spl-token-group-0.0.5.tgz", + "integrity": "sha512-CLJnWEcdoUBpQJfx9WEbX3h6nTdNiUzswfFdkABUik7HVwSNA98u5AYvBVK2H93d9PGMOHAak2lHW9xr+zAJGQ==", + "dependencies": { + "@solana/codecs": "2.0.0-preview.4", + "@solana/spl-type-length-value": "0.1.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.94.0" + } + }, + "node_modules/@solana/spl-token-metadata": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@solana/spl-token-metadata/-/spl-token-metadata-0.1.4.tgz", + "integrity": "sha512-N3gZ8DlW6NWDV28+vCCDJoTqaCZiF/jDUnk3o8GRkAFzHObiR60Bs1gXHBa8zCPdvOwiG6Z3dg5pg7+RW6XNsQ==", + "dependencies": { + "@solana/codecs": "2.0.0-preview.2", + "@solana/spl-type-length-value": "0.1.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.91.6" + } + }, + "node_modules/@solana/spl-token-metadata/node_modules/@solana/codecs": { + "version": "2.0.0-preview.2", + "resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-2.0.0-preview.2.tgz", + "integrity": "sha512-4HHzCD5+pOSmSB71X6w9ptweV48Zj1Vqhe732+pcAQ2cMNnN0gMPMdDq7j3YwaZDZ7yrILVV/3+HTnfT77t2yA==", + "dependencies": { + "@solana/codecs-core": "2.0.0-preview.2", + "@solana/codecs-data-structures": "2.0.0-preview.2", + "@solana/codecs-numbers": "2.0.0-preview.2", + "@solana/codecs-strings": "2.0.0-preview.2", + "@solana/options": "2.0.0-preview.2" + } + }, + "node_modules/@solana/spl-token-metadata/node_modules/@solana/codecs-core": { + "version": "2.0.0-preview.2", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.0.0-preview.2.tgz", + "integrity": "sha512-gLhCJXieSCrAU7acUJjbXl+IbGnqovvxQLlimztPoGgfLQ1wFYu+XJswrEVQqknZYK1pgxpxH3rZ+OKFs0ndQg==", + "dependencies": { + "@solana/errors": "2.0.0-preview.2" + } + }, + "node_modules/@solana/spl-token-metadata/node_modules/@solana/codecs-data-structures": { + "version": "2.0.0-preview.2", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-preview.2.tgz", + "integrity": "sha512-Xf5vIfromOZo94Q8HbR04TbgTwzigqrKII0GjYr21K7rb3nba4hUW2ir8kguY7HWFBcjHGlU5x3MevKBOLp3Zg==", + "dependencies": { + "@solana/codecs-core": "2.0.0-preview.2", + "@solana/codecs-numbers": "2.0.0-preview.2", + "@solana/errors": "2.0.0-preview.2" + } + }, + "node_modules/@solana/spl-token-metadata/node_modules/@solana/codecs-numbers": { + "version": "2.0.0-preview.2", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.0.0-preview.2.tgz", + "integrity": "sha512-aLZnDTf43z4qOnpTcDsUVy1Ci9im1Md8thWipSWbE+WM9ojZAx528oAql+Cv8M8N+6ALKwgVRhPZkto6E59ARw==", + "dependencies": { + "@solana/codecs-core": "2.0.0-preview.2", + "@solana/errors": "2.0.0-preview.2" + } + }, + "node_modules/@solana/spl-token-metadata/node_modules/@solana/codecs-strings": { + "version": "2.0.0-preview.2", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.0.0-preview.2.tgz", + "integrity": "sha512-EgBwY+lIaHHgMJIqVOGHfIfpdmmUDNoNO/GAUGeFPf+q0dF+DtwhJPEMShhzh64X2MeCZcmSO6Kinx0Bvmmz2g==", + "dependencies": { + "@solana/codecs-core": "2.0.0-preview.2", + "@solana/codecs-numbers": "2.0.0-preview.2", + "@solana/errors": "2.0.0-preview.2" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22" + } + }, + "node_modules/@solana/spl-token-metadata/node_modules/@solana/errors": { + "version": "2.0.0-preview.2", + "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.0.0-preview.2.tgz", + "integrity": "sha512-H2DZ1l3iYF5Rp5pPbJpmmtCauWeQXRJapkDg8epQ8BJ7cA2Ut/QEtC3CMmw/iMTcuS6uemFNLcWvlOfoQhvQuA==", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.0.0" + }, + "bin": { + "errors": "bin/cli.js" + } + }, + "node_modules/@solana/spl-token-metadata/node_modules/@solana/options": { + "version": "2.0.0-preview.2", + "resolved": "https://registry.npmjs.org/@solana/options/-/options-2.0.0-preview.2.tgz", + "integrity": "sha512-FAHqEeH0cVsUOTzjl5OfUBw2cyT8d5Oekx4xcn5hn+NyPAfQJgM3CEThzgRD6Q/4mM5pVUnND3oK/Mt1RzSE/w==", + "dependencies": { + "@solana/codecs-core": "2.0.0-preview.2", + "@solana/codecs-numbers": "2.0.0-preview.2" + } + }, + "node_modules/@solana/spl-token-metadata/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@solana/spl-type-length-value": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@solana/spl-type-length-value/-/spl-type-length-value-0.1.0.tgz", + "integrity": "sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA==", + "dependencies": { + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@solana/web3.js": { + "version": "1.95.3", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.95.3.tgz", + "integrity": "sha512-O6rPUN0w2fkNqx/Z3QJMB9L225Ex10PRDH8bTaIUPZXMPV0QP8ZpPvjQnXK+upUczlRgzHzd6SjKIha1p+I6og==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "@noble/curves": "^1.4.2", + "@noble/hashes": "^1.4.0", + "@solana/buffer-layout": "^4.0.1", + "agentkeepalive": "^4.5.0", + "bigint-buffer": "^1.1.5", + "bn.js": "^5.2.1", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.3", + "fast-stable-stringify": "^1.0.0", + "jayson": "^4.1.1", + "node-fetch": "^2.7.0", + "rpc-websockets": "^9.0.2", + "superstruct": "^2.0.2" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.12.tgz", + "integrity": "sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@typechain/ethers-v5": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-11.1.2.tgz", + "integrity": "sha512-ID6pqWkao54EuUQa0P5RgjvfA3MYqxUQKpbGKERbsjBW5Ra7EIXvbMlPp2pcP5IAdUkyMCFYsP2SN5q7mPdLDQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15", + "ts-essentials": "^7.0.1" + }, + "peerDependencies": { + "@ethersproject/abi": "^5.0.0", + "@ethersproject/providers": "^5.0.0", + "ethers": "^5.1.3", + "typechain": "^8.3.2", + "typescript": ">=4.3.0" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==" + }, + "node_modules/@types/w3c-web-usb": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.10.tgz", + "integrity": "sha512-CHgUI5kTc/QLMP8hODUHhge0D4vx+9UiAwIGiT0sTy/B2XpdX1U5rJt6JSISgr6ikRT7vxV9EVAFeYZqUnl1gQ==", + "dev": true + }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@wormhole-foundation/example-liquidity-layer-solana": { + "resolved": "../solana", + "link": true + }, + "node_modules/@wormhole-foundation/sdk-base": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@wormhole-foundation/sdk-base/-/sdk-base-0.7.0.tgz", + "integrity": "sha512-YvxEfoDeWw9klit4C3DM78+W57Humri1Fz61zc+Nt4NDn8nmKLSbmZ3MvMEUFbRSlDZZrjHjlwrescd3l/jK8A==", + "dev": true, + "dependencies": { + "@scure/base": "^1.1.3" + } + }, + "node_modules/@wormhole-foundation/sdk-definitions": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@wormhole-foundation/sdk-definitions/-/sdk-definitions-0.7.0.tgz", + "integrity": "sha512-AJQtlNCwJXQ2GmUIZHt5GiUBnHrivilnZk4wqNtLu4m0yvPOqdM81KdlLHIH++95HAlFHkwmLv1+IWCZNHTDYA==", + "dev": true, + "dependencies": { + "@noble/curves": "^1.4.0", + "@noble/hashes": "^1.3.1", + "@wormhole-foundation/sdk-base": "0.7.0" + } + }, + "node_modules/@xlabs-xyz/ledger-signer": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@xlabs-xyz/ledger-signer/-/ledger-signer-0.0.4.tgz", + "integrity": "sha512-jqAV13JqRj4TGj29ByBeRDec2EIPp7OjRSw4Qs6LmrQB5/U9rJOpYLUWyIQP51sVHfNTAzKBXWsAb3sTTQrlPA==", + "dev": true, + "dependencies": { + "@ledgerhq/hw-app-eth": "^6.35.6", + "@ledgerhq/hw-transport": "^6.30.4", + "@ledgerhq/hw-transport-node-hid": "^6.28.4", + "ethers": "^5.7.2" + } + }, + "node_modules/@xlabs-xyz/ledger-signer-solana": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@xlabs-xyz/ledger-signer-solana/-/ledger-signer-solana-0.0.1.tgz", + "integrity": "sha512-2h9BNc0UYzqbV+S0GDxvh3nV6OSpUOVcbBwQGP0ckl1TAKbwgSzJ+1VYt4xVFJWHLntvfoOpH+DV4LszGWOSNA==", + "dev": true, + "dependencies": { + "@ledgerhq/hw-app-solana": "7.1.4", + "@ledgerhq/hw-transport": "6.30.4", + "@ledgerhq/hw-transport-node-hid": "6.28.4" + } + }, + "node_modules/@xlabs-xyz/ledger-signer-solana/node_modules/@ledgerhq/hw-transport": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.30.4.tgz", + "integrity": "sha512-VBcVd7UG8HDrjWMoZI5rqBDz+PBxLHTIPZOGY/fdMoEUwaBbss0Z3MxuJanMyerlfaLqnBSVuL0blz7rOyagkw==", + "dev": true, + "dependencies": { + "@ledgerhq/devices": "^8.2.1", + "@ledgerhq/errors": "^6.16.2", + "@ledgerhq/logs": "^6.12.0", + "events": "^3.3.0" + } + }, + "node_modules/@xlabs-xyz/ledger-signer-solana/node_modules/@ledgerhq/hw-transport-node-hid": { + "version": "6.28.4", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-6.28.4.tgz", + "integrity": "sha512-f6yQvZe4cwg6ibRn1YE9wWTdvpyT7FBIxxYHAd4RKm0l5/WFZS2G8CwdNJQwlOr89iBgGvEswWYh8EhUxM5QYA==", + "dev": true, + "dependencies": { + "@ledgerhq/devices": "^8.2.1", + "@ledgerhq/errors": "^6.16.2", + "@ledgerhq/hw-transport": "^6.30.4", + "@ledgerhq/hw-transport-node-hid-noevents": "^6.29.4", + "@ledgerhq/logs": "^6.12.0", + "lodash": "^4.17.21", + "node-hid": "^2.1.2", + "usb": "2.9.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/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "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, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "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/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, + "engines": { + "node": ">=6" + } + }, + "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/axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.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 + }, + "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==", + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bigint-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", + "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.3.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "engines": { + "node": "*" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bip32-path": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/bip32-path/-/bip32-path-0.4.2.tgz", + "integrity": "sha512-ZBMCELjJfcNMkz5bDuJ1WrYvjlhEF5k6mQ8vUr4N7MbVRsXei7ZOg8VhhwMfNiW68NWmLkgkc6WvTickrLGprQ==", + "dev": true + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/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" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "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==" + }, + "node_modules/borsh": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", + "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, + "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, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "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, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-layout": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz", + "integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==", + "dev": true, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/bufferutil": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", + "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/chalk/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/chalk/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/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": 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, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "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/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/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-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, + "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, + "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/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, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-usage/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, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/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, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/command-line-usage/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 + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "engines": { + "node": ">=18" + } + }, + "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 + }, + "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, + "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/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dev": true, + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/crypto-hash": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/crypto-hash/-/crypto-hash-1.3.0.tgz", + "integrity": "sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "dev": 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/debug/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/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/eip55": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/eip55/-/eip55-2.1.1.tgz", + "integrity": "sha512-WcagVAmNu2Ww2cDUfzuWVntYwFxbvZ5MvIyLZpMjTTkjD6sCvkGOiS86jTppzu9/gWsc8isLHAeMBWK02OnZmA==", + "dev": true, + "dependencies": { + "keccak": "^3.0.3" + } + }, + "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 + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "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, + "engines": { + "node": ">=0.8.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/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/fast-stable-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", + "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==" + }, + "node_modules/fastestsmallesttextencoderdecoder": { + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", + "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==", + "peer": true + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "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, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "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/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": 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, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "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 + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "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/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, + "engines": { + "node": ">=4" + } + }, + "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, + "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/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/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "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, + "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 + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/jayson": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.1.tgz", + "integrity": "sha512-5ZWm4Q/0DHPyeMfAsrwViwUS2DMVsQgWh8bEEIVTkfb3DzHZ2L3G5WUnF+AKmGjjM9r1uAv73SaqC1/U4RL45w==", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "uuid": "^8.3.2", + "ws": "^7.5.10" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jayson/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, + "node_modules/jayson/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/jayson/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "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/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-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": 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==" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/keccak": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "dev": true, + "hasInstallScript": 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/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": 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 + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "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, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "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/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "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, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "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==" + }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-abi": { + "version": "3.62.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.62.0.tgz", + "integrity": "sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "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 + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "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.8.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", + "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "devOptional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-hid": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-2.2.0.tgz", + "integrity": "sha512-vj48zh9j555DZzUhMc8tk/qw6xPFrDyPBH1ST1Z/hWaA/juBJw7IuSxPeOgpzNFNU36mGYj+THioRMt1xOdm/g==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^3.0.2", + "prebuild-install": "^7.1.1" + }, + "bin": { + "hid-showdevices": "src/show-devices.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-hid/node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": 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, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "dev": true + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "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, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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, + "engines": { + "node": ">=6" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rpc-websockets": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.0.2.tgz", + "integrity": "sha512-YzggvfItxMY3Lwuax5rC18inhbjJv9Py7JXRHxTIi94JOLrqBsSsUUc5bbl5W6c11tXhdfpDPK0KzBhoGe8jjw==", + "dependencies": { + "@swc/helpers": "^0.5.11", + "@types/uuid": "^8.3.4", + "@types/ws": "^8.2.2", + "buffer": "^6.0.3", + "eventemitter3": "^5.0.1", + "uuid": "^8.3.2", + "ws": "^8.5.0" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + }, + "optionalDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + } + }, + "node_modules/rpc-websockets/node_modules/@types/ws": { + "version": "8.5.11", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.11.tgz", + "integrity": "sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/rpc-websockets/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/rpc-websockets/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.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/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "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" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "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, + "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 + }, + "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, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/superstruct": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz", + "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==", + "engines": { + "node": ">=14.0.0" + } + }, + "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, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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, + "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, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", + "dev": true + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-command-line-args": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", + "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", + "dev": true, + "dependencies": { + "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-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, + "peerDependencies": { + "typescript": ">=3.7.0" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tsx": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.9.4.tgz", + "integrity": "sha512-TlSJTVn2taGGDgdV3jAqCj7WQ/CafCB5p4SbG7W2Bl/0AJWH1ShJlBbc0y2lOFTjQEVAAULSTlmehw/Mwv3S/Q==", + "dev": true, + "dependencies": { + "esbuild": "~0.20.2", + "get-tsconfig": "^4.7.3" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "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, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typechain": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", + "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", + "dev": 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, + "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/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "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, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/usb": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/usb/-/usb-2.9.0.tgz", + "integrity": "sha512-G0I/fPgfHUzWH8xo2KkDxTTFruUWfppgSFJ+bQxz/kVY2x15EQ/XDB7dqD1G432G4gBG4jYQuF3U7j/orSs5nw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@types/w3c-web-usb": "^1.0.6", + "node-addon-api": "^6.0.0", + "node-gyp-build": "^4.5.0" + }, + "engines": { + "node": ">=10.20.0 <11.x || >=12.17.0 <13.0 || >=14.0.0" + } + }, + "node_modules/usb/node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", + "dev": true + }, + "node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "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 + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "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==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "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==" + }, + "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==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "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, + "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, + "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 + }, + "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==", + "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 + } + } + } + } +} diff --git a/deployment/package.json b/deployment/package.json new file mode 100644 index 00000000..be58c181 --- /dev/null +++ b/deployment/package.json @@ -0,0 +1,30 @@ +{ + "name": "deployment", + "scripts": { + "evm-deps": "forge build --contracts ../evm/lib/openzeppelin-contracts/contracts/proxy && forge build --config-path ../evm/foundry.toml", + "build-evm": "npm run evm-deps && npx typechain --target=ethers-v5 --out-dir=./contract-bindings ../evm/out/[!build-info]*/*.json", + "check": "npx tsc --noEmit" + }, + "author": "", + "devDependencies": { + "@coral-xyz/anchor": "^0.30.1", + "@inquirer/confirm": "^3.1.9", + "@solana/web3.js": "1.95.3", + "@typechain/ethers-v5": "^11.1.2", + "@types/node": "^20.11.22", + "@wormhole-foundation/example-liquidity-layer-solana": "file:../solana", + "@wormhole-foundation/sdk-base": "^0.7.0", + "@wormhole-foundation/sdk-definitions": "^0.7.0", + "@xlabs-xyz/ledger-signer": "^0.0.4", + "@xlabs-xyz/ledger-signer-solana": "^0.0.1", + "chalk": "^4.1.2", + "dotenv": "^16.4.5", + "ethers": "^5.7.2", + "tsx": "^4.7.2", + "typechain": "^8.3.2", + "typescript": "^5.4.5" + }, + "dependencies": { + "@solana/spl-token": "^0.4.8" + } +} diff --git a/deployment/scripts/evm/TokenRouter/bytecode-verification-token-router.ts b/deployment/scripts/evm/TokenRouter/bytecode-verification-token-router.ts new file mode 100644 index 00000000..df0f1e4a --- /dev/null +++ b/deployment/scripts/evm/TokenRouter/bytecode-verification-token-router.ts @@ -0,0 +1,65 @@ +import { evm, getContractAddress, getDeploymentArgs, getVerifyCommand, verificationApiKeys, flattenObject } from "../../../helpers"; +import { execSync } from "child_process"; +import path from "path"; +import chalk from "chalk"; + +evm.runOnEvms("bytecode-verification-token-router", async (chain, signer, log) => { + // The root path of the foundry project + const rootPath = path.resolve('../evm/'); + + const verifiers = verificationApiKeys[chain.chainId]; + if (!verifiers) { + log(chalk.red(`No verifiers found for chain ${chain.chainId}`)); + return; + } + + for (let [verifier, data] of Object.entries(verifiers)) { + const apiKey = typeof data === 'string' ? data : data.key; + const verifierUrl = typeof data === 'string' ? undefined : data.apiUrl; + + // Implementation data + const implementationName = "TokenRouter"; + const implementationPath = 'src/TokenRouter/TokenRouter.sol'; + const implementationAddress = getContractAddress("TokenRouterImplementation", chain.chainId); + const implementationDeploymentArgs = getDeploymentArgs("TokenRouterImplementation", chain.chainId); + const implementationConstructorSignature = "constructor(address,address,address,uint16,bytes32,bytes32,uint32)"; + const verifyImplementationCommand = getVerifyCommand({ + chain, + contractName: implementationName, + contractPath: implementationPath, + contractAddress: implementationAddress, + constructorSignature: implementationConstructorSignature, + constructorArgs: implementationDeploymentArgs, + verifier, + verifierUrl, + apiKey + }); + + // Proxy data + const proxyName = "ERC1967Proxy"; + const proxyPath = 'lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol'; + const proxyAddress = getContractAddress("TokenRouterProxy", chain.chainId); + const proxyDeploymentArgs = getDeploymentArgs("TokenRouterProxy", chain.chainId); + const proxyConstructorSignature = "constructor(address,bytes)"; + const verifyProxyCommand = getVerifyCommand({ + chain, + contractName: proxyName, + contractPath: proxyPath, + contractAddress: proxyAddress, + constructorSignature: proxyConstructorSignature, + constructorArgs: proxyDeploymentArgs, + verifier, + verifierUrl, + apiKey + }); + + log(chalk.green(`Verifying bytecode on ${verifier}...`)); + log(chalk.green("Verifying implementation bytecode...")); + execSync(verifyImplementationCommand, { stdio: "inherit", cwd: rootPath }); + console.log() + + log(chalk.green("Verifying proxy bytecode...")); + execSync(verifyProxyCommand, { stdio: "inherit", cwd: rootPath }); + console.log() + } +}); \ No newline at end of file diff --git a/deployment/scripts/evm/TokenRouter/config-token-router.ts b/deployment/scripts/evm/TokenRouter/config-token-router.ts new file mode 100644 index 00000000..69796ebc --- /dev/null +++ b/deployment/scripts/evm/TokenRouter/config-token-router.ts @@ -0,0 +1,73 @@ +import { evm, LoggerFn, getContractInstance, getContractAddress } from "../../../helpers"; +import { TokenRouterState, getConfigurationDifferences, logDiff } from "./utils"; +import confirm from '@inquirer/confirm'; +import { TokenRouter } from "../../../contract-bindings"; +import { FastTransferParametersStruct } from "../../../contract-bindings/ITokenRouter"; + +evm.runOnEvmsSequentially("config-token-router", async (chain, signer, log) => { + const tokenRouterAddress = getContractAddress("TokenRouterProxy", chain.chainId); + const tokenRouter = (await getContractInstance("TokenRouter", tokenRouterAddress, chain)) as TokenRouter; + const diff = await getConfigurationDifferences(chain); + + log(`TokenRouter configuration differences on chain ${chain.chainId}:`); + logDiff(diff, log); + + const deployConfig: boolean = await confirm({ message: 'Continue?', default: false }); + if (!deployConfig){ + log(`Configuration deployment aborted on chain ${chain.chainId}`); + return; + } + + const { cctpAllowance, fastTransferParameters } = diff; + + // Fast transfer parameters + await updateFastTransferParameters(tokenRouter, fastTransferParameters, log); + + // CCTP allowance + if (!cctpAllowance.onChain.eq(cctpAllowance.offChain)) { + await tokenRouter.setCctpAllowance(cctpAllowance.offChain); + log(`CCTP allowance updated to ${cctpAllowance.offChain}`); + } +}); + +async function updateFastTransferParameters(tokenRouter: TokenRouter, fastTransferParams: TokenRouterState["fastTransferParameters"], log: LoggerFn) { + let enableFastTransfers = false; + let updatedFastTransferParameters = false; + + // Check if any of the fast transfer parameters have changed + for (const [key, value] of Object.entries(fastTransferParams)) { + if (value.onChain.toString() !== value.offChain.toString()) { + // Check if we are updating the enabled flag + if (key === "enabled") { + enableFastTransfers = true; + } else { + updatedFastTransferParameters = true; + } + } + } + + // Update fast transfer parameters if any of the values have changed (except for the enabled flag) + if (updatedFastTransferParameters) { + + if (fastTransferParams.maxAmount.offChain.lte(fastTransferParams.baseFee.offChain.add(fastTransferParams.initAuctionFee.offChain))) + throw new Error(`Invalid fast transfer parameters: maxAmount must be greater than baseFee + initAuctionFee`); + + await tokenRouter.updateFastTransferParameters({ + enabled: fastTransferParams.enabled.offChain, + baseFee: fastTransferParams.baseFee.offChain, + maxAmount: fastTransferParams.maxAmount.offChain, + initAuctionFee: fastTransferParams.initAuctionFee.offChain + } as FastTransferParametersStruct); + log(`Fast transfer parameters updated`); + } + + // Enable / Disable fast transfers if only the enabled flag has changed + else if (enableFastTransfers) { + const enabled = fastTransferParams.enabled.offChain; + await tokenRouter.enableFastTransfers(enabled); + if (enabled) + log(`Fast transfers enabled`); + else + log(`Fast transfers disabled`); + } +} \ No newline at end of file diff --git a/deployment/scripts/evm/TokenRouter/cross-registration-token-router.ts b/deployment/scripts/evm/TokenRouter/cross-registration-token-router.ts new file mode 100644 index 00000000..d11a3257 --- /dev/null +++ b/deployment/scripts/evm/TokenRouter/cross-registration-token-router.ts @@ -0,0 +1,55 @@ +import { evm, getContractInstance, getContractAddress, contracts, getChainInfo } from "../../../helpers"; +import { TokenRouter } from "../../../contract-bindings"; +import { ChainId, chainToPlatform, circle, toChain, toChainId } from "@wormhole-foundation/sdk-base"; +import { toUniversal } from "@wormhole-foundation/sdk-definitions"; +import { getTokenRouterProgram } from "../../../helpers/solana"; +import { Connection } from "@solana/web3.js"; + +evm.runOnEvms("cross-registration-token-router", async (chain, _, log) => { + const tokenRouterAddress = getContractAddress("TokenRouterProxy", chain.chainId); + const tokenRouter = (await getContractInstance("TokenRouter", tokenRouterAddress, chain)) as TokenRouter; + const deployedTokenRouters = contracts['TokenRouterProxy'].filter((router) => router.chainId !== chain.chainId); + + for (const router of deployedTokenRouters) { + const circleDomain = circle.toCircleChainId(chain.network, toChain(router.chainId)); + const routerChain = toChain(router.chainId); + const routerAddress = toUniversal(routerChain, router.address).toString(); + const mintRecipient = getMintRecipient(router.chainId as ChainId, routerAddress); + const endpoint = { + router: routerAddress, + mintRecipient + }; + + if (router.chainId === 0) + throw new Error('Invalid chainId when register new router endpoint'); + + if (Number(router.address) === 0) + throw new Error(`Invalid router address for chainId ${router.chainId}`); + + const currentMintRecipient = await tokenRouter.getMintRecipient(router.chainId); + + if (Number(currentMintRecipient) !== 0) { + log(`Router endpoint already registered for chainId ${router.chainId}. Updating...`); + await tokenRouter.updateRouterEndpoint(router.chainId, endpoint, circleDomain); + continue; + } + + log(`Adding router endpoint for chainId ${router.chainId}. Endpoint: ${JSON.stringify(endpoint)}`); + await tokenRouter.addRouterEndpoint(router.chainId, endpoint, circleDomain); + } +}); + + +function getMintRecipient(chainId: ChainId, routerAddress: string): string { + const platform = chainToPlatform(toChain(chainId)); + + if (platform === "Evm") + return routerAddress; + + const chain = "Solana"; + const chainInfo = getChainInfo(toChainId(chain)); + const connection = new Connection(chainInfo.rpc, chainInfo.commitmentLevel || "confirmed"); + const tokenRouter = getTokenRouterProgram(connection); + + return toUniversal(chain, tokenRouter.cctpMintRecipientAddress().toBytes()).toString(); +} \ No newline at end of file diff --git a/deployment/scripts/evm/TokenRouter/deploy-token-router.ts b/deployment/scripts/evm/TokenRouter/deploy-token-router.ts new file mode 100644 index 00000000..a68a1cbf --- /dev/null +++ b/deployment/scripts/evm/TokenRouter/deploy-token-router.ts @@ -0,0 +1,39 @@ +import { ethers } from "ethers"; +import { evm, getChainInfo, LoggerFn, writeDeployedContract } from "../../../helpers"; +import { TokenRouterConfiguration } from "../../../config/config-types"; +import { deployImplementation, getMatchingEngineMintRecipientAddress, getTokenRouterConfiguration } from "./utils"; +import { ERC1967Proxy__factory } from "../../../contract-bindings"; + +evm.runOnEvms("deploy-token-router", async (chain, signer, log) => { + const config = await getTokenRouterConfiguration(chain); + + const matchingEngineMintRecipient = getMatchingEngineMintRecipientAddress(); + const implementation = await deployImplementation(chain, signer, config, matchingEngineMintRecipient, log); + await deployProxy(signer, config, implementation, log); +}); + +async function deployProxy(signer: ethers.Signer, config: TokenRouterConfiguration, implementation: ethers.Contract, log: LoggerFn) { + const factory = new ERC1967Proxy__factory(signer); + const abi = ["function initialize(bytes)"]; + const iface = new ethers.utils.Interface(abi); + const data = config.ownerAssistant; + + // Validate if the address are valid and not zero + if (!ethers.utils.isAddress(data) || Number(data) === 0) + throw new Error(`Invalid value: ${data}`); + + const encodedData = ethers.utils.solidityPack(["address"], [data]); + const encodedCall = iface.encodeFunctionData("initialize", [encodedData]); + + const deployment = await factory.deploy( + implementation.address, + encodedCall, + ); + + await deployment.deployed(); + + log(`TokenRouterProxy deployed at ${deployment.address}`); + writeDeployedContract(config.chainId, "TokenRouterProxy", deployment.address, [implementation.address, encodedCall]); + + return deployment; +} diff --git a/deployment/scripts/evm/TokenRouter/disable-router-token-router.ts b/deployment/scripts/evm/TokenRouter/disable-router-token-router.ts new file mode 100644 index 00000000..cba0d540 --- /dev/null +++ b/deployment/scripts/evm/TokenRouter/disable-router-token-router.ts @@ -0,0 +1,35 @@ +import { TokenRouter } from "../../../contract-bindings"; +import { evm, getContractInstance, getContractAddress } from "../../../helpers"; +import { getTokenRouterConfiguration } from "./utils"; + +evm.runOnEvms("disable-router-token-router", async (chain, signer, log) => { + const tokenRouterAddress = getContractAddress("TokenRouterProxy", chain.chainId); + const tokenRouter = (await getContractInstance("TokenRouter", tokenRouterAddress, chain)) as TokenRouter; + const config = await getTokenRouterConfiguration(chain); + + if (config.disableRouterEndpoints === undefined) + throw new Error(`disableRouterEndpoints not defined in config for chain ${chain.chainId}`); + + const isRouterDisabled = await Promise.all( + config.disableRouterEndpoints.map(async chainId => { + const endpoint = await tokenRouter.getRouterEndpoint(chainId); + const domain = await tokenRouter.getDomain(chainId); + + // When a endpoint is disabled, the router and the domain are set to 0 but the mintRecipient still has a value + return Number(endpoint.router) === 0 && Number(domain) === 0 && Number(endpoint.mintRecipient) !== 0; + }) + ); + + for (const i in config.disableRouterEndpoints) { + const chainId = config.disableRouterEndpoints[i]; + const isDisabled = isRouterDisabled[i]; + + if (isDisabled) { + log(`Router endpoint already disabled for wormholeChainId ${chainId}`); + log('Please remove the chainId from the disableRouterEndpoints array.') + } else { + await tokenRouter.disableRouterEndpoint(chainId); + log(`Router endpoint disabled for wormholeChainId ${chainId}`); + }; + } +}); \ No newline at end of file diff --git a/deployment/scripts/evm/TokenRouter/get-config-diff-token-router.ts b/deployment/scripts/evm/TokenRouter/get-config-diff-token-router.ts new file mode 100644 index 00000000..b218c87a --- /dev/null +++ b/deployment/scripts/evm/TokenRouter/get-config-diff-token-router.ts @@ -0,0 +1,9 @@ +import { evm } from "../../../helpers"; +import { getConfigurationDifferences, logDiff } from "./utils"; + +evm.runOnEvms("get-config-diff-token-router", async (chain, signer, log) => { + const diff = await getConfigurationDifferences(chain); + + log(`TokenRouter configuration differences on chain ${chain.chainId}:`); + logDiff(diff, log); +}); \ No newline at end of file diff --git a/deployment/scripts/evm/TokenRouter/read-config-token-router.ts b/deployment/scripts/evm/TokenRouter/read-config-token-router.ts new file mode 100644 index 00000000..0c8b2f82 --- /dev/null +++ b/deployment/scripts/evm/TokenRouter/read-config-token-router.ts @@ -0,0 +1,9 @@ +import { evm } from "../../../helpers"; +import { getOnChainTokenRouterConfiguration } from "./utils"; +import { inspect } from "util"; + +evm.runOnEvms("read-config-token-router", async (chain, signer, log) => { + const onChainConfig = await getOnChainTokenRouterConfiguration(chain); + log(`TokenRouter configuration for chainId ${chain.chainId}:`); + log(inspect(onChainConfig, { depth: null, colors: true, compact: true })); +}); \ No newline at end of file diff --git a/deployment/scripts/evm/TokenRouter/update-owner-assistant-token-router.ts b/deployment/scripts/evm/TokenRouter/update-owner-assistant-token-router.ts new file mode 100644 index 00000000..bb557c8c --- /dev/null +++ b/deployment/scripts/evm/TokenRouter/update-owner-assistant-token-router.ts @@ -0,0 +1,33 @@ +import { TokenRouter } from "../../../contract-bindings"; +import { evm, getContractInstance, getContractAddress, logComparison } from "../../../helpers"; +import { getConfigurationDifferences } from "./utils"; +import confirm from '@inquirer/confirm'; + +evm.runOnEvmsSequentially("update-owner-assistant-token-router", async (chain, signer, log) => { + const tokenRouterAddress = getContractAddress("TokenRouterProxy", chain.chainId); + const tokenRouter = (await getContractInstance("TokenRouter", tokenRouterAddress, chain)) as TokenRouter; + const diff = await getConfigurationDifferences(chain); + + log(`TokenRouter configuration differences on chain ${chain.chainId}:`); + logComparison('OwnerAssistant', diff.ownerAssistant, log); + + if (diff.ownerAssistant.onChain === diff.ownerAssistant.offChain) { + log(`No differences found on chain ${chain.chainId}`); + return; + } + + const updateOwnerAssistant: boolean = await confirm({ message: 'Continue?', default: false }); + if (!updateOwnerAssistant){ + log(`OwnerAssistant update aborted on chain ${chain.chainId}`); + return; + } + + const ownerAddress = await tokenRouter.getOwner(); + const signerAddress = await signer.getAddress(); + if (signerAddress !== ownerAddress) { + throw new Error(`Signer address ${signerAddress} is not the owner of TokenRouter on chain ${chain.chainId}`); + } + + log(`Updating OwnerAssistant on chain ${chain.chainId}`); + await tokenRouter.updateOwnerAssistant(diff.ownerAssistant.offChain); +}); \ No newline at end of file diff --git a/deployment/scripts/evm/TokenRouter/upgrade-token-router.ts b/deployment/scripts/evm/TokenRouter/upgrade-token-router.ts new file mode 100644 index 00000000..7f40db4c --- /dev/null +++ b/deployment/scripts/evm/TokenRouter/upgrade-token-router.ts @@ -0,0 +1,58 @@ +import { evm, ChainInfo, getContractInstance, getContractAddress, getDependencyAddress, getChainInfo } from "../../../helpers"; +import { deployImplementation, getMatchingEngineMintRecipientAddress, getTokenRouterConfiguration, matchingEngineChain, matchingEngineDomain } from "./utils"; +import { TokenRouter } from "../../../contract-bindings"; +import { UniversalAddress, toUniversal } from "@wormhole-foundation/sdk-definitions"; + + +evm.runOnEvms("upgrade-token-router", async (chain, signer, log) => { + const currentImplementationAddress = getContractAddress("TokenRouterImplementation", chain.chainId); + const proxyAddress = getContractAddress("TokenRouterProxy", chain.chainId); + const proxy = (await getContractInstance("TokenRouter", proxyAddress, chain)) as TokenRouter; + const config = await getTokenRouterConfiguration(chain); + + const matchingEngineMintRecipient = getMatchingEngineMintRecipientAddress(); + + log(`Checking immutables for TokenRouter`); + checkImmutables(proxy, chain, matchingEngineMintRecipient); + + const newImplementation = await deployImplementation(chain, signer, config, matchingEngineMintRecipient, log); + + log(`Upgrading TokenRouter implementation from ${currentImplementationAddress} to ${newImplementation.address}`); + + await proxy.upgradeContract(newImplementation.address); +}); + +async function checkImmutables(tokenRouter: TokenRouter, chain: ChainInfo, matchingEngineMintRecipient: string) { + const [ + token, + savedMatchingEngineMintRecipient, + savedMatchingEngineChain, + savedMatchingEngineDomain, + savedMatchingEngineAddress, + ] = await Promise.all([ + tokenRouter.orderToken(), + tokenRouter.matchingEngineMintRecipient(), + tokenRouter.matchingEngineChain(), + tokenRouter.matchingEngineDomain(), + tokenRouter.matchingEngineAddress(), + ]); + + const localMatchingEngineAddress = getContractAddress("MatchingEngineProxy", matchingEngineChain); + const matchingEngineAddress = toUniversal("Solana", localMatchingEngineAddress).toString(); + const tokenAddress = getDependencyAddress("token", chain); + + if (savedMatchingEngineMintRecipient.toLowerCase() !== matchingEngineMintRecipient.toLowerCase()) + throw new Error(`MatchingEngineMintRecipient is an immutable value and cannot be changed.`); + + if (savedMatchingEngineChain !== matchingEngineChain) + throw new Error(`MatchingEngineChain is an immutable value and cannot be changed.`); + + if (savedMatchingEngineDomain !== matchingEngineDomain) + throw new Error(`MatchingEngineDomain is an immutable value and cannot be changed.`); + + if (savedMatchingEngineAddress.toLowerCase() !== matchingEngineAddress.toLowerCase()) + throw new Error(`MatchingEngineAddress is an immutable value and cannot be changed.`); + + if (token.toLowerCase() !== tokenAddress.toLowerCase()) + throw new Error(`Token is an immutable value and cannot be changed.`); +} \ No newline at end of file diff --git a/deployment/scripts/evm/TokenRouter/utils.ts b/deployment/scripts/evm/TokenRouter/utils.ts new file mode 100644 index 00000000..d4a3e00f --- /dev/null +++ b/deployment/scripts/evm/TokenRouter/utils.ts @@ -0,0 +1,159 @@ +import { BigNumber, ethers } from "ethers"; +import { TokenRouterConfiguration } from "../../../config/config-types"; +import { TokenRouter, TokenRouter__factory, IERC20 } from "../../../contract-bindings"; +import { ChainInfo, getChainConfig, LoggerFn, getDependencyAddress, writeDeployedContract, getContractAddress, getContractInstance, logComparison, someoneIsDifferent, ValueDiff, BigNumberDiff, StringDiff, BooleanDiff, getLocalDependencyAddress } from "../../../helpers"; +import { toUniversal } from "@wormhole-foundation/sdk-definitions"; + +export interface TokenRouterState { + cctpAllowance: BigNumberDiff; + ownerAssistant: StringDiff; + fastTransferParameters: { + enabled: BooleanDiff; + maxAmount: BigNumberDiff; + baseFee: BigNumberDiff; + initAuctionFee: BigNumberDiff; + }; +} + +/** + * Chain ID for the Solana wormhole chain + */ +export const matchingEngineChain = 1; + +/** + * CCTP Domain for Solana + */ +export const matchingEngineDomain = 5; + +export function getMatchingEngineMintRecipientAddress(): string { + return toUniversal("Solana", (getLocalDependencyAddress( + "matchingEngineMintRecipient", // i.e. Custodian Matching Engine Mint Recipient + { chainId: matchingEngineChain } as ChainInfo + ))).toString(); +}; + +export function getTokenRouterConfiguration(chain: ChainInfo): Promise { + return getChainConfig("token-router", chain.chainId); +} + +export async function deployImplementation(chain: ChainInfo, signer: ethers.Signer, config: TokenRouterConfiguration, matchingEngineMintRecipient: string, log: LoggerFn) { + if (config.chainId !== chain.chainId) { + throw new Error(`Chain ID mismatch: ${config.chainId} !== ${chain.chainId}`); + } + + const factory = new TokenRouter__factory(signer); + const token = getDependencyAddress("token", chain); + const wormhole = getDependencyAddress("wormhole", chain); + const tokenMessenger = getDependencyAddress("tokenMessenger", chain); + + // this should be of the program's emitter address (custodian) + const matchingEngineAddress = toUniversal("Solana", (getLocalDependencyAddress( + "custodianMatchingEngine", + { chainId: matchingEngineChain } as ChainInfo + ))).toString(); + + const constructorArgs = [ + token, + wormhole, + tokenMessenger, + matchingEngineChain, + matchingEngineAddress, + matchingEngineMintRecipient, + matchingEngineDomain, + ] as const; + const overrides = {}; + + const deployment = await factory.deploy( + ...constructorArgs, + overrides, + ); + + await deployment.deployed(); + + log(`TokenRouter deployed at ${deployment.address}`); + + writeDeployedContract(config.chainId, "TokenRouterImplementation", deployment.address, constructorArgs); + + return deployment; +} + +export async function getOnChainTokenRouterConfiguration(chain: ChainInfo) { + const tokenRouterProxyAddress = getContractAddress("TokenRouterProxy", chain.chainId); + const tokenRouter = (await getContractInstance("TokenRouter", tokenRouterProxyAddress, chain)) as TokenRouter; + + // Get the allowance for the token messenger + const tokenMessengerAddress = getDependencyAddress("tokenMessenger", chain); + const orderTokenAddress = await tokenRouter.orderToken(); + const orderToken = (await getContractInstance("IERC20", orderTokenAddress, chain)) as IERC20; + const cctpAllowance = await orderToken.allowance(tokenRouterProxyAddress, tokenMessengerAddress); + const ownerAssistant = await tokenRouter.getOwnerAssistant(); + const { enabled, maxAmount, baseFee, initAuctionFee} = await tokenRouter.getFastTransferParameters(); + + return { + cctpAllowance, + ownerAssistant, + fastTransferParameters: { + enabled, + maxAmount, + baseFee, + initAuctionFee + } + }; +} + +function compareConfigurations(onChainConfig: Record, offChainConfig: Record) { + const differences = {} as Record; + + for (const key of Object.keys(onChainConfig)) { + const offChainValue = offChainConfig[key as keyof typeof offChainConfig]; + const onChainValue = onChainConfig[key as keyof typeof onChainConfig]; + + if (offChainValue === undefined) + throw new Error(`${key} not found in offChainConfig`); + + // Ignore key if it's an array + if (Array.isArray(offChainValue)) + continue; + + // If the values are objects, compare them + if (!BigNumber.isBigNumber(offChainValue) && typeof offChainValue === 'object' && typeof onChainValue === 'object') { + differences[key] = compareConfigurations(onChainValue, offChainValue) as unknown as ValueDiff; + continue; + } + + differences[key] = { + offChain: offChainValue, + onChain: onChainValue + }; + } + + return differences; +} + +export async function getConfigurationDifferences(chain: ChainInfo) { + const onChainConfig = await getOnChainTokenRouterConfiguration(chain); + const offChainConfig = await getTokenRouterConfiguration(chain); + const offChainDesiredState = { + cctpAllowance: BigNumber.from(offChainConfig.cctpAllowance), + ownerAssistant: offChainConfig.ownerAssistant, + fastTransferParameters: { + enabled: offChainConfig.fastTransferParameters.enabled, + maxAmount: BigNumber.from(offChainConfig.fastTransferParameters.maxAmount), + baseFee: BigNumber.from(offChainConfig.fastTransferParameters.baseFee), + initAuctionFee: BigNumber.from(offChainConfig.fastTransferParameters.initAuctionFee), + }, + } satisfies typeof onChainConfig; + return compareConfigurations(onChainConfig, offChainDesiredState) as unknown as TokenRouterState; +} + +export function logDiff(differences: TokenRouterState, log: LoggerFn) { + logComparison('cctpAllowance', differences.cctpAllowance, log); + + const { enabled, maxAmount, baseFee, initAuctionFee } = differences.fastTransferParameters; + if (someoneIsDifferent([enabled, maxAmount, baseFee, initAuctionFee])) { + log('Fast transfer parameters:'); + for (const [key, value] of Object.entries(differences.fastTransferParameters)) { + logComparison(key, value, log); + } + } +} \ No newline at end of file diff --git a/deployment/scripts/solana/closeProposal.ts b/deployment/scripts/solana/closeProposal.ts new file mode 100644 index 00000000..56bf1289 --- /dev/null +++ b/deployment/scripts/solana/closeProposal.ts @@ -0,0 +1,45 @@ +import { + ComputeBudgetProgram, + Connection, + PublicKey, +} from "@solana/web3.js"; +import "dotenv/config"; +import { MatchingEngineProgram, ProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine"; +import { solana, getLocalDependencyAddress, env } from "../../helpers"; +import { capitalize } from "../../helpers/utils"; +import { circle } from "@wormhole-foundation/sdk-base"; + +solana.runOnSolana("close-proposal", async (chain, signer, log) => { + const matchingEngineId = getLocalDependencyAddress("matchingEngineProxy", chain) as ProgramId; + const canonicalEnv = capitalize(env); + if (canonicalEnv !== "Mainnet" && canonicalEnv !== "Testnet") { + throw new Error(`Unsupported environment: ${env} must be Mainnet or Testnet`); + } + + const usdcMint = new PublicKey(circle.usdcContract(canonicalEnv, "Solana")); + const connection = new Connection(chain.rpc, solana.connectionCommitmentLevel); + const matchingEngine = new MatchingEngineProgram(connection, matchingEngineId, usdcMint); + + log('Matching Engine Program ID:', matchingEngineId.toString()); + + log("Proposal to be closed", await matchingEngine.fetchProposal()); + + if (solana.priorityMicrolamports === undefined || solana.priorityMicrolamports === 0) { + log(`(!) PRIORITY_MICROLAMPORTS is undefined or zero, your transaction may not land during congestion.`) + } + + const priorityFee = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: solana.priorityMicrolamports }); + const ownerOrAssistant = new PublicKey(await signer.getAddress()); + + const closeProposalIx = await matchingEngine.closeProposalIx({ + ownerOrAssistant, + }); + + try { + const closeTxSig = await solana.ledgerSignAndSend(connection, [closeProposalIx, priorityFee], []); + console.log(`Close Proposal Transaction ID: ${closeTxSig}`); + } catch (error) { + console.error('Failed to close proposal:', error); + } + +}); diff --git a/deployment/scripts/solana/commit-upgrades.ts b/deployment/scripts/solana/commit-upgrades.ts new file mode 100644 index 00000000..b54c0f7d --- /dev/null +++ b/deployment/scripts/solana/commit-upgrades.ts @@ -0,0 +1,35 @@ +import { Connection, PublicKey } from "@solana/web3.js"; +import "dotenv/config"; +import { + UpgradeManagerProgram, + ProgramId as UpgradeManagerProgramId, +} from "@wormhole-foundation/example-liquidity-layer-solana/upgradeManager"; + +import { + solana, + getContractAddress, +} from "../../helpers"; + +solana.runOnSolana("upgrade-matching-engine", async (chain, signer, log) => { + const connection = new Connection(chain.rpc, solana.connectionCommitmentLevel); + const upgradeManagerProgramId = getContractAddress( + "UpgradeManager", + chain.chainId, + ) as UpgradeManagerProgramId; + + const upgradeManager = new UpgradeManagerProgram(connection, upgradeManagerProgramId); + + const owner = new PublicKey(await signer.getAddress()); + + const meCommitUpgradeIx = await upgradeManager.commitMatchingEngineUpgradeIx({ + owner + }); + const meTxIdCommit = await solana.ledgerSignAndSend(connection, [meCommitUpgradeIx], []); + log(`Succesfully commited matching engine upgrade on tx -> ${meTxIdCommit}`); + + const trCommitUpgradeIx = await upgradeManager.commitTokenRouterUpgradeIx({ + owner + }); + const trTxIdCommit = await solana.ledgerSignAndSend(connection, [trCommitUpgradeIx], []); + log(`Succesfully committed token router upgrade on tx -> ${trTxIdCommit}`); +}); diff --git a/deployment/scripts/solana/fetchProposal.ts b/deployment/scripts/solana/fetchProposal.ts new file mode 100644 index 00000000..bdd3d3d3 --- /dev/null +++ b/deployment/scripts/solana/fetchProposal.ts @@ -0,0 +1,35 @@ +import { + ComputeBudgetProgram, + Connection, + PublicKey, +} from "@solana/web3.js"; +import "dotenv/config"; +import { MatchingEngineProgram } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine"; +import { solana, getLocalDependencyAddress, env, capitalize } from "../../helpers"; +import { ProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine"; +import { circle } from "@wormhole-foundation/sdk-base"; + +solana.runOnSolana("fetch-proposal", async (chain, signer, log) => { + const matchingEngineId = getLocalDependencyAddress("matchingEngineProxy", chain) as ProgramId; + + const canonicalEnv = capitalize(env); + + if (canonicalEnv !== "Mainnet" && canonicalEnv !== "Testnet") { + throw new Error(`Unsupported environment: ${env} must be Mainnet or Testnet.`); + } + + const usdcMint = new PublicKey(circle.usdcContract(canonicalEnv, "Solana")); + const connection = new Connection(chain.rpc, solana.connectionCommitmentLevel); + const matchingEngine = new MatchingEngineProgram(connection, matchingEngineId, usdcMint); + + log('Matching Engine Program ID:', matchingEngineId.toString()); + + const proposal = await matchingEngine.fetchProposal(); + log('Proposal:', proposal); + + if (proposal.slotEnactedAt !== null) { + log(`Proposal has already been enacted at slot ${proposal.slotEnactedAt.toNumber()}`); + } else { + log('Proposal has not been enacted yet. Update must be submitted after slot ' + proposal.slotEnactDelay.toNumber()); + } +}); diff --git a/deployment/scripts/solana/initializeMatchingEngine.ts b/deployment/scripts/solana/initializeMatchingEngine.ts new file mode 100644 index 00000000..042af75e --- /dev/null +++ b/deployment/scripts/solana/initializeMatchingEngine.ts @@ -0,0 +1,85 @@ +import { + AccountInfo, + ComputeBudgetProgram, + Connection, + PublicKey, +} from "@solana/web3.js"; +import "dotenv/config"; +import { uint64ToBN } from "@wormhole-foundation/example-liquidity-layer-solana/common"; +import { AuctionParameters, MatchingEngineProgram } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine"; +import { solana, LoggerFn, getChainConfig, getContractAddress, getLocalDependencyAddress } from "../../helpers"; +import { MatchingEngineConfiguration } from "../../config/config-types"; +import { ProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine"; +import { SolanaLedgerSigner } from "@xlabs-xyz/ledger-signer-solana"; +import { circle } from "@wormhole-foundation/sdk-base"; + +solana.runOnSolana("deploy-matching-engine", async (chain, signer, log) => { + const config = await getChainConfig("matching-engine", chain.chainId); + const matchingEngineId = getLocalDependencyAddress("MatchingEngineProxy", chain) as ProgramId; + + const env = "Mainnet"; + const usdcMint = new PublicKey(circle.usdcContract(env, "Solana")); + const connection = new Connection(chain.rpc, solana.connectionCommitmentLevel); + const matchingEngine = new MatchingEngineProgram(connection, matchingEngineId, usdcMint); + + await initialize(matchingEngine, signer, log, config, usdcMint); +}); + +async function initialize(matchingEngine: MatchingEngineProgram, signer: SolanaLedgerSigner, log: LoggerFn, config: MatchingEngineConfiguration, usdcMint: PublicKey) { + const connection = matchingEngine.program.provider.connection; + + const custodian = matchingEngine.custodianAddress(); + log("custodian", custodian.toString()); + + const exists = await connection.getAccountInfo(custodian).then((acct: null | AccountInfo) => acct != null); + if (exists) { + log("already initialized"); + return; + } + + const signerPubkey = new PublicKey(await signer.getAddress()); + const auctionParams: AuctionParameters = { + userPenaltyRewardBps: toIntegerNumber(config.userPenaltyRewardBps, "userPenaltyRewardBps"), + initialPenaltyBps: toIntegerNumber(config.initialPenaltyBps, "initialPenaltyBps"), + duration: toIntegerNumber(config.auctionDuration, "duration"), + gracePeriod: toIntegerNumber(config.auctionGracePeriod, "gracePeriod"), + penaltyPeriod: toIntegerNumber(config.auctionPenaltySlots, "penaltyPeriod"), + minOfferDeltaBps: toIntegerNumber(config.minOfferDeltaBps, "minOfferDeltaBps"), + securityDepositBase: uint64ToBN(BigInt(config.securityDepositBase)), + securityDepositBps: toIntegerNumber(config.securityDepositBps, "securityDepositBps"), + } + const initializeInstructions = []; + const priorityFee = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: solana.priorityMicrolamports }); + const feeRecipient = new PublicKey(config.feeRecipient); + initializeInstructions.push(await matchingEngine.initializeIx( + { + owner: signerPubkey, + ownerAssistant: new PublicKey(config.ownerAssistant), + feeRecipient, + }, + auctionParams + )); + initializeInstructions.push(priorityFee); + + // TODO: this doesn't check if the ATA already exists + const splToken = await import("@solana/spl-token"); + const assocciatedTokenProgramId = splToken.ASSOCIATED_TOKEN_PROGRAM_ID; + const associatedToken = splToken.getAssociatedTokenAddressSync(usdcMint, feeRecipient, undefined, usdcMint, assocciatedTokenProgramId); + const createAtaInstructions = []; + createAtaInstructions.push(splToken.createAssociatedTokenAccountInstruction(signerPubkey, associatedToken, feeRecipient, usdcMint)); + createAtaInstructions.push(priorityFee); + + const createAtaTxid = await solana.ledgerSignAndSend(connection, createAtaInstructions, []); + log(`CreateAtaTxid ${createAtaTxid}`); + + const initializeTxid = await solana.ledgerSignAndSend(connection, initializeInstructions, []); + log(`InitializeTxid ${initializeTxid}`); +} + +function toIntegerNumber(text: string, name: string): number { + const res = Number(text); + if (!Number.isSafeInteger(res)) { + throw new Error(`${name} is not a safe integer. Received ${text}`) + } + return res; +} \ No newline at end of file diff --git a/deployment/scripts/solana/initializeTokenRouter.ts b/deployment/scripts/solana/initializeTokenRouter.ts new file mode 100644 index 00000000..89ebd96a --- /dev/null +++ b/deployment/scripts/solana/initializeTokenRouter.ts @@ -0,0 +1,48 @@ +import { + ComputeBudgetProgram, + Connection, + PublicKey, +} from "@solana/web3.js"; +import "dotenv/config"; +import { solana, LoggerFn, getChainConfig, getContractAddress } from "../../helpers"; +import { TokenRouterConfiguration } from "../../config/config-types"; +import { ProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/tokenRouter"; +import { SolanaLedgerSigner } from "@xlabs-xyz/ledger-signer-solana"; +import { circle } from "@wormhole-foundation/sdk-base"; +import { TokenRouterProgram } from "@wormhole-foundation/example-liquidity-layer-solana/tokenRouter"; +import { ledgerSignAndSend } from "../../helpers/solana"; + +solana.runOnSolana("deploy-token-router", async (chain, signer, log) => { + const config = await getChainConfig("token-router", chain.chainId); + const tokenRouterId = getContractAddress("TokenRouterProxy", chain.chainId) as ProgramId; + + const env = "Mainnet"; + const usdcMint = new PublicKey(circle.usdcContract(env, "Solana")); + const connection = new Connection(chain.rpc, solana.connectionCommitmentLevel); + const tokenRouter = new TokenRouterProgram(connection, tokenRouterId, usdcMint); + + await initialize(tokenRouter, signer, log, config); +}); + +async function initialize(tokenRouter: TokenRouterProgram, signer: SolanaLedgerSigner, log: LoggerFn, config: TokenRouterConfiguration) { + const connection = tokenRouter.program.provider.connection; + + const custodian = tokenRouter.custodianAddress(); + log("custodian", custodian.toString()); + + const exists = await connection.getAccountInfo(custodian).then((acct) => acct != null); + if (exists) { + log("already initialized"); + return; + } + + const signerPubkey = new PublicKey(await signer.getAddress()); + const initializeIx = await tokenRouter.initializeIx({ + owner: signerPubkey, + ownerAssistant: new PublicKey(config.ownerAssistant), + }); + const priorityFee = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: solana.priorityMicrolamports }); + + const txSig = await ledgerSignAndSend(connection, [initializeIx, priorityFee], []); + log("intialize", txSig); +} \ No newline at end of file diff --git a/deployment/scripts/solana/proposeAuctionParameters.ts b/deployment/scripts/solana/proposeAuctionParameters.ts new file mode 100644 index 00000000..7acdac9e --- /dev/null +++ b/deployment/scripts/solana/proposeAuctionParameters.ts @@ -0,0 +1,49 @@ +import { + ComputeBudgetProgram, + Connection, + PublicKey, +} from "@solana/web3.js"; +import "dotenv/config"; +import { MatchingEngineProgram, ProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine"; +import { capitalize, env, getLocalDependencyAddress, getMatchingEngineAuctionParameters, solana } from "../../helpers"; +import { circle } from "@wormhole-foundation/sdk-base"; + +solana.runOnSolana("propose-auction-parameters", async (chain, signer, log) => { + const matchingEngineId = getLocalDependencyAddress("matchingEngineProxy", chain) as ProgramId; + const canonicalEnv = capitalize(env); + if (canonicalEnv !== "Mainnet" && canonicalEnv !== "Testnet") { + throw new Error(`Unsupported environment: ${env}. Must be Mainnet or Testnet.`); + } + + const usdcMint = new PublicKey(circle.usdcContract(canonicalEnv, "Solana")); + const connection = new Connection(chain.rpc, solana.connectionCommitmentLevel); + const matchingEngine = new MatchingEngineProgram(connection, matchingEngineId, usdcMint); + + log('Matching Engine Program ID:', matchingEngineId.toString()); + log('Current Matching Engine Auction parameters:', await matchingEngine.fetchAuctionParameters()); + log('\nTo-be-proposed Matching Engine Auction parameters:', getMatchingEngineAuctionParameters(chain)); + + if (solana.priorityMicrolamports === undefined || solana.priorityMicrolamports === 0) { + log(`(!) PRIORITY_MICROLAMPORTS is undefined or zero, your transaction may not land during congestion.`); + } + + const priorityFee = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: solana.priorityMicrolamports }); + const ownerOrAssistant = new PublicKey(await signer.getAddress()); + + const proposeIx = await matchingEngine.proposeAuctionParametersIx({ + ownerOrAssistant, + }, getMatchingEngineAuctionParameters(chain)); + + try { + const proposeTxSig = await solana.ledgerSignAndSend(connection, [proposeIx, priorityFee], []); + log(`Propose Transaction ID: ${proposeTxSig}.`) + + const proposal = await matchingEngine.fetchProposal(); + log(`The proposal has been published at slot ${proposal.slotProposedAt.toNumber()}.`); + log(`You must wait up to slot ${proposal.slotEnactDelay.toNumber()} to submit the auction parameters update.`); + } + catch (error) { + console.error('Failed to send transaction:', error); + } + +}); diff --git a/deployment/scripts/solana/registerRoutersInMatchingEngine.ts b/deployment/scripts/solana/registerRoutersInMatchingEngine.ts new file mode 100644 index 00000000..1883113f --- /dev/null +++ b/deployment/scripts/solana/registerRoutersInMatchingEngine.ts @@ -0,0 +1,200 @@ +import { + AccountInfo, + ComputeBudgetProgram, + Connection, + PublicKey, +} from "@solana/web3.js"; +import "dotenv/config"; +import { MatchingEngineProgram } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine"; +import { solana, LoggerFn, contracts, getLocalDependencyAddress } from "../../helpers"; +import { ProgramId as TokenRouterProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/tokenRouter"; +import { ProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine"; +import { SolanaLedgerSigner } from "@xlabs-xyz/ledger-signer-solana"; +import { Chain, chainToPlatform, circle, toChain, toChainId } from "@wormhole-foundation/sdk-base"; +import { toUniversal } from "@wormhole-foundation/sdk-definitions"; +import { TokenRouterProgram } from "@wormhole-foundation/example-liquidity-layer-solana/tokenRouter"; +import { priorityMicrolamports } from "../../helpers/solana"; + + +solana.runOnSolana("register-routers-matching-engine", async (chain, signer, log) => { + const matchingEngineId = getLocalDependencyAddress("matchingEngineProxy", chain) as ProgramId; + + if (chain.network === "Devnet") + throw new Error("Devnet is not supported by USDC. Use Mainnet or Testnet."); + + const usdcMint = new PublicKey(circle.usdcContract(chain.network, "Solana")); + const connection = new Connection(chain.rpc, solana.connectionCommitmentLevel); + const matchingEngine = new MatchingEngineProgram(connection, matchingEngineId, usdcMint); + + const deployedTokenRouters = contracts['TokenRouterProxy']; + + for (const router of deployedTokenRouters) { + const routerChain = toChain(router.chainId); + const circleDomain = circle.toCircleChainId(chain.network, routerChain); + const routerAddress = toUniversal(routerChain, router.address); + + // check if it is already registered + + if (router.chainId === 0) + throw new Error('Invalid chainId when registering new router endpoint'); + + + if (Number(router.address) === 0) + throw new Error(`Invalid router address for chainId ${router.chainId}`); + + if (router.chainId === toChainId("Solana")) { + // throw new Error("not implemented"); + const tokenRouterId = router.address as TokenRouterProgramId; + const tokenRouter = new TokenRouterProgram(connection, tokenRouterId, usdcMint); + await addSolanaCctpRouterEndpoint(matchingEngine, signer, tokenRouter, log); + } else if (chainToPlatform(routerChain) === "Evm") { + await addCctpRouterEndpoint(matchingEngine, signer, routerChain, circleDomain, routerAddress.toString(), null, log); + } else { + const operatingChain = toChain(chain.chainId); + throw new Error(`Router registrations not implemented for operating chain ${operatingChain}, target chain ${routerChain}`); + } + log(`Router endpoint added for chainId ${router.chainId}`); + } +}); + + +async function addCctpRouterEndpoint( + matchingEngine: MatchingEngineProgram, + signer: SolanaLedgerSigner, + foreignChain: Chain, + cctpDomain: number, + foreignEmitter: string, + foreignMintRecipient: string | null, + log: LoggerFn, +) { + await matchingEngine.fetchCustodian().catch((_: unknown) => { + throw new Error("no custodian found"); + }); + + const connection = matchingEngine.program.provider.connection; + + const foreignChainId = toChainId(foreignChain); + const endpoint = matchingEngine.routerEndpointAddress(foreignChainId); + const exists = await connection.getAccountInfo(endpoint).then((acct: null | AccountInfo) => acct != null); + + const endpointAddress = Array.from(toUniversal(foreignChain, foreignEmitter).unwrap()); + const endpointMintRecipient = + foreignMintRecipient === null + ? null + : Array.from(toUniversal(foreignChain, foreignMintRecipient).unwrap()); + + const signerPubkey = new PublicKey(await signer.getAddress()); + + const [registerIx, action] = await (async () => { + if (exists) { + const { address, mintRecipient } = await matchingEngine.fetchRouterEndpointInfo(foreignChainId); + if ( + Buffer.from(address).equals(Buffer.from(endpointAddress)) && + Buffer.from(mintRecipient).equals( + Buffer.from(endpointMintRecipient ?? endpointAddress), + ) + ) { + return [null, "already exists"] as const; + } else { + // TODO: check that signer pubkey is owner + const registerIx = await matchingEngine.updateCctpRouterEndpointIx( + { owner: signerPubkey }, + { + chain: foreignChainId, + address: endpointAddress, + mintRecipient: endpointMintRecipient, + cctpDomain, + }, + ); + return [registerIx, "updated"] as const; + } + } else { + const registerIx = await matchingEngine.addCctpRouterEndpointIx( + { + ownerOrAssistant: signerPubkey, + }, + { + chain: foreignChainId, + address: endpointAddress, + mintRecipient: endpointMintRecipient, + cctpDomain, + }, + ); + return [registerIx, "added"] as const; + } + })(); + + if (action === "already exists") { + log( + "endpoint already exists", + foreignChain, + "addr", + foreignEmitter, + "domain", + cctpDomain, + "mintRecipient", + foreignMintRecipient, + ); + } else { + const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityMicrolamports }); + const instructions = [registerIx, priorityFeeIx] + const txSig = await solana.ledgerSignAndSend(connection, instructions, []); + log( + `${action} endpoint`, + txSig, + "foreignChain", + foreignChain, + "addr", + foreignEmitter, + "domain", + cctpDomain, + "mintRecipient", + foreignMintRecipient, + ); + } +} + +async function addSolanaCctpRouterEndpoint( + matchingEngine: MatchingEngineProgram, + signer: SolanaLedgerSigner, + tokenRouter: TokenRouterProgram, + log: LoggerFn, +) { + await matchingEngine.fetchCustodian().catch((_: unknown) => { + throw new Error("no custodian found"); + }); + + const connection = matchingEngine.program.provider.connection; + + const chain = toChainId("Solana"); + const endpoint = matchingEngine.routerEndpointAddress(chain); + const exists = await connection.getAccountInfo(endpoint).then((acct: null | AccountInfo) => acct != null); + + const endpointAddress = Array.from( + toUniversal("Solana", tokenRouter.custodianAddress().toString()).unwrap(), + ); + const endpointMintRecipient = Array.from( + toUniversal("Solana", tokenRouter.cctpMintRecipientAddress().toString()).unwrap(), + ); + + if (exists) { + const { address, mintRecipient } = await matchingEngine.fetchRouterEndpointInfo(chain); + if ( + Buffer.from(address).equals(Buffer.from(endpointAddress)) && + Buffer.from(mintRecipient).equals(Buffer.from(endpointMintRecipient ?? endpointAddress)) + ) { + log("local endpoint already exists", endpoint.toString()); + return; + } + } + + const signerPubkey = new PublicKey(await signer.getAddress()); + const registerIx = await matchingEngine.addLocalRouterEndpointIx({ + ownerOrAssistant: signerPubkey, + tokenRouterProgram: tokenRouter.ID, + }); + const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityMicrolamports }); + const instructions = [registerIx, priorityFeeIx]; + const txSig = await solana.ledgerSignAndSend(connection, instructions, []); + log("added local endpoint", txSig, "router", tokenRouter.ID.toString()); +} \ No newline at end of file diff --git a/deployment/scripts/solana/updateAuctionParameters.ts b/deployment/scripts/solana/updateAuctionParameters.ts new file mode 100644 index 00000000..e7cb5edb --- /dev/null +++ b/deployment/scripts/solana/updateAuctionParameters.ts @@ -0,0 +1,43 @@ +import { + ComputeBudgetProgram, + Connection, + PublicKey, +} from "@solana/web3.js"; +import "dotenv/config"; +import { MatchingEngineProgram, ProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine"; +import { env, getLocalDependencyAddress, getMatchingEngineAuctionParameters, solana } from "../../helpers"; +import { capitalize } from "../../helpers/utils"; +import { circle } from "@wormhole-foundation/sdk-base"; + +solana.runOnSolana("update-auction-parameters", async (chain, signer, log) => { + const matchingEngineId = getLocalDependencyAddress("matchingEngineProxy", chain) as ProgramId; + const canonicalEnv = capitalize(env); + if (canonicalEnv !== "Mainnet" && canonicalEnv !== "Testnet") { + throw new Error(`Unsupported environment: ${env} must be Mainnet or Testnet`); + } + + const usdcMint = new PublicKey(circle.usdcContract(canonicalEnv, "Solana")); + const connection = new Connection(chain.rpc, solana.connectionCommitmentLevel); + const matchingEngine = new MatchingEngineProgram(connection, matchingEngineId, usdcMint); + + log('Matching Engine Program ID:', matchingEngineId.toString()); + log('Current Matching Engine Auction parameters:', await matchingEngine.fetchAuctionParameters()); + log('\nTo-be-proposed Matching Engine Auction parameters:', getMatchingEngineAuctionParameters(chain)); + + if (solana.priorityMicrolamports === undefined || solana.priorityMicrolamports === 0) { + log(`(!) PRIORITY_MICROLAMPORTS is undefined or zero, your transaction may not land during congestion.`) + } + + const priorityFee = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: solana.priorityMicrolamports }); + + const ownerOrAssistant = new PublicKey(await signer.getAddress()); + const updateIx = await matchingEngine.updateAuctionParametersIx({ + owner: ownerOrAssistant, + }); + try { + const updateTxSig = await solana.ledgerSignAndSend(connection, [updateIx, priorityFee], []); + log(`Update Transaction ID: ${updateTxSig}`); + } catch (error) { + console.error('Failed to send transaction:', error); + } +}); diff --git a/deployment/scripts/solana/upgrade-matching-engine.ts b/deployment/scripts/solana/upgrade-matching-engine.ts new file mode 100644 index 00000000..b072e584 --- /dev/null +++ b/deployment/scripts/solana/upgrade-matching-engine.ts @@ -0,0 +1,51 @@ +import { Connection, PublicKey } from "@solana/web3.js"; +import "dotenv/config"; +import { + UpgradeManagerProgram, + ProgramId as UpgradeManagerProgramId, +} from "@wormhole-foundation/example-liquidity-layer-solana/upgradeManager"; + +import { + solana, + getContractAddress, + getEnv, +} from "../../helpers"; + +solana.runOnSolana("upgrade-matching-engine", async (chain, signer, log) => { + const connection = new Connection(chain.rpc, solana.connectionCommitmentLevel); + const upgradeManagerProgramId = getContractAddress( + "UpgradeManager", + chain.chainId, + ) as UpgradeManagerProgramId; + + const upgradeManager = new UpgradeManagerProgram(connection, upgradeManagerProgramId); + + const buffer = new PublicKey(getEnv("MATCHING_ENGINE_BUFFER_ACCOUNT")); + + await checkBufferExists(buffer, connection); + + const owner = new PublicKey(await signer.getAddress()); + const upgradeIx = await upgradeManager.executeMatchingEngineUpgradeIx({ + owner, + matchingEngineBuffer: buffer, + }); + + const txId = await solana.ledgerSignAndSend(connection, [upgradeIx], []); + log(`Succesfully upgraded on tx -> ${txId}`); + + const commitUpgradeIx = await upgradeManager.commitMatchingEngineUpgradeIx({ + owner + }); + const txIdCommit = await solana.ledgerSignAndSend(connection, [commitUpgradeIx], []); + log(`Succesfully commited upgrade on tx -> ${txIdCommit}`); +}); + +async function checkBufferExists(buffer: PublicKey, connection: Connection) { + const accInfo = await connection.getAccountInfo(buffer, { + dataSlice: { offset: 0, length: 8 }, + }); + + if (accInfo === null) { + throw new Error(`Buffer at ${buffer.toString()} not found`); + } +} diff --git a/deployment/scripts/solana/upgrade-token-router.ts b/deployment/scripts/solana/upgrade-token-router.ts new file mode 100644 index 00000000..e1eb7882 --- /dev/null +++ b/deployment/scripts/solana/upgrade-token-router.ts @@ -0,0 +1,51 @@ +import { Connection, PublicKey } from "@solana/web3.js"; +import "dotenv/config"; +import { + UpgradeManagerProgram, + ProgramId as UpgradeManagerProgramId, +} from "@wormhole-foundation/example-liquidity-layer-solana/upgradeManager"; + +import { + solana, + getContractAddress, + getEnv, +} from "../../helpers"; + +solana.runOnSolana("upgrade-token-router", async (chain, signer, log) => { + const connection = new Connection(chain.rpc, solana.connectionCommitmentLevel); + const upgradeManagerProgramId = getContractAddress( + "UpgradeManager", + chain.chainId, + ) as UpgradeManagerProgramId; + + const upgradeManager = new UpgradeManagerProgram(connection, upgradeManagerProgramId); + + const buffer = new PublicKey(getEnv("TOKEN_ROUTER_BUFFER_ACCOUNT")); + + await checkBufferExists(buffer, connection); + + const owner = new PublicKey(await signer.getAddress()); + const upgradeIx = await upgradeManager.executeTokenRouterUpgradeIx({ + owner, + tokenRouterBuffer: buffer, + }); + + const txId = await solana.ledgerSignAndSend(connection, [upgradeIx], []); + log(`Succesfully upgraded on tx -> ${txId}`); + + const commitUpgradeIx = await upgradeManager.commitTokenRouterUpgradeIx({ + owner + }); + const txIdCommit = await solana.ledgerSignAndSend(connection, [commitUpgradeIx], []); + log(`Succesfully committed upgrade on tx -> ${txIdCommit}`); +}); + +async function checkBufferExists(buffer: PublicKey, connection: Connection) { + const accInfo = await connection.getAccountInfo(buffer, { + dataSlice: { offset: 0, length: 8 }, + }); + + if (accInfo === null) { + throw new Error(`Buffer at ${buffer.toString()} not found`); + } +} diff --git a/deployment/tsconfig.json b/deployment/tsconfig.json new file mode 100644 index 00000000..0e89e60c --- /dev/null +++ b/deployment/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../tsconfig.json", + "include": ["scripts/**/*.ts", "scripts/**/*.json", "helpers/**/*.ts", "config/**/*.ts", "config/**/*.json", "contract-bindings/**/*.ts"], + "references": [ + { "path": "../solana/tsconfig.cjs.json" }, + ] +} diff --git a/solana/ts/scripts/upgradeMainnet.ts b/solana/ts/scripts/upgradeMainnet.ts new file mode 100644 index 00000000..2a9b3081 --- /dev/null +++ b/solana/ts/scripts/upgradeMainnet.ts @@ -0,0 +1,139 @@ +import { + Connection, + Keypair, + PublicKey, + Transaction, + sendAndConfirmTransaction, +} from "@solana/web3.js"; +import "dotenv/config"; +import { UpgradeManagerProgram } from "../src/upgradeManager"; + +const UPGRADE_MANAGER_ID = "4jyJ7EEsYa72REdD8ZMBvHFTXZ4VYGQPUHaJTajsK8SN"; + +// Here we go. +main(); + +// impl + +async function main() { + const connection = new Connection("https://api.mainnet.solana.com", "confirmed"); + const upgradeManager = new UpgradeManagerProgram(connection, UPGRADE_MANAGER_ID); + + if (process.env.SOLANA_PRIVATE_KEY === undefined) { + throw new Error("SOLANA_PRIVATE_KEY is undefined"); + } + const payer = Keypair.fromSecretKey(Buffer.from(process.env.SOLANA_PRIVATE_KEY, "base64")); + + // TODO: update the buffer addresses + // { + // const buffer = new PublicKey("7Ug82c9aZDCNBpjyBsYyZWuBFnphM2K3tSJmYQw6Huev"); + // await upgradeMatchingEngine(upgradeManager, payer, buffer); + // } + + // { + // const buffer = new PublicKey("2ZKYhV56iaFpHQsdGc2TXdnomVCf3KytCb8ZnjxnLBPN"); + // await upgradeTokenRouter(upgradeManager, payer, buffer); + // } +} + +async function upgradeMatchingEngine( + upgradeManager: UpgradeManagerProgram, + owner: Keypair, + matchingEngineBuffer: PublicKey, +) { + const connection = upgradeManager.program.provider.connection; + + const accInfo = await connection.getAccountInfo(matchingEngineBuffer, { + dataSlice: { offset: 0, length: 8 }, + }); + if (accInfo === null) { + throw new Error("no buffer found"); + } + + const executeIx = await upgradeManager.executeMatchingEngineUpgradeIx({ + owner: owner.publicKey, + matchingEngineBuffer, + }); + + const executeTxSig = await sendAndConfirmTransaction( + connection, + new Transaction().add(executeIx), + [owner], + { + commitment: "finalized", + }, + ).catch((err) => { + console.log(err); + throw err; + }); + console.log("executed upgrade", executeTxSig); + + const commitIx = await upgradeManager.commitMatchingEngineUpgradeIx({ + owner: owner.publicKey, + }); + + let commitTxSig: string | null = null; + while (commitTxSig === null) { + console.log("attempting to commit..."); + await new Promise((r) => setTimeout(r, 2000)); + + commitTxSig = await sendAndConfirmTransaction(connection, new Transaction().add(commitIx), [ + owner, + ]).catch((err) => { + console.log(err); + return null; + }); + } + console.log("committed upgrade", commitTxSig); +} + +async function upgradeTokenRouter( + upgradeManager: UpgradeManagerProgram, + owner: Keypair, + tokenRouterBuffer: PublicKey, +) { + const connection = upgradeManager.program.provider.connection; + + const accInfo = await connection.getAccountInfo(tokenRouterBuffer, { + dataSlice: { offset: 0, length: 8 }, + }); + if (accInfo === null) { + throw new Error("no buffer found"); + } + + const executeIx = await upgradeManager.executeTokenRouterUpgradeIx({ + owner: owner.publicKey, + tokenRouterBuffer, + }); + + const executeTxSig = await sendAndConfirmTransaction( + connection, + new Transaction().add(executeIx), + [owner], + { + commitment: "finalized", + }, + ).catch((err) => { + console.log(err); + throw err; + }); + console.log("executed upgrade", executeTxSig); + + const commitIx = await upgradeManager.commitTokenRouterUpgradeIx({ + owner: owner.publicKey, + }); + + let commitTxSig: string | null = null; + while (commitTxSig === null) { + console.log("attempting to commit..."); + await new Promise((r) => setTimeout(r, 2000)); + + commitTxSig = await sendAndConfirmTransaction(connection, new Transaction().add(commitIx), [ + owner, + ]).catch((err) => { + console.log(err); + return null; + }); + } + console.log("committed upgrade", commitTxSig); +} diff --git a/solana/ts/src/tokenRouter/index.ts b/solana/ts/src/tokenRouter/index.ts index b96c7cda..0c9c1842 100644 --- a/solana/ts/src/tokenRouter/index.ts +++ b/solana/ts/src/tokenRouter/index.ts @@ -24,7 +24,7 @@ import { uint64ToBN, } from "../common"; import * as matchingEngineSdk from "../matchingEngine"; -import { UpgradeManagerProgram } from "../upgradeManager"; +import { UpgradeManagerProgram, mainnet as mainnetUpgradeProgramId } from "../upgradeManager"; import { BPF_LOADER_UPGRADEABLE_PROGRAM_ID, programDataAddress } from "../utils"; import { VaaAccount } from "../wormhole"; import { Custodian, PreparedFill, PreparedOrder } from "./state"; @@ -917,6 +917,12 @@ export class TokenRouterProgram { "UpgradeManager11111111111111111111111111111", ); } + case mainnet(): { + return new UpgradeManagerProgram( + this.program.provider.connection, + mainnetUpgradeProgramId(), + ); + } default: { throw new Error("unsupported network"); } diff --git a/solana/ts/src/upgradeManager/index.ts b/solana/ts/src/upgradeManager/index.ts index 4f58b227..f0f0202a 100644 --- a/solana/ts/src/upgradeManager/index.ts +++ b/solana/ts/src/upgradeManager/index.ts @@ -208,6 +208,13 @@ export class UpgradeManagerProgram { PublicKey.default, ); } + case mainnet(): { + return new matchingEngineSdk.MatchingEngineProgram( + this.program.provider.connection, + matchingEngineSdk.mainnet(), + PublicKey.default, + ); + } default: { throw new Error("unsupported network"); } @@ -230,6 +237,13 @@ export class UpgradeManagerProgram { PublicKey.default, ); } + case mainnet(): { + return new tokenRouterSdk.TokenRouterProgram( + this.program.provider.connection, + tokenRouterSdk.mainnet(), + PublicKey.default, + ); + } default: { throw new Error("unsupported network"); } diff --git a/tsconfig.json b/tsconfig.json index dfe3659a..8ce3cdda 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,8 @@ "sourceMap": true, "skipLibCheck": true, "noErrorTruncation": true, + "outDir": "ts-build", + "resolveJsonModule": true, // Strict Checks // "alwaysStrict": true, // "noImplicitAny": true,