From 08ff230e25c64952d5af9dfa89f8dc3a9d7f50c5 Mon Sep 17 00:00:00 2001 From: SGiaccobasso Date: Wed, 18 Sep 2024 12:18:26 -0300 Subject: [PATCH 1/7] feat: validation script to run when new tokens are pushed --- .github/workflows/validate-tokens.yml | 46 ++++ scripts/validate-token-configs.ts | 360 ++++++++++++++++++++++++++ 2 files changed, 406 insertions(+) create mode 100644 .github/workflows/validate-tokens.yml create mode 100644 scripts/validate-token-configs.ts diff --git a/.github/workflows/validate-tokens.yml b/.github/workflows/validate-tokens.yml new file mode 100644 index 0000000..f4c7a42 --- /dev/null +++ b/.github/workflows/validate-tokens.yml @@ -0,0 +1,46 @@ +name: Validate New Token Configurations + +on: + pull_request: + paths: + - 'registry/mainnet/interchain/squid.tokenlist.json' + +jobs: + validate-tokens: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js + uses: actions/setup-node@v2 + with: + node-version: '16' + + - name: Install dependencies + run: | + npm install -g typescript + npm install ethers@5.7.2 + npm install viem + npm install axios + npm install fs + npm install @types/node + + - name: Compile TypeScript + run: tsc validate-token-configs.ts + + - name: Extract and validate new tokens + run: | + DIFF=$(git diff origin/${{ github.base_ref }} -- registry/mainnet/interchain/squid.tokenlist.json | grep '^+' | grep -v '+++') + NEW_TOKENS=$(echo "$DIFF" | sed -n '/"0x/,/]/{/]/q;p}' | jq -s 'reduce .[] as $item ({}; . + ($item | fromjson))') + echo "$NEW_TOKENS" > new_tokens.json + node validate-token-configs.ts + + - name: Check validation results + run: | + if [ -f validation_errors.txt ]; then + echo "Validation errors found:" + cat validation_errors.txt + exit 1 + else + echo "All new token configurations are valid." + fi diff --git a/scripts/validate-token-configs.ts b/scripts/validate-token-configs.ts new file mode 100644 index 0000000..c1d4d21 --- /dev/null +++ b/scripts/validate-token-configs.ts @@ -0,0 +1,360 @@ +import fs from "fs"; +import { ethers } from "ethers"; +import axios from "axios"; +/* + * ============================= + * Section: Types and Constants + * ============================= + */ +interface ChainInfo { + symbol: string; + name: string; + axelarChainId: string; + tokenAddress: string; + tokenManager: string; + tokenManagerType: TokenManagerType; +} +interface TokenInfo { + tokenId: string; + deployer: string; + originalMinter: string | null; + prettySymbol: string; + decimals: number; + originAxelarChainId: string; + tokenType: string; + deploySalt: string; + iconUrls: { + svg: string; + }; + deploymentMessageId: string; + coinGeckoId: string; + chains: ChainInfo[]; +} +type TokenManagerType = (typeof tokenManagerTypes)[number]; + +// Constants +const tokenManagerTypes = [ + "nativeInterchainToken", + "mintBurnFrom", + "lockUnlock", + "lockUnlockFee", + "mintBurn", + "gateway", +] as const; +const ITSAddress = "0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C"; +const TOKEN_FILE_ROUTE = "./new_tokens.json"; +const COINGECKO_API_KEY = "CG-3VGxh1K3Qk7jAvpt4DJA3LvB"; +const COINGECKO_URL = "https://api.coingecko.com/api/v3/coins/"; +const CHAIN_CONFIGS_URL = + "https://axelar-mainnet.s3.us-east-2.amazonaws.com/configs/mainnet-config-1.x.json"; +const ERC20ABI = [ + { + constant: true, + inputs: [], + name: "name", + outputs: [{ name: "", type: "string" }], + type: "function", + }, + { + constant: true, + inputs: [], + name: "symbol", + outputs: [{ name: "", type: "string" }], + type: "function", + }, + { + constant: true, + inputs: [], + name: "decimals", + outputs: [{ name: "", type: "uint8" }], + type: "function", + }, +]; +const ITSABI = [ + { + inputs: [ + { internalType: "address", name: "sender", type: "address" }, + { internalType: "bytes32", name: "salt", type: "bytes32" }, + ], + name: "interchainTokenId", + outputs: [{ internalType: "bytes32", name: "tokenId", type: "bytes32" }], + stateMutability: "pure", + type: "function", + }, +]; +const tokenManagerABI = [ + { + inputs: [], + name: "tokenAddress", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "implementationType", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, +]; + +/* + * ============================= + * Section: Helper Functions + * ============================= + */ +async function getAxelarChains() { + const { data } = await axios.get(CHAIN_CONFIGS_URL); + return data.chains; +} + +async function getRpcUrl(axelarChainId: string): Promise { + try { + const chains = await getAxelarChains(); + return chains[axelarChainId].config.rpc[0]; + } catch (error) { + throw new Error( + `Error fetching chain configs for chain '${axelarChainId}':\n ${ + (error as Error).message + }` + ); + } +} + +function exitWitheError(errorMessage: string) { + console.error(errorMessage); + fs.writeFileSync("validation_errors.txt", errorMessage); + process.exit(1); +} + +/* + * ============================= + * Section: Validation Functions + * ============================= + */ +async function validateTokenInfo( + tokenInfo: Record +): Promise { + for (const [tokenId, info] of Object.entries(tokenInfo)) { + console.log(`\nValidating token: ${tokenId}...`); + try { + await validateTokenId(tokenId, info); + await validateCoinGeckoId(tokenId, info); + await validateChains(info); + await validateOriginChain(info); + await validateDeployerAndSalt(tokenId, info); + } catch (error) { + exitWitheError((error as Error).message); + } + } +} + +async function validateTokenId( + tokenId: string, + info: TokenInfo +): Promise { + if (tokenId !== info.tokenId) { + throw new Error(`Mismatch in tokenId: ${tokenId} vs ${info.tokenId}`); + } +} + +async function validateCoinGeckoId( + tokenId: string, + { coinGeckoId, prettySymbol }: TokenInfo +): Promise { + if (!coinGeckoId) + throw new Error(`CoinGecko ID is missing for token ${tokenId}`); + + try { + const response = await axios.get(COINGECKO_URL + coinGeckoId, { + headers: { + "x-cg-demo-api-key": COINGECKO_API_KEY, + }, + }); + + if (response.status !== 200) + throw new Error( + `CoinGecko API returned status ${response.status} for token ${tokenId}` + ); + + const coinData = response.data; + if (coinData.symbol.toLowerCase() !== prettySymbol.toLowerCase()) { + throw new Error( + `CoinGecko symbol (${coinData.symbol}) does not match prettySymbol (${prettySymbol}) for token ${tokenId}` + ); + } + } catch (error) { + if (axios.isAxiosError(error) && error.response?.status === 404) { + throw new Error( + `CoinGecko ID ${coinGeckoId} not found for token ${tokenId}` + ); + } + throw new Error( + `Error fetching data from CoinGecko for token ${tokenId}: ${ + (error as Error).message + }` + ); + } +} + +async function validateChains(info: TokenInfo): Promise { + for (const chain of info.chains) { + console.log(`Validating for ${chain.axelarChainId}...`); + + const rpcUrl = await getRpcUrl(chain.axelarChainId); + const provider = new ethers.JsonRpcProvider(rpcUrl); + + await validateTokenAddress(chain, provider); + await validateTokenDetails(chain, info, provider); + await validateTokenManager(chain, provider); + } +} + +async function validateTokenAddress( + chain: ChainInfo, + provider: ethers.JsonRpcProvider +): Promise { + const tokenCode = await provider.getCode(chain.tokenAddress); + if (tokenCode === "0x") + throw new Error( + `Token address ${chain.tokenAddress} does not exist on chain ${chain.axelarChainId}` + ); +} + +async function validateTokenDetails( + chain: ChainInfo, + { originAxelarChainId, prettySymbol, decimals }: TokenInfo, + provider: ethers.JsonRpcProvider +): Promise { + const tokenContract = new ethers.Contract( + chain.tokenAddress, + ERC20ABI, + provider + ); + const tokenName = await tokenContract.name(); + const tokenSymbol = await tokenContract.symbol(); + const tokenDecimals = await tokenContract.decimals(); + const decimalsFromContract = Number(tokenDecimals); + + if (tokenName.toLowerCase() !== chain.name.toLowerCase()) + throw new Error( + `Token name mismatch on chain ${chain.axelarChainId}: expected ${chain.name}, got ${tokenName}` + ); + if (tokenSymbol.toLowerCase() !== chain.symbol.toLowerCase()) + throw new Error( + `Token symbol mismatch on chain ${chain.axelarChainId}: expected ${chain.symbol}, got ${tokenSymbol}` + ); + if (originAxelarChainId === chain.axelarChainId) { + if (tokenSymbol.toLowerCase() !== prettySymbol.toLowerCase()) + throw new Error( + `Token symbol mismatch on chain ${chain.axelarChainId}: expected ${prettySymbol}, got ${tokenSymbol}` + ); + if (decimalsFromContract !== decimals) + throw new Error( + `Token decimals mismatch on chain ${chain.axelarChainId}: expected ${decimals}, got ${decimalsFromContract}` + ); + } +} + +async function validateTokenManager( + chain: ChainInfo, + provider: ethers.JsonRpcProvider +): Promise { + const managerCode = await provider.getCode(chain.tokenManager); + if (managerCode === "0x") { + throw new Error( + `Token manager ${chain.tokenManager} does not exist on chain ${chain.axelarChainId}` + ); + } + + const tokenManagerContract = new ethers.Contract( + chain.tokenManager, + tokenManagerABI, + provider + ); + const managedTokenAddress = await tokenManagerContract.tokenAddress(); + if (managedTokenAddress.toLowerCase() !== chain.tokenAddress.toLowerCase()) + throw new Error( + `Token manager ${chain.tokenManager} on chain ${chain.axelarChainId} does not manage the specified token address ${chain.tokenAddress}` + ); + + const implementationType = await tokenManagerContract.implementationType(); + if ( + Number(implementationType) !== + tokenManagerTypes.indexOf(chain.tokenManagerType) + ) + throw new Error( + `Token manager on chain ${ + chain.axelarChainId + } has incorrect implementation type: expected '${ + tokenManagerTypes[Number(implementationType)] || "Unknown" + }', got '${chain.tokenManagerType}'` + ); +} + +async function validateOriginChain({ + chains, + originAxelarChainId, +}: TokenInfo): Promise { + const originChain = chains.find( + (chain) => chain.axelarChainId === originAxelarChainId + ); + if (!originChain) + throw new Error( + `Origin chain ${originAxelarChainId} not found in chains list` + ); +} + +async function validateDeployerAndSalt( + tokenId: string, + { originAxelarChainId, deployer, deploySalt }: TokenInfo +): Promise { + const rpcUrl = await getRpcUrl(originAxelarChainId); + const provider = new ethers.JsonRpcProvider(rpcUrl); + const itsContract = new ethers.Contract(ITSAddress, ITSABI, provider); + + if (!ethers.isAddress(deployer)) + throw new Error(`Invalid deployer address: ${deployer}`); + + const calculatedTokenId = await itsContract.interchainTokenId( + deployer, + deploySalt + ); + + if (calculatedTokenId.toLowerCase() !== tokenId.toLowerCase()) + throw new Error( + `Mismatch in interchainTokenId for token ${tokenId}:\n` + + `Deployer or Deploy Salt could be incorrect\n` + + ` Expected: ${tokenId}\n` + + ` Calculated: ${calculatedTokenId}\n` + + ` Deployer: ${deployer}\n` + + ` Deploy Salt: ${deploySalt}` + ); +} + +/* + * ============================= + * Section: Main + * ============================= + */ +async function main() { + try { + // Read new token configurations from file + const newTokens: Record = JSON.parse( + fs.readFileSync(TOKEN_FILE_ROUTE, "utf8") + ); + await validateTokenInfo(newTokens); + } catch (error) { + exitWitheError((error as Error).message); + } + console.log("Validation successful!"); +} + +main(); From f926ea1e29871c88dfed94b3d1ebf4afd45eb1fc Mon Sep 17 00:00:00 2001 From: SGiaccobasso Date: Mon, 23 Sep 2024 16:22:55 -0300 Subject: [PATCH 2/7] chore: format yaml file --- .github/workflows/validate-tokens.yml | 64 +++++++++++++-------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/workflows/validate-tokens.yml b/.github/workflows/validate-tokens.yml index f4c7a42..040572d 100644 --- a/.github/workflows/validate-tokens.yml +++ b/.github/workflows/validate-tokens.yml @@ -3,44 +3,44 @@ name: Validate New Token Configurations on: pull_request: paths: - - 'registry/mainnet/interchain/squid.tokenlist.json' + - "registry/mainnet/interchain/squid.tokenlist.json" jobs: validate-tokens: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - - name: Use Node.js - uses: actions/setup-node@v2 - with: - node-version: '16' + - uses: actions/checkout@v2 - - name: Install dependencies - run: | - npm install -g typescript - npm install ethers@5.7.2 - npm install viem - npm install axios - npm install fs - npm install @types/node + - name: Use Node.js + uses: actions/setup-node@v2 + with: + node-version: "16" - - name: Compile TypeScript - run: tsc validate-token-configs.ts + - name: Install dependencies + run: | + npm install -g typescript + npm install ethers@5.7.2 + npm install viem + npm install axios + npm install fs + npm install @types/node - - name: Extract and validate new tokens - run: | - DIFF=$(git diff origin/${{ github.base_ref }} -- registry/mainnet/interchain/squid.tokenlist.json | grep '^+' | grep -v '+++') - NEW_TOKENS=$(echo "$DIFF" | sed -n '/"0x/,/]/{/]/q;p}' | jq -s 'reduce .[] as $item ({}; . + ($item | fromjson))') - echo "$NEW_TOKENS" > new_tokens.json - node validate-token-configs.ts + - name: Compile TypeScript + run: tsc validate-token-configs.ts - - name: Check validation results - run: | - if [ -f validation_errors.txt ]; then - echo "Validation errors found:" - cat validation_errors.txt - exit 1 - else - echo "All new token configurations are valid." - fi + - name: Extract and validate new tokens + run: | + DIFF=$(git diff origin/${{ github.base_ref }} -- registry/mainnet/interchain/squid.tokenlist.json | grep '^+' | grep -v '+++') + NEW_TOKENS=$(echo "$DIFF" | sed -n '/"0x/,/]/{/]/q;p}' | jq -s 'reduce .[] as $item ({}; . + ($item | fromjson))') + echo "$NEW_TOKENS" > new_tokens.json + node validate-token-configs.ts + + - name: Check validation results + run: | + if [ -f validation_errors.txt ]; then + echo "Validation errors found:" + cat validation_errors.txt + exit 1 + else + echo "All new token configurations are valid." + fi From c595dc9b88643925f6074a639648708f2e479fa9 Mon Sep 17 00:00:00 2001 From: SGiaccobasso Date: Mon, 23 Sep 2024 20:47:11 -0300 Subject: [PATCH 3/7] chore: use js script --- .github/workflows/validate-tokens.yml | 9 +- scripts/validate-token-configs.js | 311 ++++++++++++++++++++++++++ scripts/validate-token-configs.ts | 2 +- 3 files changed, 313 insertions(+), 9 deletions(-) create mode 100644 scripts/validate-token-configs.js diff --git a/.github/workflows/validate-tokens.yml b/.github/workflows/validate-tokens.yml index 040572d..39cba2c 100644 --- a/.github/workflows/validate-tokens.yml +++ b/.github/workflows/validate-tokens.yml @@ -18,22 +18,15 @@ jobs: - name: Install dependencies run: | - npm install -g typescript npm install ethers@5.7.2 - npm install viem npm install axios - npm install fs - npm install @types/node - - - name: Compile TypeScript - run: tsc validate-token-configs.ts - name: Extract and validate new tokens run: | DIFF=$(git diff origin/${{ github.base_ref }} -- registry/mainnet/interchain/squid.tokenlist.json | grep '^+' | grep -v '+++') NEW_TOKENS=$(echo "$DIFF" | sed -n '/"0x/,/]/{/]/q;p}' | jq -s 'reduce .[] as $item ({}; . + ($item | fromjson))') echo "$NEW_TOKENS" > new_tokens.json - node validate-token-configs.ts + node scripts/validate-token-configs.js - name: Check validation results run: | diff --git a/scripts/validate-token-configs.js b/scripts/validate-token-configs.js new file mode 100644 index 0000000..0a013b1 --- /dev/null +++ b/scripts/validate-token-configs.js @@ -0,0 +1,311 @@ +const fs = require("fs"); +const ethers = require("ethers"); +const axios = require("axios"); + +/* + * ============================= + * Section: Constants + * ============================= + */ +const tokenManagerTypes = [ + "nativeInterchainToken", + "mintBurnFrom", + "lockUnlock", + "lockUnlockFee", + "mintBurn", + "gateway", +]; +const ITSAddress = "0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C"; +const TOKEN_FILE_ROUTE = "./new_tokens.json"; +const COINGECKO_API_KEY = "CG-3VGxh1K3Qk7jAvpt4DJA3LvB"; +const COINGECKO_URL = "https://api.coingecko.com/api/v3/coins/"; +const CHAIN_CONFIGS_URL = + "https://axelar-mainnet.s3.us-east-2.amazonaws.com/configs/mainnet-config-1.x.json"; +const ERC20ABI = [ + { + constant: true, + inputs: [], + name: "name", + outputs: [{ name: "", type: "string" }], + type: "function", + }, + { + constant: true, + inputs: [], + name: "symbol", + outputs: [{ name: "", type: "string" }], + type: "function", + }, + { + constant: true, + inputs: [], + name: "decimals", + outputs: [{ name: "", type: "uint8" }], + type: "function", + }, +]; +const ITSABI = [ + { + inputs: [ + { internalType: "address", name: "sender", type: "address" }, + { internalType: "bytes32", name: "salt", type: "bytes32" }, + ], + name: "interchainTokenId", + outputs: [{ internalType: "bytes32", name: "tokenId", type: "bytes32" }], + stateMutability: "pure", + type: "function", + }, +]; +const tokenManagerABI = [ + { + inputs: [], + name: "tokenAddress", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "implementationType", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, +]; + +/* + * ============================= + * Section: Helper Functions + * ============================= + */ +async function getAxelarChains() { + const { data } = await axios.get(CHAIN_CONFIGS_URL); + return data.chains; +} + +async function getRpcUrl(axelarChainId) { + try { + const chains = await getAxelarChains(); + return chains[axelarChainId].config.rpc[0]; + } catch (error) { + throw new Error( + `Error fetching chain configs for chain '${axelarChainId}':\n ${error.message}` + ); + } +} + +function exitWithError(errorMessage) { + console.error(errorMessage); + fs.writeFileSync("validation_errors.txt", errorMessage); + process.exit(1); +} + +/* + * ============================= + * Section: Validation Functions + * ============================= + */ +async function validateTokenInfo(tokenInfo) { + for (const [tokenId, info] of Object.entries(tokenInfo)) { + console.log(`\nValidating token: ${tokenId}...`); + try { + await validateTokenId(tokenId, info); + await validateCoinGeckoId(tokenId, info); + await validateChains(info); + await validateOriginChain(info); + await validateDeployerAndSalt(tokenId, info); + } catch (error) { + exitWithError(error.message); + } + } +} + +async function validateTokenId(tokenId, info) { + if (tokenId !== info.tokenId) { + throw new Error(`Mismatch in tokenId: ${tokenId} vs ${info.tokenId}`); + } +} + +async function validateCoinGeckoId(tokenId, { coinGeckoId, prettySymbol }) { + if (!coinGeckoId) + throw new Error(`CoinGecko ID is missing for token ${tokenId}`); + + try { + const response = await axios.get(COINGECKO_URL + coinGeckoId, { + headers: { + "x-cg-demo-api-key": COINGECKO_API_KEY, + }, + }); + + if (response.status !== 200) + throw new Error( + `CoinGecko API returned status ${response.status} for token ${tokenId}` + ); + + const coinData = response.data; + if (coinData.symbol.toLowerCase() !== prettySymbol.toLowerCase()) { + throw new Error( + `CoinGecko symbol (${coinData.symbol}) does not match prettySymbol (${prettySymbol}) for token ${tokenId}` + ); + } + } catch (error) { + if (axios.isAxiosError(error) && error.response?.status === 404) { + throw new Error( + `CoinGecko ID ${coinGeckoId} not found for token ${tokenId}` + ); + } + throw new Error( + `Error fetching data from CoinGecko for token ${tokenId}: ${error.message}` + ); + } +} + +async function validateChains(info) { + for (const chain of info.chains) { + console.log(`Validating for ${chain.axelarChainId}...`); + + const rpcUrl = await getRpcUrl(chain.axelarChainId); + const provider = new ethers.JsonRpcProvider(rpcUrl); + + await validateTokenAddress(chain, provider); + await validateTokenDetails(chain, info, provider); + await validateTokenManager(chain, provider); + } +} + +async function validateTokenAddress(chain, provider) { + const tokenCode = await provider.getCode(chain.tokenAddress); + if (tokenCode === "0x") + throw new Error( + `Token address ${chain.tokenAddress} does not exist on chain ${chain.axelarChainId}` + ); +} + +async function validateTokenDetails( + chain, + { originAxelarChainId, prettySymbol, decimals }, + provider +) { + const tokenContract = new ethers.Contract( + chain.tokenAddress, + ERC20ABI, + provider + ); + const tokenName = await tokenContract.name(); + const tokenSymbol = await tokenContract.symbol(); + const tokenDecimals = await tokenContract.decimals(); + const decimalsFromContract = Number(tokenDecimals); + + if (tokenName.toLowerCase() !== chain.name.toLowerCase()) + throw new Error( + `Token name mismatch on chain ${chain.axelarChainId}: expected ${chain.name}, got ${tokenName}` + ); + if (tokenSymbol.toLowerCase() !== chain.symbol.toLowerCase()) + throw new Error( + `Token symbol mismatch on chain ${chain.axelarChainId}: expected ${chain.symbol}, got ${tokenSymbol}` + ); + if (originAxelarChainId === chain.axelarChainId) { + if (tokenSymbol.toLowerCase() !== prettySymbol.toLowerCase()) + throw new Error( + `Token symbol mismatch on chain ${chain.axelarChainId}: expected ${prettySymbol}, got ${tokenSymbol}` + ); + if (decimalsFromContract !== decimals) + throw new Error( + `Token decimals mismatch on chain ${chain.axelarChainId}: expected ${decimals}, got ${decimalsFromContract}` + ); + } +} + +async function validateTokenManager(chain, provider) { + const managerCode = await provider.getCode(chain.tokenManager); + if (managerCode === "0x") { + throw new Error( + `Token manager ${chain.tokenManager} does not exist on chain ${chain.axelarChainId}` + ); + } + + const tokenManagerContract = new ethers.Contract( + chain.tokenManager, + tokenManagerABI, + provider + ); + const managedTokenAddress = await tokenManagerContract.tokenAddress(); + if (managedTokenAddress.toLowerCase() !== chain.tokenAddress.toLowerCase()) + throw new Error( + `Token manager ${chain.tokenManager} on chain ${chain.axelarChainId} does not manage the specified token address ${chain.tokenAddress}` + ); + + const implementationType = await tokenManagerContract.implementationType(); + if ( + Number(implementationType) !== + tokenManagerTypes.indexOf(chain.tokenManagerType) + ) + throw new Error( + `Token manager on chain ${ + chain.axelarChainId + } has incorrect implementation type: expected '${ + tokenManagerTypes[Number(implementationType)] || "Unknown" + }', got '${chain.tokenManagerType}'` + ); +} + +async function validateOriginChain({ chains, originAxelarChainId }) { + const originChain = chains.find( + (chain) => chain.axelarChainId === originAxelarChainId + ); + if (!originChain) + throw new Error( + `Origin chain ${originAxelarChainId} not found in chains list` + ); +} + +async function validateDeployerAndSalt( + tokenId, + { originAxelarChainId, deployer, deploySalt } +) { + const rpcUrl = await getRpcUrl(originAxelarChainId); + const provider = new ethers.JsonRpcProvider(rpcUrl); + const itsContract = new ethers.Contract(ITSAddress, ITSABI, provider); + + if (!ethers.isAddress(deployer)) + throw new Error(`Invalid deployer address: ${deployer}`); + + const calculatedTokenId = await itsContract.interchainTokenId( + deployer, + deploySalt + ); + + if (calculatedTokenId.toLowerCase() !== tokenId.toLowerCase()) + throw new Error( + `Mismatch in interchainTokenId for token ${tokenId}:\n` + + `Deployer or Deploy Salt could be incorrect\n` + + ` Expected: ${tokenId}\n` + + ` Calculated: ${calculatedTokenId}\n` + + ` Deployer: ${deployer}\n` + + ` Deploy Salt: ${deploySalt}` + ); +} + +/* + * ============================= + * Section: Main + * ============================= + */ +async function main() { + try { + // Read new token configurations from file + const newTokens = JSON.parse(fs.readFileSync(TOKEN_FILE_ROUTE, "utf8")); + await validateTokenInfo(newTokens); + } catch (error) { + exitWithError(error.message); + } + console.log("Validation successful!"); +} + +main(); diff --git a/scripts/validate-token-configs.ts b/scripts/validate-token-configs.ts index c1d4d21..3cb3cc6 100644 --- a/scripts/validate-token-configs.ts +++ b/scripts/validate-token-configs.ts @@ -1,4 +1,4 @@ -import fs from "fs"; +import * as fs from "fs"; import { ethers } from "ethers"; import axios from "axios"; /* From 336100fb59c6549dc0a5df171319da4fed1bf818 Mon Sep 17 00:00:00 2001 From: SGiaccobasso Date: Tue, 24 Sep 2024 02:19:14 -0300 Subject: [PATCH 4/7] chore: create new token (#129) --- .github/workflows/validate-tokens.yml | 42 +- package.json | 7 +- pnpm-lock.yaml | 2402 +++++++++++++++++++++++++ scripts/run-validation.ts | 50 + scripts/validate-token-configs.js | 311 ---- scripts/validate-token-configs.ts | 71 +- 6 files changed, 2527 insertions(+), 356 deletions(-) create mode 100644 pnpm-lock.yaml create mode 100644 scripts/run-validation.ts delete mode 100644 scripts/validate-token-configs.js diff --git a/.github/workflows/validate-tokens.yml b/.github/workflows/validate-tokens.yml index 39cba2c..7172201 100644 --- a/.github/workflows/validate-tokens.yml +++ b/.github/workflows/validate-tokens.yml @@ -9,31 +9,33 @@ jobs: validate-tokens: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + with: + fetch-depth: 0 - - name: Use Node.js - uses: actions/setup-node@v2 + - name: Setup Bun + uses: oven-sh/setup-bun@v1 with: - node-version: "16" + bun-version: latest - name: Install dependencies - run: | - npm install ethers@5.7.2 - npm install axios + run: bun install - name: Extract and validate new tokens run: | - DIFF=$(git diff origin/${{ github.base_ref }} -- registry/mainnet/interchain/squid.tokenlist.json | grep '^+' | grep -v '+++') - NEW_TOKENS=$(echo "$DIFF" | sed -n '/"0x/,/]/{/]/q;p}' | jq -s 'reduce .[] as $item ({}; . + ($item | fromjson))') - echo "$NEW_TOKENS" > new_tokens.json - node scripts/validate-token-configs.js + git fetch origin ${{ github.base_ref }} + git show origin/${{ github.base_ref }}:registry/mainnet/interchain/squid.tokenlist.json > base_file.json + cp registry/mainnet/interchain/squid.tokenlist.json current_file.json - - name: Check validation results - run: | - if [ -f validation_errors.txt ]; then - echo "Validation errors found:" - cat validation_errors.txt - exit 1 - else - echo "All new token configurations are valid." - fi + bun run - < !base.tokens[id]) + .reduce((obj, [id, token]) => ({ ...obj, [id]: token }), {}); + await fs.writeFile('new_tokens.json', JSON.stringify(newTokens, null, 2)); + EOF + + bun run scripts/validate-token-configs.ts diff --git a/package.json b/package.json index b940ae1..0e3d692 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "codegen:chains": "bun run scripts/codegen-chains.ts", "codegen": "bun run codegen:schemas && bun run codegen:chains", "test": "vitest --run", - "prepare": "husky install" + "prepare": "husky install", + "validate": "bun run scripts/run-validation.ts" }, "keywords": [ "axelar", @@ -20,7 +21,9 @@ ], "license": "LicenseRef-LICENSE", "dependencies": { - "@inquirer/prompts": "^4.3.0" + "@inquirer/prompts": "^4.3.0", + "ethers": "^6.13.2", + "axios": "^1.6.7" }, "devDependencies": { "@axelarjs/utils": "^0.1.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..fbaaf59 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2402 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@inquirer/prompts': + specifier: ^4.3.0 + version: 4.3.3 + axios: + specifier: ^1.6.7 + version: 1.7.7 + ethers: + specifier: ^6.13.2 + version: 6.13.2 + devDependencies: + '@axelarjs/utils': + specifier: ^0.1.12 + version: 0.1.12 + '@types/prettier': + specifier: ^2.7.3 + version: 2.7.3 + bun-types: + specifier: ^1.0.30 + version: 1.1.29 + chalk: + specifier: ^5.3.0 + version: 5.3.0 + husky: + specifier: ^8.0.3 + version: 8.0.3 + jsonschema: + specifier: ^1.4.1 + version: 1.4.1 + prettier: + specifier: ^2.8.8 + version: 2.8.8 + pretty-quick: + specifier: ^3.1.3 + version: 3.3.1(prettier@2.8.8) + svgo: + specifier: ^3.0.2 + version: 3.3.2 + tslib: + specifier: ^2.6.2 + version: 2.7.0 + typescript: + specifier: ^5.2.2 + version: 5.6.2 + vitest: + specifier: ^1.3.1 + version: 1.6.0(@types/node@22.6.0) + zod: + specifier: ^3.22.4 + version: 3.23.8 + zod-to-json-schema: + specifier: ^3.22.4 + version: 3.23.3(zod@3.23.8) + zx: + specifier: ^7.2.3 + version: 7.2.3 + +packages: + + '@adraffy/ens-normalize@1.10.1': + resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} + + '@axelarjs/utils@0.1.12': + resolution: {integrity: sha512-56fnZN8ePGsrEYhDPgsnXUDuuKhkhJC/15RCpeRDPJm9MzVvcfleWSEIsYNgpz3gDA1W4n0sNxFyVsoQUeXP2w==} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@inquirer/checkbox@2.5.0': + resolution: {integrity: sha512-sMgdETOfi2dUHT8r7TT1BTKOwNvdDGFDXYWtQ2J69SvlYNntk9I/gJe7r5yvMwwsuKnYbuRs3pNhx4tgNck5aA==} + engines: {node: '>=18'} + + '@inquirer/confirm@3.2.0': + resolution: {integrity: sha512-oOIwPs0Dvq5220Z8lGL/6LHRTEr9TgLHmiI99Rj1PJ1p1czTys+olrgBqZk4E2qC0YTzeHprxSQmoHioVdJ7Lw==} + engines: {node: '>=18'} + + '@inquirer/core@7.1.3': + resolution: {integrity: sha512-MbHUe32W0DRtuw3Hlt+vLWy3c0Vw7wVHSJyYZ16IGVXyxs31BTyo2MOFKzNnzBBAWhsqn+iHO1r84FXIzs39HQ==} + engines: {node: '>=18'} + + '@inquirer/core@9.2.1': + resolution: {integrity: sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==} + engines: {node: '>=18'} + + '@inquirer/editor@2.2.0': + resolution: {integrity: sha512-9KHOpJ+dIL5SZli8lJ6xdaYLPPzB8xB9GZItg39MBybzhxA16vxmszmQFrRwbOA918WA2rvu8xhDEg/p6LXKbw==} + engines: {node: '>=18'} + + '@inquirer/expand@2.3.0': + resolution: {integrity: sha512-qnJsUcOGCSG1e5DTOErmv2BPQqrtT6uzqn1vI/aYGiPKq+FgslGZmtdnXbhuI7IlT7OByDoEEqdnhUnVR2hhLw==} + engines: {node: '>=18'} + + '@inquirer/figures@1.0.6': + resolution: {integrity: sha512-yfZzps3Cso2UbM7WlxKwZQh2Hs6plrbjs1QnzQDZhK2DgyCo6D8AaHps9olkNcUFlcYERMqU3uJSp1gmy3s/qQ==} + engines: {node: '>=18'} + + '@inquirer/input@2.3.0': + resolution: {integrity: sha512-XfnpCStx2xgh1LIRqPXrTNEEByqQWoxsWYzNRSEUxJ5c6EQlhMogJ3vHKu8aXuTacebtaZzMAHwEL0kAflKOBw==} + engines: {node: '>=18'} + + '@inquirer/password@2.2.0': + resolution: {integrity: sha512-5otqIpgsPYIshqhgtEwSspBQE40etouR8VIxzpJkv9i0dVHIpyhiivbkH9/dGiMLdyamT54YRdGJLfl8TFnLHg==} + engines: {node: '>=18'} + + '@inquirer/prompts@4.3.3': + resolution: {integrity: sha512-QLn4tTeLKH3Foqlof0+dY0kLoCGQvvR4MDkHAooPI0rLGPOjUwoiVeEalcMtJTGulqJ76it2UW4++j88WO6KLQ==} + engines: {node: '>=18'} + + '@inquirer/rawlist@2.3.0': + resolution: {integrity: sha512-zzfNuINhFF7OLAtGHfhwOW2TlYJyli7lOUoJUXw/uyklcwalV6WRXBXtFIicN8rTRK1XTiPWB4UY+YuW8dsnLQ==} + engines: {node: '>=18'} + + '@inquirer/select@2.5.0': + resolution: {integrity: sha512-YmDobTItPP3WcEI86GvPo+T2sRHkxxOq/kXmsBjHS5BVXUgvgZ5AfJjkvQvZr03T81NnI3KrrRuMzeuYUQRFOA==} + engines: {node: '>=18'} + + '@inquirer/type@1.5.5': + resolution: {integrity: sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==} + engines: {node: '>=18'} + + '@inquirer/type@2.0.0': + resolution: {integrity: sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==} + engines: {node: '>=18'} + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@noble/curves@1.2.0': + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + + '@noble/hashes@1.3.2': + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@rollup/rollup-android-arm-eabi@4.22.4': + resolution: {integrity: sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.22.4': + resolution: {integrity: sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.22.4': + resolution: {integrity: sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.22.4': + resolution: {integrity: sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.22.4': + resolution: {integrity: sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.22.4': + resolution: {integrity: sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.22.4': + resolution: {integrity: sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.22.4': + resolution: {integrity: sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': + resolution: {integrity: sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.22.4': + resolution: {integrity: sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.22.4': + resolution: {integrity: sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.22.4': + resolution: {integrity: sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.22.4': + resolution: {integrity: sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.22.4': + resolution: {integrity: sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.22.4': + resolution: {integrity: sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.22.4': + resolution: {integrity: sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==} + cpu: [x64] + os: [win32] + + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@trysound/sax@0.2.0': + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + + '@types/jsonfile@6.1.4': + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + + '@types/minimist@1.2.5': + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + + '@types/mute-stream@0.0.4': + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + + '@types/node@18.15.13': + resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} + + '@types/node@18.19.50': + resolution: {integrity: sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==} + + '@types/node@20.12.14': + resolution: {integrity: sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==} + + '@types/node@20.16.5': + resolution: {integrity: sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==} + + '@types/node@22.6.0': + resolution: {integrity: sha512-QyR8d5bmq+eR72TwQDfujwShHMcIrWIYsaQFtXRE58MHPTEKUNxjxvl0yS0qPMds5xbSDWtp7ZpvGFtd7dfMdQ==} + + '@types/prettier@2.7.3': + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + + '@types/ps-tree@1.1.6': + resolution: {integrity: sha512-PtrlVaOaI44/3pl3cvnlK+GxOM3re2526TJvPvh7W+keHIXdV4TE0ylpPBAcvFQCbGitaTXwL9u+RF7qtVeazQ==} + + '@types/which@3.0.4': + resolution: {integrity: sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==} + + '@types/wrap-ansi@3.0.0': + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + + '@types/ws@8.5.12': + resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} + + '@vitest/expect@1.6.0': + resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} + + '@vitest/runner@1.6.0': + resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} + + '@vitest/snapshot@1.6.0': + resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} + + '@vitest/spy@1.6.0': + resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} + + '@vitest/utils@1.6.0': + resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} + + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + + aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.7.7: + resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + bun-types@1.1.29: + resolution: {integrity: sha512-En3/TzSPMPyl5UlUB1MHzHpcrZDakTm7mS203eLoX1fBoEa3PW+aSS8GAqVJ7Is/m34Z5ogL+ECniLY0uDaCPw==} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + chai@4.5.0: + resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + + check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + confbox@0.1.7: + resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + + css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-eql@4.1.4: + resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} + engines: {node: '>=6'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + ethers@6.13.2: + resolution: {integrity: sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==} + engines: {node: '>=14.0.0'} + + event-stream@3.3.4: + resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} + + execa@4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + + from@0.1.7: + resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} + + fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fx@35.0.0: + resolution: {integrity: sha512-O07q+Lknrom5RUX/u53tjo2KTTLUnL0K703JbqMYb19ORijfJNvijzFqqYXEjdk25T9R14S6t6wHD8fCWXCM0g==} + hasBin: true + + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + human-signals@1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + husky@8.0.3: + resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} + engines: {node: '>=14'} + hasBin: true + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + immer@10.1.1: + resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isomorphic-unfetch@4.0.2: + resolution: {integrity: sha512-1Yd+CF/7al18/N2BDbsLBcp6RO3tucSW+jcLq24dqdX5MNbCNTw1z4BsGsp4zNmjr/Izm2cs/cEqZPp4kvWSCA==} + + js-tokens@9.0.0: + resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsonschema@1.4.1: + resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} + + local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + + magic-string@0.30.11: + resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + + map-stream@0.1.0: + resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} + + mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + mlly@1.7.1: + resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + + node-fetch@3.3.1: + resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + + pause-stream@0.0.11: + resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} + + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@3.0.1: + resolution: {integrity: sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==} + engines: {node: '>=10'} + + pkg-types@1.2.0: + resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==} + + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + engines: {node: ^10 || ^12 || >=14} + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + pretty-quick@3.3.1: + resolution: {integrity: sha512-3b36UXfYQ+IXXqex6mCca89jC8u0mYLqFAN5eTQKoXO6oCQYcIVYZEB/5AlBHI7JPYygReM2Vv6Vom/Gln7fBg==} + engines: {node: '>=10.13'} + hasBin: true + peerDependencies: + prettier: ^2.0.0 + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + ps-tree@1.2.0: + resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} + engines: {node: '>= 0.10'} + hasBin: true + + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + ramda@0.29.1: + resolution: {integrity: sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.22.4: + resolution: {integrity: sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + split@0.3.3: + resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + + stream-combiner@0.0.4: + resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-literal@2.1.0: + resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + svgo@3.3.2: + resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} + engines: {node: '>=14.0.0'} + hasBin: true + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinypool@0.8.4: + resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} + engines: {node: '>=14.0.0'} + + tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + + type-detect@4.1.0: + resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} + engines: {node: '>=4'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + typescript@5.6.2: + resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + unfetch@5.0.0: + resolution: {integrity: sha512-3xM2c89siXg0nHvlmYsQ2zkLASvVMBisZm5lF3gFDqfF2xonNStDJyMpvaOBe0a1Edxmqrf2E0HBdmy9QyZaeg==} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + vite-node@1.6.0: + resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + vite@5.4.7: + resolution: {integrity: sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitest@1.6.0: + resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.6.0 + '@vitest/ui': 1.6.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + webpod@0.0.2: + resolution: {integrity: sha512-cSwwQIeg8v4i3p4ajHhwgR7N6VyxAf+KYSSsY6Pd3aETE+xEU4vbitz7qQkB0I321xnhDdgtxuiSfk5r/FVtjg==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@3.0.1: + resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + 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 + + yaml@2.5.1: + resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} + engines: {node: '>= 14'} + hasBin: true + + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + + yoctocolors-cjs@2.1.2: + resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} + engines: {node: '>=18'} + + zod-to-json-schema@3.23.3: + resolution: {integrity: sha512-TYWChTxKQbRJp5ST22o/Irt9KC5nj7CdBKYB/AosCRdj/wxEMvv4NNaj9XVUHDOIp53ZxArGhnw5HMZziPFjog==} + peerDependencies: + zod: ^3.23.3 + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + + zx@7.2.3: + resolution: {integrity: sha512-QODu38nLlYXg/B/Gw7ZKiZrvPkEsjPN3LQ5JFXM7h0JvwhEdPNNl+4Ao1y4+o3CLNiDUNcwzQYZ4/Ko7kKzCMA==} + engines: {node: '>= 16.0.0'} + hasBin: true + +snapshots: + + '@adraffy/ens-normalize@1.10.1': {} + + '@axelarjs/utils@0.1.12': + dependencies: + immer: 10.1.1 + isomorphic-unfetch: 4.0.2 + lodash.debounce: 4.0.8 + lodash.throttle: 4.1.1 + ramda: 0.29.1 + tiny-invariant: 1.3.3 + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@inquirer/checkbox@2.5.0': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.6 + '@inquirer/type': 1.5.5 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + + '@inquirer/confirm@3.2.0': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + + '@inquirer/core@7.1.3': + dependencies: + '@inquirer/figures': 1.0.6 + '@inquirer/type': 1.5.5 + '@types/mute-stream': 0.0.4 + '@types/node': 20.16.5 + '@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 + + '@inquirer/core@9.2.1': + dependencies: + '@inquirer/figures': 1.0.6 + '@inquirer/type': 2.0.0 + '@types/mute-stream': 0.0.4 + '@types/node': 22.6.0 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.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 + yoctocolors-cjs: 2.1.2 + + '@inquirer/editor@2.2.0': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + external-editor: 3.1.0 + + '@inquirer/expand@2.3.0': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + yoctocolors-cjs: 2.1.2 + + '@inquirer/figures@1.0.6': {} + + '@inquirer/input@2.3.0': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + + '@inquirer/password@2.2.0': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + ansi-escapes: 4.3.2 + + '@inquirer/prompts@4.3.3': + dependencies: + '@inquirer/checkbox': 2.5.0 + '@inquirer/confirm': 3.2.0 + '@inquirer/core': 7.1.3 + '@inquirer/editor': 2.2.0 + '@inquirer/expand': 2.3.0 + '@inquirer/input': 2.3.0 + '@inquirer/password': 2.2.0 + '@inquirer/rawlist': 2.3.0 + '@inquirer/select': 2.5.0 + + '@inquirer/rawlist@2.3.0': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 + yoctocolors-cjs: 2.1.2 + + '@inquirer/select@2.5.0': + dependencies: + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.6 + '@inquirer/type': 1.5.5 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + + '@inquirer/type@1.5.5': + dependencies: + mute-stream: 1.0.0 + + '@inquirer/type@2.0.0': + dependencies: + mute-stream: 1.0.0 + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@noble/curves@1.2.0': + dependencies: + '@noble/hashes': 1.3.2 + + '@noble/hashes@1.3.2': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@rollup/rollup-android-arm-eabi@4.22.4': + optional: true + + '@rollup/rollup-android-arm64@4.22.4': + optional: true + + '@rollup/rollup-darwin-arm64@4.22.4': + optional: true + + '@rollup/rollup-darwin-x64@4.22.4': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.22.4': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.22.4': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.22.4': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-x64-musl@4.22.4': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.22.4': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.22.4': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.22.4': + optional: true + + '@sinclair/typebox@0.27.8': {} + + '@trysound/sax@0.2.0': {} + + '@types/estree@1.0.5': {} + + '@types/estree@1.0.6': {} + + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 22.6.0 + + '@types/jsonfile@6.1.4': + dependencies: + '@types/node': 22.6.0 + + '@types/minimist@1.2.5': {} + + '@types/mute-stream@0.0.4': + dependencies: + '@types/node': 22.6.0 + + '@types/node@18.15.13': {} + + '@types/node@18.19.50': + dependencies: + undici-types: 5.26.5 + + '@types/node@20.12.14': + dependencies: + undici-types: 5.26.5 + + '@types/node@20.16.5': + dependencies: + undici-types: 6.19.8 + + '@types/node@22.6.0': + dependencies: + undici-types: 6.19.8 + + '@types/prettier@2.7.3': {} + + '@types/ps-tree@1.1.6': {} + + '@types/which@3.0.4': {} + + '@types/wrap-ansi@3.0.0': {} + + '@types/ws@8.5.12': + dependencies: + '@types/node': 20.12.14 + + '@vitest/expect@1.6.0': + dependencies: + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + chai: 4.5.0 + + '@vitest/runner@1.6.0': + dependencies: + '@vitest/utils': 1.6.0 + p-limit: 5.0.0 + pathe: 1.1.2 + + '@vitest/snapshot@1.6.0': + dependencies: + magic-string: 0.30.11 + pathe: 1.1.2 + pretty-format: 29.7.0 + + '@vitest/spy@1.6.0': + dependencies: + tinyspy: 2.2.1 + + '@vitest/utils@1.6.0': + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + + acorn-walk@8.3.4: + dependencies: + acorn: 8.12.1 + + acorn@8.12.1: {} + + aes-js@4.0.0-beta.5: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + assertion-error@1.1.0: {} + + asynckit@0.4.0: {} + + axios@1.7.7: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + boolbase@1.0.0: {} + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + bun-types@1.1.29: + dependencies: + '@types/node': 20.12.14 + '@types/ws': 8.5.12 + + cac@6.7.14: {} + + chai@4.5.0: + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.4 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.1.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.3.0: {} + + chardet@0.7.0: {} + + check-error@1.0.3: + dependencies: + get-func-name: 2.0.2 + + cli-spinners@2.9.2: {} + + cli-width@4.1.0: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@7.2.0: {} + + confbox@0.1.7: {} + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-select@5.1.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.1.0 + nth-check: 2.1.1 + + css-tree@2.2.1: + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.2.1 + + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.1 + + css-what@6.1.0: {} + + csso@5.0.5: + dependencies: + css-tree: 2.2.1 + + data-uri-to-buffer@4.0.1: {} + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + deep-eql@4.1.4: + dependencies: + type-detect: 4.1.0 + + delayed-stream@1.0.0: {} + + diff-sequences@29.6.3: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.1.0: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + duplexer@0.1.2: {} + + emoji-regex@8.0.0: {} + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + entities@4.5.0: {} + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + + ethers@6.13.2: + dependencies: + '@adraffy/ens-normalize': 1.10.1 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@types/node': 18.15.13 + aes-js: 4.0.0-beta.5 + tslib: 2.4.0 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + event-stream@3.3.4: + dependencies: + duplexer: 0.1.2 + from: 0.1.7 + map-stream: 0.1.0 + pause-stream: 0.0.11 + split: 0.3.3 + stream-combiner: 0.0.4 + through: 2.3.8 + + execa@4.1.0: + dependencies: + cross-spawn: 7.0.3 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + follow-redirects@1.15.9: {} + + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + from@0.1.7: {} + + fs-extra@11.2.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fsevents@2.3.3: + optional: true + + fx@35.0.0: {} + + get-func-name@2.0.2: {} + + get-stream@5.2.0: + dependencies: + pump: 3.0.2 + + get-stream@8.0.1: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + globby@13.2.2: + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 4.0.0 + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + human-signals@1.1.1: {} + + human-signals@5.0.0: {} + + husky@8.0.3: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + immer@10.1.1: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-stream@2.0.1: {} + + is-stream@3.0.0: {} + + isexe@2.0.0: {} + + isomorphic-unfetch@4.0.2: + dependencies: + node-fetch: 3.3.2 + unfetch: 5.0.0 + + js-tokens@9.0.0: {} + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonschema@1.4.1: {} + + local-pkg@0.5.0: + dependencies: + mlly: 1.7.1 + pkg-types: 1.2.0 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + lodash.debounce@4.0.8: {} + + lodash.throttle@4.1.1: {} + + loupe@2.3.7: + dependencies: + get-func-name: 2.0.2 + + magic-string@0.30.11: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + map-stream@0.1.0: {} + + mdn-data@2.0.28: {} + + mdn-data@2.0.30: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mimic-fn@2.1.0: {} + + mimic-fn@4.0.0: {} + + minimist@1.2.8: {} + + mlly@1.7.1: + dependencies: + acorn: 8.12.1 + pathe: 1.1.2 + pkg-types: 1.2.0 + ufo: 1.5.4 + + mri@1.2.0: {} + + ms@2.1.3: {} + + mute-stream@1.0.0: {} + + nanoid@3.3.7: {} + + node-domexception@1.0.0: {} + + node-fetch@3.3.1: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + os-tmpdir@1.0.2: {} + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@5.0.0: + dependencies: + yocto-queue: 1.1.1 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-try@2.2.0: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-type@4.0.0: {} + + pathe@1.1.2: {} + + pathval@1.1.1: {} + + pause-stream@0.0.11: + dependencies: + through: 2.3.8 + + picocolors@1.1.0: {} + + picomatch@2.3.1: {} + + picomatch@3.0.1: {} + + pkg-types@1.2.0: + dependencies: + confbox: 0.1.7 + mlly: 1.7.1 + pathe: 1.1.2 + + postcss@8.4.47: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.0 + source-map-js: 1.2.1 + + prettier@2.8.8: {} + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + pretty-quick@3.3.1(prettier@2.8.8): + dependencies: + execa: 4.1.0 + find-up: 4.1.0 + ignore: 5.3.2 + mri: 1.2.0 + picocolors: 1.1.0 + picomatch: 3.0.1 + prettier: 2.8.8 + tslib: 2.7.0 + + proxy-from-env@1.1.0: {} + + ps-tree@1.2.0: + dependencies: + event-stream: 3.3.4 + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + queue-microtask@1.2.3: {} + + ramda@0.29.1: {} + + react-is@18.3.1: {} + + reusify@1.0.4: {} + + rollup@4.22.4: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.22.4 + '@rollup/rollup-android-arm64': 4.22.4 + '@rollup/rollup-darwin-arm64': 4.22.4 + '@rollup/rollup-darwin-x64': 4.22.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.22.4 + '@rollup/rollup-linux-arm-musleabihf': 4.22.4 + '@rollup/rollup-linux-arm64-gnu': 4.22.4 + '@rollup/rollup-linux-arm64-musl': 4.22.4 + '@rollup/rollup-linux-powerpc64le-gnu': 4.22.4 + '@rollup/rollup-linux-riscv64-gnu': 4.22.4 + '@rollup/rollup-linux-s390x-gnu': 4.22.4 + '@rollup/rollup-linux-x64-gnu': 4.22.4 + '@rollup/rollup-linux-x64-musl': 4.22.4 + '@rollup/rollup-win32-arm64-msvc': 4.22.4 + '@rollup/rollup-win32-ia32-msvc': 4.22.4 + '@rollup/rollup-win32-x64-msvc': 4.22.4 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safer-buffer@2.1.2: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + siginfo@2.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + slash@4.0.0: {} + + source-map-js@1.2.1: {} + + split@0.3.3: + dependencies: + through: 2.3.8 + + stackback@0.0.2: {} + + std-env@3.7.0: {} + + stream-combiner@0.0.4: + dependencies: + duplexer: 0.1.2 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-final-newline@2.0.0: {} + + strip-final-newline@3.0.0: {} + + strip-literal@2.1.0: + dependencies: + js-tokens: 9.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + svgo@3.3.2: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 5.1.0 + css-tree: 2.3.1 + css-what: 6.1.0 + csso: 5.0.5 + picocolors: 1.1.0 + + through@2.3.8: {} + + tiny-invariant@1.3.3: {} + + tinybench@2.9.0: {} + + tinypool@0.8.4: {} + + tinyspy@2.2.1: {} + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tslib@2.4.0: {} + + tslib@2.7.0: {} + + type-detect@4.1.0: {} + + type-fest@0.21.3: {} + + typescript@5.6.2: {} + + ufo@1.5.4: {} + + undici-types@5.26.5: {} + + undici-types@6.19.8: {} + + unfetch@5.0.0: {} + + universalify@2.0.1: {} + + vite-node@1.6.0(@types/node@22.6.0): + dependencies: + cac: 6.7.14 + debug: 4.3.7 + pathe: 1.1.2 + picocolors: 1.1.0 + vite: 5.4.7(@types/node@22.6.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite@5.4.7(@types/node@22.6.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.47 + rollup: 4.22.4 + optionalDependencies: + '@types/node': 22.6.0 + fsevents: 2.3.3 + + vitest@1.6.0(@types/node@22.6.0): + dependencies: + '@vitest/expect': 1.6.0 + '@vitest/runner': 1.6.0 + '@vitest/snapshot': 1.6.0 + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + acorn-walk: 8.3.4 + chai: 4.5.0 + debug: 4.3.7 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.11 + pathe: 1.1.2 + picocolors: 1.1.0 + std-env: 3.7.0 + strip-literal: 2.1.0 + tinybench: 2.9.0 + tinypool: 0.8.4 + vite: 5.4.7(@types/node@22.6.0) + vite-node: 1.6.0(@types/node@22.6.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.6.0 + transitivePeerDependencies: + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + web-streams-polyfill@3.3.3: {} + + webpod@0.0.2: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@3.0.1: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + ws@8.17.1: {} + + yaml@2.5.1: {} + + yocto-queue@1.1.1: {} + + yoctocolors-cjs@2.1.2: {} + + zod-to-json-schema@3.23.3(zod@3.23.8): + dependencies: + zod: 3.23.8 + + zod@3.23.8: {} + + zx@7.2.3: + dependencies: + '@types/fs-extra': 11.0.4 + '@types/minimist': 1.2.5 + '@types/node': 18.19.50 + '@types/ps-tree': 1.1.6 + '@types/which': 3.0.4 + chalk: 5.3.0 + fs-extra: 11.2.0 + fx: 35.0.0 + globby: 13.2.2 + minimist: 1.2.8 + node-fetch: 3.3.1 + ps-tree: 1.2.0 + webpod: 0.0.2 + which: 3.0.1 + yaml: 2.5.1 diff --git a/scripts/run-validation.ts b/scripts/run-validation.ts new file mode 100644 index 0000000..dce319d --- /dev/null +++ b/scripts/run-validation.ts @@ -0,0 +1,50 @@ +import { readFile, writeFile, unlink } from "fs/promises"; +import { execSync } from "child_process"; +import path from "path"; + +const tokenListPath = "registry/mainnet/interchain/squid.tokenlist.json"; +const tempFile = "new_tokens.json"; + +async function cleanup() { + try { + await unlink(tempFile); + } catch {} +} + +async function main() { + try { + // Fetching latest changes from main branch + execSync("git fetch origin main", { stdio: "inherit" }); + const mainContent = execSync(`git show "origin/main":${tokenListPath}`, { + encoding: "utf-8", + }); + const mainTokens = JSON.parse(mainContent).tokens; + + // Read local version + const localContent = await readFile( + path.join(process.cwd(), tokenListPath), + "utf8" + ); + const localTokens = JSON.parse(localContent).tokens; + + // Extract new tokens to new_tokens.json + const newTokens = Object.entries(localTokens) + .filter(([id]) => !mainTokens[id]) + .reduce((obj, [id, token]) => ({ ...obj, [id]: token }), {}); + + await writeFile("new_tokens.json", JSON.stringify(newTokens, null, 2)); + } catch (error) { + console.error("An error occurred:", error); + cleanup(); + } + + // Run validation script + try { + execSync("bun run scripts/validate-token-configs.ts", { stdio: "inherit" }); + } catch { + } finally { + cleanup(); + } +} + +main(); diff --git a/scripts/validate-token-configs.js b/scripts/validate-token-configs.js deleted file mode 100644 index 0a013b1..0000000 --- a/scripts/validate-token-configs.js +++ /dev/null @@ -1,311 +0,0 @@ -const fs = require("fs"); -const ethers = require("ethers"); -const axios = require("axios"); - -/* - * ============================= - * Section: Constants - * ============================= - */ -const tokenManagerTypes = [ - "nativeInterchainToken", - "mintBurnFrom", - "lockUnlock", - "lockUnlockFee", - "mintBurn", - "gateway", -]; -const ITSAddress = "0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C"; -const TOKEN_FILE_ROUTE = "./new_tokens.json"; -const COINGECKO_API_KEY = "CG-3VGxh1K3Qk7jAvpt4DJA3LvB"; -const COINGECKO_URL = "https://api.coingecko.com/api/v3/coins/"; -const CHAIN_CONFIGS_URL = - "https://axelar-mainnet.s3.us-east-2.amazonaws.com/configs/mainnet-config-1.x.json"; -const ERC20ABI = [ - { - constant: true, - inputs: [], - name: "name", - outputs: [{ name: "", type: "string" }], - type: "function", - }, - { - constant: true, - inputs: [], - name: "symbol", - outputs: [{ name: "", type: "string" }], - type: "function", - }, - { - constant: true, - inputs: [], - name: "decimals", - outputs: [{ name: "", type: "uint8" }], - type: "function", - }, -]; -const ITSABI = [ - { - inputs: [ - { internalType: "address", name: "sender", type: "address" }, - { internalType: "bytes32", name: "salt", type: "bytes32" }, - ], - name: "interchainTokenId", - outputs: [{ internalType: "bytes32", name: "tokenId", type: "bytes32" }], - stateMutability: "pure", - type: "function", - }, -]; -const tokenManagerABI = [ - { - inputs: [], - name: "tokenAddress", - outputs: [{ internalType: "address", name: "", type: "address" }], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "implementationType", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, -]; - -/* - * ============================= - * Section: Helper Functions - * ============================= - */ -async function getAxelarChains() { - const { data } = await axios.get(CHAIN_CONFIGS_URL); - return data.chains; -} - -async function getRpcUrl(axelarChainId) { - try { - const chains = await getAxelarChains(); - return chains[axelarChainId].config.rpc[0]; - } catch (error) { - throw new Error( - `Error fetching chain configs for chain '${axelarChainId}':\n ${error.message}` - ); - } -} - -function exitWithError(errorMessage) { - console.error(errorMessage); - fs.writeFileSync("validation_errors.txt", errorMessage); - process.exit(1); -} - -/* - * ============================= - * Section: Validation Functions - * ============================= - */ -async function validateTokenInfo(tokenInfo) { - for (const [tokenId, info] of Object.entries(tokenInfo)) { - console.log(`\nValidating token: ${tokenId}...`); - try { - await validateTokenId(tokenId, info); - await validateCoinGeckoId(tokenId, info); - await validateChains(info); - await validateOriginChain(info); - await validateDeployerAndSalt(tokenId, info); - } catch (error) { - exitWithError(error.message); - } - } -} - -async function validateTokenId(tokenId, info) { - if (tokenId !== info.tokenId) { - throw new Error(`Mismatch in tokenId: ${tokenId} vs ${info.tokenId}`); - } -} - -async function validateCoinGeckoId(tokenId, { coinGeckoId, prettySymbol }) { - if (!coinGeckoId) - throw new Error(`CoinGecko ID is missing for token ${tokenId}`); - - try { - const response = await axios.get(COINGECKO_URL + coinGeckoId, { - headers: { - "x-cg-demo-api-key": COINGECKO_API_KEY, - }, - }); - - if (response.status !== 200) - throw new Error( - `CoinGecko API returned status ${response.status} for token ${tokenId}` - ); - - const coinData = response.data; - if (coinData.symbol.toLowerCase() !== prettySymbol.toLowerCase()) { - throw new Error( - `CoinGecko symbol (${coinData.symbol}) does not match prettySymbol (${prettySymbol}) for token ${tokenId}` - ); - } - } catch (error) { - if (axios.isAxiosError(error) && error.response?.status === 404) { - throw new Error( - `CoinGecko ID ${coinGeckoId} not found for token ${tokenId}` - ); - } - throw new Error( - `Error fetching data from CoinGecko for token ${tokenId}: ${error.message}` - ); - } -} - -async function validateChains(info) { - for (const chain of info.chains) { - console.log(`Validating for ${chain.axelarChainId}...`); - - const rpcUrl = await getRpcUrl(chain.axelarChainId); - const provider = new ethers.JsonRpcProvider(rpcUrl); - - await validateTokenAddress(chain, provider); - await validateTokenDetails(chain, info, provider); - await validateTokenManager(chain, provider); - } -} - -async function validateTokenAddress(chain, provider) { - const tokenCode = await provider.getCode(chain.tokenAddress); - if (tokenCode === "0x") - throw new Error( - `Token address ${chain.tokenAddress} does not exist on chain ${chain.axelarChainId}` - ); -} - -async function validateTokenDetails( - chain, - { originAxelarChainId, prettySymbol, decimals }, - provider -) { - const tokenContract = new ethers.Contract( - chain.tokenAddress, - ERC20ABI, - provider - ); - const tokenName = await tokenContract.name(); - const tokenSymbol = await tokenContract.symbol(); - const tokenDecimals = await tokenContract.decimals(); - const decimalsFromContract = Number(tokenDecimals); - - if (tokenName.toLowerCase() !== chain.name.toLowerCase()) - throw new Error( - `Token name mismatch on chain ${chain.axelarChainId}: expected ${chain.name}, got ${tokenName}` - ); - if (tokenSymbol.toLowerCase() !== chain.symbol.toLowerCase()) - throw new Error( - `Token symbol mismatch on chain ${chain.axelarChainId}: expected ${chain.symbol}, got ${tokenSymbol}` - ); - if (originAxelarChainId === chain.axelarChainId) { - if (tokenSymbol.toLowerCase() !== prettySymbol.toLowerCase()) - throw new Error( - `Token symbol mismatch on chain ${chain.axelarChainId}: expected ${prettySymbol}, got ${tokenSymbol}` - ); - if (decimalsFromContract !== decimals) - throw new Error( - `Token decimals mismatch on chain ${chain.axelarChainId}: expected ${decimals}, got ${decimalsFromContract}` - ); - } -} - -async function validateTokenManager(chain, provider) { - const managerCode = await provider.getCode(chain.tokenManager); - if (managerCode === "0x") { - throw new Error( - `Token manager ${chain.tokenManager} does not exist on chain ${chain.axelarChainId}` - ); - } - - const tokenManagerContract = new ethers.Contract( - chain.tokenManager, - tokenManagerABI, - provider - ); - const managedTokenAddress = await tokenManagerContract.tokenAddress(); - if (managedTokenAddress.toLowerCase() !== chain.tokenAddress.toLowerCase()) - throw new Error( - `Token manager ${chain.tokenManager} on chain ${chain.axelarChainId} does not manage the specified token address ${chain.tokenAddress}` - ); - - const implementationType = await tokenManagerContract.implementationType(); - if ( - Number(implementationType) !== - tokenManagerTypes.indexOf(chain.tokenManagerType) - ) - throw new Error( - `Token manager on chain ${ - chain.axelarChainId - } has incorrect implementation type: expected '${ - tokenManagerTypes[Number(implementationType)] || "Unknown" - }', got '${chain.tokenManagerType}'` - ); -} - -async function validateOriginChain({ chains, originAxelarChainId }) { - const originChain = chains.find( - (chain) => chain.axelarChainId === originAxelarChainId - ); - if (!originChain) - throw new Error( - `Origin chain ${originAxelarChainId} not found in chains list` - ); -} - -async function validateDeployerAndSalt( - tokenId, - { originAxelarChainId, deployer, deploySalt } -) { - const rpcUrl = await getRpcUrl(originAxelarChainId); - const provider = new ethers.JsonRpcProvider(rpcUrl); - const itsContract = new ethers.Contract(ITSAddress, ITSABI, provider); - - if (!ethers.isAddress(deployer)) - throw new Error(`Invalid deployer address: ${deployer}`); - - const calculatedTokenId = await itsContract.interchainTokenId( - deployer, - deploySalt - ); - - if (calculatedTokenId.toLowerCase() !== tokenId.toLowerCase()) - throw new Error( - `Mismatch in interchainTokenId for token ${tokenId}:\n` + - `Deployer or Deploy Salt could be incorrect\n` + - ` Expected: ${tokenId}\n` + - ` Calculated: ${calculatedTokenId}\n` + - ` Deployer: ${deployer}\n` + - ` Deploy Salt: ${deploySalt}` - ); -} - -/* - * ============================= - * Section: Main - * ============================= - */ -async function main() { - try { - // Read new token configurations from file - const newTokens = JSON.parse(fs.readFileSync(TOKEN_FILE_ROUTE, "utf8")); - await validateTokenInfo(newTokens); - } catch (error) { - exitWithError(error.message); - } - console.log("Validation successful!"); -} - -main(); diff --git a/scripts/validate-token-configs.ts b/scripts/validate-token-configs.ts index 3cb3cc6..f02f31d 100644 --- a/scripts/validate-token-configs.ts +++ b/scripts/validate-token-configs.ts @@ -1,6 +1,7 @@ import * as fs from "fs"; import { ethers } from "ethers"; import axios from "axios"; + /* * ============================= * Section: Types and Constants @@ -40,7 +41,7 @@ const tokenManagerTypes = [ "lockUnlockFee", "mintBurn", "gateway", -] as const; +]; const ITSAddress = "0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C"; const TOKEN_FILE_ROUTE = "./new_tokens.json"; const COINGECKO_API_KEY = "CG-3VGxh1K3Qk7jAvpt4DJA3LvB"; @@ -115,10 +116,44 @@ async function getAxelarChains() { return data.chains; } -async function getRpcUrl(axelarChainId: string): Promise { +async function getProvider(axelarChainId: string) { + // Create rpc provider with backup urls + const rpcUrls = await getRpcUrls(axelarChainId); + let provider; + for (let attempt = 0; attempt < rpcUrls.length; attempt++) { + try { + const rpcURL = rpcUrls[attempt]; + provider = await new ethers.JsonRpcProvider(rpcURL); + + // Test the provider with a simple call + await provider.getNetwork(); + break; + } catch (error) { + console.error( + `Attempt ${ + attempt + 1 + } failed to initialize provider for ${axelarChainId}: ${ + (error as Error).message + }` + ); + + if (attempt === rpcUrls.length - 1) { + // If this was the last attempt, we throw the error + throw new Error( + `Failed to initialize provider for ${axelarChainId} after ${ + attempt + 1 + } attempts: ${(error as Error).message}` + ); + } + } + } + return provider; +} + +async function getRpcUrls(axelarChainId: string): Promise { try { const chains = await getAxelarChains(); - return chains[axelarChainId].config.rpc[0]; + return chains[axelarChainId].config.rpc; } catch (error) { throw new Error( `Error fetching chain configs for chain '${axelarChainId}':\n ${ @@ -128,9 +163,8 @@ async function getRpcUrl(axelarChainId: string): Promise { } } -function exitWitheError(errorMessage: string) { +function exitWithError(errorMessage: string) { console.error(errorMessage); - fs.writeFileSync("validation_errors.txt", errorMessage); process.exit(1); } @@ -139,19 +173,17 @@ function exitWitheError(errorMessage: string) { * Section: Validation Functions * ============================= */ -async function validateTokenInfo( - tokenInfo: Record -): Promise { +async function validateTokenInfo(tokenInfo: Record) { for (const [tokenId, info] of Object.entries(tokenInfo)) { console.log(`\nValidating token: ${tokenId}...`); try { await validateTokenId(tokenId, info); - await validateCoinGeckoId(tokenId, info); await validateChains(info); await validateOriginChain(info); await validateDeployerAndSalt(tokenId, info); + await validateCoinGeckoId(tokenId, info); } catch (error) { - exitWitheError((error as Error).message); + exitWithError((error as Error).message); } } } @@ -208,8 +240,7 @@ async function validateChains(info: TokenInfo): Promise { for (const chain of info.chains) { console.log(`Validating for ${chain.axelarChainId}...`); - const rpcUrl = await getRpcUrl(chain.axelarChainId); - const provider = new ethers.JsonRpcProvider(rpcUrl); + const provider = await getProvider(chain.axelarChainId); await validateTokenAddress(chain, provider); await validateTokenDetails(chain, info, provider); @@ -217,10 +248,7 @@ async function validateChains(info: TokenInfo): Promise { } } -async function validateTokenAddress( - chain: ChainInfo, - provider: ethers.JsonRpcProvider -): Promise { +async function validateTokenAddress(chain, provider) { const tokenCode = await provider.getCode(chain.tokenAddress); if (tokenCode === "0x") throw new Error( @@ -315,9 +343,8 @@ async function validateOriginChain({ async function validateDeployerAndSalt( tokenId: string, { originAxelarChainId, deployer, deploySalt }: TokenInfo -): Promise { - const rpcUrl = await getRpcUrl(originAxelarChainId); - const provider = new ethers.JsonRpcProvider(rpcUrl); +) { + const provider = await getProvider(originAxelarChainId); const itsContract = new ethers.Contract(ITSAddress, ITSABI, provider); if (!ethers.isAddress(deployer)) @@ -347,12 +374,10 @@ async function validateDeployerAndSalt( async function main() { try { // Read new token configurations from file - const newTokens: Record = JSON.parse( - fs.readFileSync(TOKEN_FILE_ROUTE, "utf8") - ); + const newTokens = JSON.parse(fs.readFileSync(TOKEN_FILE_ROUTE, "utf8")); await validateTokenInfo(newTokens); } catch (error) { - exitWitheError((error as Error).message); + exitWithError((error as Error).message); } console.log("Validation successful!"); } From c25040c7a1ac7b6f4a3fc76d168243a68cfd5243 Mon Sep 17 00:00:00 2001 From: SGiaccobasso Date: Tue, 24 Sep 2024 02:40:07 -0300 Subject: [PATCH 5/7] Test/action (#130) --- .github/workflows/validate-tokens.yml | 20 +---- .../mainnet/interchain/squid.tokenlist.json | 80 +++++++++++++++++++ scripts/run-validation.ts | 42 +++++----- scripts/validate-token-configs.ts | 11 ++- 4 files changed, 111 insertions(+), 42 deletions(-) diff --git a/.github/workflows/validate-tokens.yml b/.github/workflows/validate-tokens.yml index 7172201..e215c17 100644 --- a/.github/workflows/validate-tokens.yml +++ b/.github/workflows/validate-tokens.yml @@ -21,21 +21,5 @@ jobs: - name: Install dependencies run: bun install - - name: Extract and validate new tokens - run: | - git fetch origin ${{ github.base_ref }} - git show origin/${{ github.base_ref }}:registry/mainnet/interchain/squid.tokenlist.json > base_file.json - cp registry/mainnet/interchain/squid.tokenlist.json current_file.json - - bun run - < !base.tokens[id]) - .reduce((obj, [id, token]) => ({ ...obj, [id]: token }), {}); - await fs.writeFile('new_tokens.json', JSON.stringify(newTokens, null, 2)); - EOF - - bun run scripts/validate-token-configs.ts + - name: Run validation + run: bun run scripts/run-validation.ts diff --git a/registry/mainnet/interchain/squid.tokenlist.json b/registry/mainnet/interchain/squid.tokenlist.json index 32663f8..a54e457 100644 --- a/registry/mainnet/interchain/squid.tokenlist.json +++ b/registry/mainnet/interchain/squid.tokenlist.json @@ -2502,6 +2502,86 @@ } ] }, + "0x1ac831937426660d5952bc9ae0dc7c895a3c3f5f159d3518813df30181404be6": { + "tokenId": "0x1ac831937426660d5952bc9ae0dc7c895a3c3f5f159d3518813df30181404be6", + "deployer": "0x7AAd74b7f0d60D5867B59dbD377a71783425af47", + "originalMinter": null, + "prettySymbol": "agETH", + "decimals": 18, + "originAxelarChainId": "ethereum", + "tokenType": "canonical", + "deploySalt": "0x", + "iconUrls": { + "svg": "https://raw.githubusercontent.com/axelarnetwork/axelar-configs/main/images/tokens/ageth.svg" + }, + "deploymentMessageId": "0x9c77e79177ec83dff97c1d0749cd9d4cd2a7f2c6b36256d017df53819e10ab0e-476", + "chains": [ + { + "symbol": "agETH", + "name": "Kelp Gain", + "axelarChainId": "ethereum", + "tokenAddress": "0xe1b4d34e8754600962cd944b535180bd758e6c2e", + "tokenManager": "0xa526eDa85A1CF901E77a33493852B0aFD910Ed0d", + "tokenManagerType": "lockUnlock" + }, + { + "symbol": "agETH", + "name": "Kelp Gain", + "axelarChainId": "polygon", + "tokenAddress": "0x1bD0Fe8E92a157D3ef66C9FB9e38621252b407c2", + "tokenManager": "0xa526eDa85A1CF901E77a33493852B0aFD910Ed0d", + "tokenManagerType": "mintBurn" + }, + { + "symbol": "agETH", + "name": "Kelp Gain", + "axelarChainId": "optimism", + "tokenAddress": "0x1bD0Fe8E92a157D3ef66C9FB9e38621252b407c2", + "tokenManager": "0xa526eDa85A1CF901E77a33493852B0aFD910Ed0d", + "tokenManagerType": "mintBurn" + }, + { + "symbol": "agETH", + "name": "Kelp Gain", + "axelarChainId": "linea", + "tokenAddress": "0x1bD0Fe8E92a157D3ef66C9FB9e38621252b407c2", + "tokenManager": "0xa526eDa85A1CF901E77a33493852B0aFD910Ed0d", + "tokenManagerType": "mintBurn" + }, + { + "symbol": "agETH", + "name": "Kelp Gain", + "axelarChainId": "base", + "tokenAddress": "0x1bD0Fe8E92a157D3ef66C9FB9e38621252b407c2", + "tokenManager": "0xa526eDa85A1CF901E77a33493852B0aFD910Ed0d", + "tokenManagerType": "mintBurn" + }, + { + "symbol": "agETH", + "name": "Kelp Gain", + "axelarChainId": "scroll", + "tokenAddress": "0x1bD0Fe8E92a157D3ef66C9FB9e38621252b407c2", + "tokenManager": "0xa526eDa85A1CF901E77a33493852B0aFD910Ed0d", + "tokenManagerType": "mintBurn" + }, + { + "symbol": "agETH", + "name": "Kelp Gain", + "axelarChainId": "blast", + "tokenAddress": "0x1bD0Fe8E92a157D3ef66C9FB9e38621252b407c2", + "tokenManager": "0xa526eDa85A1CF901E77a33493852B0aFD910Ed0d", + "tokenManagerType": "mintBurn" + }, + { + "symbol": "agETH", + "name": "Kelp Gain", + "axelarChainId": "arbitrum", + "tokenAddress": "0x1bD0Fe8E92a157D3ef66C9FB9e38621252b407c2", + "tokenManager": "0xa526eDa85A1CF901E77a33493852B0aFD910Ed0d", + "tokenManagerType": "mintBurn" + } + ] + }, "0x291401f2645b4a6a6439323c4db76a820439ace0a5ad7637e10a3f5adfdd7c33": { "tokenId": "0x291401f2645b4a6a6439323c4db76a820439ace0a5ad7637e10a3f5adfdd7c33", "deployer": "0xfb311Eb413a49389a2078284B57C8BEFeF6aFF67", diff --git a/scripts/run-validation.ts b/scripts/run-validation.ts index dce319d..d847c80 100644 --- a/scripts/run-validation.ts +++ b/scripts/run-validation.ts @@ -1,15 +1,8 @@ -import { readFile, writeFile, unlink } from "fs/promises"; -import { execSync } from "child_process"; +import { readFile } from "fs/promises"; +import { execSync, spawnSync } from "child_process"; import path from "path"; const tokenListPath = "registry/mainnet/interchain/squid.tokenlist.json"; -const tempFile = "new_tokens.json"; - -async function cleanup() { - try { - await unlink(tempFile); - } catch {} -} async function main() { try { @@ -27,23 +20,30 @@ async function main() { ); const localTokens = JSON.parse(localContent).tokens; - // Extract new tokens to new_tokens.json + // Extract new tokens const newTokens = Object.entries(localTokens) .filter(([id]) => !mainTokens[id]) .reduce((obj, [id, token]) => ({ ...obj, [id]: token }), {}); - await writeFile("new_tokens.json", JSON.stringify(newTokens, null, 2)); - } catch (error) { - console.error("An error occurred:", error); - cleanup(); - } + // Run validation script with new tokens as parameter + const result = spawnSync( + "bun", + ["run", "scripts/validate-token-configs.ts"], + { + input: JSON.stringify(newTokens), + encoding: "utf-8", + stdio: ["pipe", "inherit", "inherit"], + } + ); - // Run validation script - try { - execSync("bun run scripts/validate-token-configs.ts", { stdio: "inherit" }); - } catch { - } finally { - cleanup(); + if (result.status !== 0) { + throw new Error(`Validation script exited with status ${result.status}`); + } + + console.log("All new token configurations are valid."); + } catch (error) { + console.error("Validation failed:", (error as Error).message); + process.exit(1); } } diff --git a/scripts/validate-token-configs.ts b/scripts/validate-token-configs.ts index f02f31d..21e5f24 100644 --- a/scripts/validate-token-configs.ts +++ b/scripts/validate-token-configs.ts @@ -1,4 +1,3 @@ -import * as fs from "fs"; import { ethers } from "ethers"; import axios from "axios"; @@ -43,7 +42,6 @@ const tokenManagerTypes = [ "gateway", ]; const ITSAddress = "0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C"; -const TOKEN_FILE_ROUTE = "./new_tokens.json"; const COINGECKO_API_KEY = "CG-3VGxh1K3Qk7jAvpt4DJA3LvB"; const COINGECKO_URL = "https://api.coingecko.com/api/v3/coins/"; const CHAIN_CONFIGS_URL = @@ -111,6 +109,13 @@ const tokenManagerABI = [ * Section: Helper Functions * ============================= */ + +async function getInputTokens() { + const chunks: any[] = []; + for await (const chunk of process.stdin) chunks.push(chunk); + return JSON.parse(Buffer.concat(chunks).toString("utf8")); +} + async function getAxelarChains() { const { data } = await axios.get(CHAIN_CONFIGS_URL); return data.chains; @@ -374,7 +379,7 @@ async function validateDeployerAndSalt( async function main() { try { // Read new token configurations from file - const newTokens = JSON.parse(fs.readFileSync(TOKEN_FILE_ROUTE, "utf8")); + const newTokens = await getInputTokens(); await validateTokenInfo(newTokens); } catch (error) { exitWithError((error as Error).message); From 79ced73f8cabb87142fa89ab8aec9f42b8bc53d3 Mon Sep 17 00:00:00 2001 From: SGiaccobasso Date: Tue, 24 Sep 2024 10:49:04 -0300 Subject: [PATCH 6/7] chore: update run validation script --- scripts/run-validation.ts | 33 ++++++++++++++++++++----------- scripts/validate-token-configs.ts | 3 ++- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/scripts/run-validation.ts b/scripts/run-validation.ts index d847c80..e0af3f6 100644 --- a/scripts/run-validation.ts +++ b/scripts/run-validation.ts @@ -1,5 +1,5 @@ import { readFile } from "fs/promises"; -import { execSync, spawnSync } from "child_process"; +import { execSync, spawn } from "child_process"; import path from "path"; const tokenListPath = "registry/mainnet/interchain/squid.tokenlist.json"; @@ -26,21 +26,30 @@ async function main() { .reduce((obj, [id, token]) => ({ ...obj, [id]: token }), {}); // Run validation script with new tokens as parameter - const result = spawnSync( + const validationProcess = spawn( "bun", ["run", "scripts/validate-token-configs.ts"], - { - input: JSON.stringify(newTokens), - encoding: "utf-8", - stdio: ["pipe", "inherit", "inherit"], - } + { stdio: ["pipe", "inherit", "inherit"] } ); - if (result.status !== 0) { - throw new Error(`Validation script exited with status ${result.status}`); - } - - console.log("All new token configurations are valid."); + validationProcess.stdin.setDefaultEncoding("utf-8"); + validationProcess.stdin.write(JSON.stringify(newTokens)); + validationProcess.stdin.end(); + + await new Promise((resolve, reject) => { + validationProcess.on("close", (code) => { + if (code === 0) { + console.log("All new token configurations are valid."); + resolve(null); + } else { + reject(new Error(`Validation script exited with status ${code}`)); + } + }); + + validationProcess.on("error", (error) => { + reject(new Error(`Validation process error: ${error.message}`)); + }); + }); } catch (error) { console.error("Validation failed:", (error as Error).message); process.exit(1); diff --git a/scripts/validate-token-configs.ts b/scripts/validate-token-configs.ts index 21e5f24..816ff0b 100644 --- a/scripts/validate-token-configs.ts +++ b/scripts/validate-token-configs.ts @@ -110,6 +110,7 @@ const tokenManagerABI = [ * ============================= */ +// Get the tokens to be validated async function getInputTokens() { const chunks: any[] = []; for await (const chunk of process.stdin) chunks.push(chunk); @@ -128,7 +129,7 @@ async function getProvider(axelarChainId: string) { for (let attempt = 0; attempt < rpcUrls.length; attempt++) { try { const rpcURL = rpcUrls[attempt]; - provider = await new ethers.JsonRpcProvider(rpcURL); + provider = new ethers.JsonRpcProvider(rpcURL); // Test the provider with a simple call await provider.getNetwork(); From 11648006c183971baa82bd50b7e5599eaba64f0c Mon Sep 17 00:00:00 2001 From: SGiaccobasso Date: Tue, 24 Sep 2024 10:52:32 -0300 Subject: [PATCH 7/7] chore: update run validation script --- scripts/run-validation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run-validation.ts b/scripts/run-validation.ts index e0af3f6..5d4892a 100644 --- a/scripts/run-validation.ts +++ b/scripts/run-validation.ts @@ -6,7 +6,7 @@ const tokenListPath = "registry/mainnet/interchain/squid.tokenlist.json"; async function main() { try { - // Fetching latest changes from main branch + // Fetch latest changes from main branch execSync("git fetch origin main", { stdio: "inherit" }); const mainContent = execSync(`git show "origin/main":${tokenListPath}`, { encoding: "utf-8",