diff --git a/.env.example b/.env.example index 4cb128b..ea2239c 100644 --- a/.env.example +++ b/.env.example @@ -5,6 +5,10 @@ RPC_URL_OPTIMISM= RPC_URL_ETHEREUM_TESTNET= RPC_URL_HYPEREVM_TESTNET= +# Use https://www.helius.dev/ for mainnet +RPC_URL_SOLANA=https://api.mainnet-beta.solana.com +RPC_URL_SOLANA_TESTNET=https://api.devnet.solana.com + # Hardhat. MNEMONIC= PRIVATE_KEY= diff --git a/Anchor.toml b/Anchor.toml index 0369366..0630242 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -7,7 +7,7 @@ resolution = false skip-lint = false [programs.localnet] -oft = "G2BYTnfGCMQAErMZkTBCFSapKevzf6QCjizjXi8hFEtJ" +oft = "H5WWM7uWHbmZjThKyPbjNGvAagizKA9zzchZWwn79W99" [registry] url = "https://api.apr.dev" @@ -15,6 +15,3 @@ url = "https://api.apr.dev" [provider] cluster = "localnet" wallet = "./junk-id.json" - -[scripts] -test = "npx jest test/anchor" diff --git a/consts/mainnet.ts b/consts/mainnet.ts index d069807..54cec03 100644 --- a/consts/mainnet.ts +++ b/consts/mainnet.ts @@ -7,21 +7,25 @@ export const OPTIONAL_DVNS: Record>> [EndpointId.ETHEREUM_V2_MAINNET]: '0xa4fe5a5b9a846458a70cd0748228aed3bf65c2cd', [EndpointId.HYPERLIQUID_V2_MAINNET]: '0x83342ec538df0460e730a8f543fe63063e2d44c4', [EndpointId.OPTIMISM_V2_MAINNET]: '0x5b6735c66d97479ccd18294fc96b3084ecb2fa3f', + [EndpointId.SOLANA_V2_MAINNET]: '7jMeX5mzXnSSKYd8DxBDP4xMnkNFZZZm5W28FWUTbwU3', }, DEUTSCHE_TELEKOM: { [EndpointId.ETHEREUM_V2_MAINNET]: '0x373a6e5c0c4e89e24819f00aa37ea370917aaff4', [EndpointId.HYPERLIQUID_V2_MAINNET]: '0x32ffd21260172518a8844fec76a88c8f239c384b', [EndpointId.OPTIMISM_V2_MAINNET]: '0x427bd19a0463fc4edc2e247d35eb61323d7e5541', + [EndpointId.SOLANA_V2_MAINNET]: 'FxFxe8j7e2xgpP9bw8LUehmz7DoQXaNFadJMEUKwBcRs', }, LUGANODES: { [EndpointId.ETHEREUM_V2_MAINNET]: '0x58249a2ec05c1978bf21df1f5ec1847e42455cf4', [EndpointId.HYPERLIQUID_V2_MAINNET]: '0x9e451905f65ef78d62b93dac3513486da8429d0a', [EndpointId.OPTIMISM_V2_MAINNET]: '0xd841a741addcb6dea735d3b8c9faf96ba3f3d30d', + [EndpointId.SOLANA_V2_MAINNET]: '41QAdzUraTcvk1P2B6fcs5nQ4EeEKEGnQy5EPpCQ5AdX', }, P2P: { [EndpointId.ETHEREUM_V2_MAINNET]: '0x06559ee34d85a88317bf0bfe307444116c631b67', [EndpointId.HYPERLIQUID_V2_MAINNET]: '0xc7423626016bc40375458bc0277f28681ec91c8e', [EndpointId.OPTIMISM_V2_MAINNET]: '0x539008c98b17803a273edf98aba2d4414ee3f4d7', + [EndpointId.SOLANA_V2_MAINNET]: '29EKzmCscUg8mf4f5uskwMqvu2SXM8hKF1gWi1cCBoKT', }, } @@ -32,6 +36,7 @@ export const CONFIRMATIONS: Partial> = { [EndpointId.ETHEREUM_V2_MAINNET]: 15, [EndpointId.HYPERLIQUID_V2_MAINNET]: 1, [EndpointId.OPTIMISM_V2_MAINNET]: 20, + [EndpointId.SOLANA_V2_MAINNET]: 32, } const DEFAULT_ENFORCED_OPTIONS: OAppEnforcedOption[] = [ @@ -43,12 +48,17 @@ const DEFAULT_ENFORCED_OPTIONS: OAppEnforcedOption[] = [ export const ENFORCED_OPTIONS: Partial> = { [EndpointId.ETHEREUM_V2_MAINNET]: DEFAULT_ENFORCED_OPTIONS, [EndpointId.HYPERLIQUID_V2_MAINNET]: DEFAULT_ENFORCED_OPTIONS, + [EndpointId.SOLANA_V2_MAINNET]: [ + { msgType: 1, optionType: ExecutorOptionType.LZ_RECEIVE, gas: 200_000, value: 2_500_000 }, + { msgType: 2, optionType: ExecutorOptionType.LZ_RECEIVE, gas: 200_000, value: 2_500_000 }, + ], } export const OWNERS: Partial> = { [EndpointId.ETHEREUM_V2_MAINNET]: '0xfA633B67b1d9371eBa32cf3476F275D75C75ce77', [EndpointId.HYPERLIQUID_V2_MAINNET]: '0xfA633B67b1d9371eBa32cf3476F275D75C75ce77', [EndpointId.OPTIMISM_V2_MAINNET]: '0xfA633B67b1d9371eBa32cf3476F275D75C75ce77', + [EndpointId.SOLANA_V2_MAINNET]: 'FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E', } as const export const getRequiredDVNs = (_eid: EndpointId): string[] => { diff --git a/consts/testnet.ts b/consts/testnet.ts index 4ed9a27..e4d90b6 100644 --- a/consts/testnet.ts +++ b/consts/testnet.ts @@ -3,11 +3,13 @@ import { ExecutorOptionType } from '@layerzerolabs/lz-v2-utilities' import { OAppEnforcedOption } from '@layerzerolabs/toolbox-hardhat' // These are not the selected DVNs, but they are used to mimic the 2/4 optional DVNs -// set-up as best as possible, as only 3 DVNs support Sepolia <-> HyperEVM Testnet. +// set-up as best as possible, as only 3 DVNs support Sepolia <-> HyperEVM Testnet +// and only 2 DVNs that supports Solana <-> *. export const OPTIONAL_DVNS: Record>> = { LAYERZERO_LABS: { [EndpointId.SEPOLIA_V2_TESTNET]: '0x8eebf8b423b73bfca51a1db4b7354aa0bfca9193', [EndpointId.HYPERLIQUID_V2_TESTNET]: '0x91e698871030d0e1b6c9268c20bb57e2720618dd', + [EndpointId.SOLANA_V2_TESTNET]: '4VDjp6XQaxoZf5RGwiPU9NR1EXSZn2TP4ATMmiSzLfhb', }, MANTLE01: { [EndpointId.SEPOLIA_V2_TESTNET]: '0x6943872cfc48f6b18f8b81d57816733d4545eca3', @@ -16,6 +18,7 @@ export const OPTIONAL_DVNS: Record>> P2P: { [EndpointId.SEPOLIA_V2_TESTNET]: '0x9efba56c8598853e5b40fd9a66b54a6c163742d7', [EndpointId.HYPERLIQUID_V2_TESTNET]: '0x4c90f152707c6eab6cd801e326d25b0591e449a2', + [EndpointId.SOLANA_V2_TESTNET]: '29EKzmCscUg8mf4f5uskwMqvu2SXM8hKF1gWi1cCBoKT', }, } @@ -25,6 +28,7 @@ export const OPTIONAL_DVNS_THRESHOLD = 2 export const CONFIRMATIONS: Partial> = { [EndpointId.SEPOLIA_V2_TESTNET]: 2, [EndpointId.HYPERLIQUID_V2_TESTNET]: 1, + [EndpointId.SOLANA_V2_TESTNET]: 10, } const DEFAULT_ENFORCED_OPTIONS: OAppEnforcedOption[] = [ @@ -35,23 +39,27 @@ const DEFAULT_ENFORCED_OPTIONS: OAppEnforcedOption[] = [ export const ENFORCED_OPTIONS: Partial> = { [EndpointId.SEPOLIA_V2_TESTNET]: DEFAULT_ENFORCED_OPTIONS, [EndpointId.HYPERLIQUID_V2_TESTNET]: DEFAULT_ENFORCED_OPTIONS, + [EndpointId.SOLANA_V2_TESTNET]: [ + { msgType: 1, optionType: ExecutorOptionType.LZ_RECEIVE, gas: 200_000, value: 2_500_000 }, + { msgType: 2, optionType: ExecutorOptionType.LZ_RECEIVE, gas: 200_000, value: 2_500_000 }, + ], } export const OWNERS: Partial> = { [EndpointId.SEPOLIA_V2_TESTNET]: '0xa4B4c951E9Fae331c65700C9BB6A21c236fcF165', [EndpointId.HYPERLIQUID_V2_TESTNET]: '0xa4B4c951E9Fae331c65700C9BB6A21c236fcF165', + [EndpointId.SOLANA_V2_TESTNET]: 'Hy6h65XTsDkR6DBcGjr33WTpCJpM9dyLywYyu81vPKob', // $SQUADS_VAULT_ADDR } as const export const getRequiredDVNs = (_eid: EndpointId): string[] => { return [] as string[] } -export const getOptionalDVNs = (eid: EndpointId): string[] => { - return Object.values(OPTIONAL_DVNS) - .map((dvnMap) => dvnMap[eid]) +export const getOptionalDVNs = (fromEid: EndpointId, toEid: EndpointId): string[] => + Object.values(OPTIONAL_DVNS) + // Gets optional dvn only if it supports both eids + .map((dvnMap) => (dvnMap[toEid] ? dvnMap[fromEid] : null)) .filter(Boolean) as string[] -} - export const getEnforcedOptions = (eid: EndpointId): OAppEnforcedOption[] => { return ENFORCED_OPTIONS[eid] ?? DEFAULT_ENFORCED_OPTIONS } diff --git a/deploy/WXRPMintBurnOFTAdapter.ts b/deploy/WXRPMintBurnOFTAdapter.ts index d33e994..f95dd87 100644 --- a/deploy/WXRPMintBurnOFTAdapter.ts +++ b/deploy/WXRPMintBurnOFTAdapter.ts @@ -31,7 +31,7 @@ export const deployMaba = async (hre: HardhatRuntimeEnvironment) => { // This contract requires >1.5M gas to deploy. Switching to big blocks in HyperEVM. const deployment = await hre.deployments.getOrNull(contractName) - if (isHyperEvm && !deployment) await useBigBlock(wallet!, isHyperEvmTestnet, logLevel) + if (isHyperEvm && !deployment) await useBigBlock(wallet!, isHyperEvmTestnet, logLevel, true) const result = await deploy(contractName, { from: signer.address, @@ -41,7 +41,7 @@ export const deployMaba = async (hre: HardhatRuntimeEnvironment) => { skipIfAlreadyDeployed: false, }) - if (isHyperEvm && !deployment) await useSmallBlock(wallet!, isHyperEvmTestnet, logLevel) + if (isHyperEvm && !deployment) await useSmallBlock(wallet!, isHyperEvmTestnet, logLevel, true) return result } diff --git a/deployments/solana-mainnet/OFT.json b/deployments/solana-mainnet/OFT.json new file mode 100644 index 0000000..605b342 --- /dev/null +++ b/deployments/solana-mainnet/OFT.json @@ -0,0 +1,7 @@ +{ + "programId": "H5WWM7uWHbmZjThKyPbjNGvAagizKA9zzchZWwn79W99", + "mint": "6UpQcMAb5xMzxc7ZfPaVMgx3KqsvKZdT5U718BzD5We2", + "mintAuthority": "E5GXVzJbuN7iPJAfNB23SMXgQLXWGkqRWgvsq4Dg156o", + "escrow": "GCBEb6WBHu6dkd8hZfkucWvoyycBo57qVpn2DuKgSovR", + "oftStore": "FwF2zxV5MaFZfq3pgfcgzJqKWBRyYsiVNVEXqxgshKaH" +} \ No newline at end of file diff --git a/deployments/solana-testnet/OFT.json b/deployments/solana-testnet/OFT.json new file mode 100644 index 0000000..121a45e --- /dev/null +++ b/deployments/solana-testnet/OFT.json @@ -0,0 +1,7 @@ +{ + "programId": "ANBPMYzXfRt5xwwGDzakyjHCeCr2jkLJrN5E8z8vSspD", + "mint": "3KndFCxLqndtfnY7uafEZ6iDg9dTAWXiFGrkhf8TQi2z", + "mintAuthority": "8vWTyXD3rVza9Fvr5oN7QuhASGEyMYi6Dzj7pZGRXCCG", + "escrow": "CrqF8RJUVP9fH5rNsk9xUhSX66HAZ6dGVui7eYJN5Xvp", + "oftStore": "2pkdQ9UWzgLAJ77KZ6avHHWtTVYE7gq1kQV67j8xzDNV" +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 39150c5..68c835d 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -17,6 +17,8 @@ import { EndpointId } from '@layerzerolabs/lz-definitions' import './tasks/transferErc20AdminRole' import './tasks/transferProxyAdminRole' +import './tasks/index' + // Set your preferred authentication method // // If you prefer using a mnemonic, set a MNEMONIC environment variable diff --git a/layerzero.mainnet.config.ts b/layerzero.mainnet.config.ts index 6eeef10..99079d2 100644 --- a/layerzero.mainnet.config.ts +++ b/layerzero.mainnet.config.ts @@ -9,12 +9,14 @@ import { getOwnerAddress, getRequiredDVNs, } from './consts/mainnet' +import { getOftStoreAddress } from './tasks/solana' // Define all contracts. export const CONTRACTS: OmniPointHardhat[] = [ { eid: EndpointId.ETHEREUM_V2_MAINNET, contractName: 'WXRPMintBurnOFTAdapter' }, { eid: EndpointId.HYPERLIQUID_V2_MAINNET, contractName: 'WXRPMintBurnOFTAdapter' }, { eid: EndpointId.OPTIMISM_V2_MAINNET, contractName: 'WXRPMintBurnOFTAdapter' }, + { eid: EndpointId.SOLANA_V2_MAINNET, address: getOftStoreAddress(EndpointId.SOLANA_V2_MAINNET) }, ] // Generate all possible connections. diff --git a/layerzero.mainnet.dewire.config.ts b/layerzero.mainnet.dewire.config.ts new file mode 100644 index 0000000..2ddbb0e --- /dev/null +++ b/layerzero.mainnet.dewire.config.ts @@ -0,0 +1,54 @@ +/** + * Note: + * + * This config is part of the migration to the new spl token solana OFT. + * It can be deleted once de-wiring of the outdated token2022 OFT is successfully completed. + */ +import { EndpointId } from '@layerzerolabs/lz-definitions' +import { OmniPointHardhat } from '@layerzerolabs/toolbox-hardhat' + +const previousSolanaOftStoreAddress = 'GKzT5jtvcysvWoRN7Kgro1nqriS6QhHjyqrtL6UNK89t' +const blockedMsgLibOnSolana = '2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB' + +// Define all contracts. +export const CONTRACTS: OmniPointHardhat[] = [ + { eid: EndpointId.ETHEREUM_V2_MAINNET, contractName: 'WXRPMintBurnOFTAdapter' }, + { eid: EndpointId.HYPERLIQUID_V2_MAINNET, contractName: 'WXRPMintBurnOFTAdapter' }, + { eid: EndpointId.OPTIMISM_V2_MAINNET, contractName: 'WXRPMintBurnOFTAdapter' }, + { eid: EndpointId.SOLANA_V2_MAINNET, address: previousSolanaOftStoreAddress }, +] + +// Generate connections only from Solana to EVM chains +export const generateConnections = async () => { + const connections = [] + const solanaContract = CONTRACTS.find((contract) => contract.eid === EndpointId.SOLANA_V2_MAINNET) + const evmContracts = CONTRACTS.filter((contract) => contract.eid !== EndpointId.SOLANA_V2_MAINNET) + + if (!solanaContract) { + throw new Error('Solana contract not found in CONTRACTS') + } + + // Generate connections from Solana to all EVM chains. + for (const evmContract of evmContracts) { + connections.push({ + from: solanaContract, + to: evmContract, + config: { + sendLibrary: blockedMsgLibOnSolana, + }, + }) + } + + return connections +} + +export default async function () { + const connections = await generateConnections() + + return { + contracts: CONTRACTS.map((contract) => ({ + contract, + })), + connections, + } +} diff --git a/layerzero.testnet.config.ts b/layerzero.testnet.config.ts index 7699002..7e356fc 100644 --- a/layerzero.testnet.config.ts +++ b/layerzero.testnet.config.ts @@ -9,11 +9,13 @@ import { getOwnerAddress, getRequiredDVNs, } from './consts/testnet' +import { getOftStoreAddress } from './tasks/solana' // Define all contracts. export const CONTRACTS: OmniPointHardhat[] = [ { eid: EndpointId.SEPOLIA_V2_TESTNET, contractName: 'WXRPMintBurnOFTAdapter' }, { eid: EndpointId.HYPERLIQUID_V2_TESTNET, contractName: 'WXRPMintBurnOFTAdapter' }, + { eid: EndpointId.SOLANA_V2_TESTNET, address: getOftStoreAddress(EndpointId.SOLANA_V2_TESTNET) }, ] // Generate all possible connections. @@ -42,7 +44,7 @@ export const generateConnections = async () => { ulnConfig: { confirmations: CONFIRMATIONS[from.eid], requiredDVNs: getRequiredDVNs(from.eid), - optionalDVNs: getOptionalDVNs(from.eid), + optionalDVNs: getOptionalDVNs(from.eid, to.eid), optionalDVNThreshold: OPTIONAL_DVNS_THRESHOLD, }, }, @@ -50,7 +52,7 @@ export const generateConnections = async () => { ulnConfig: { confirmations: CONFIRMATIONS[to.eid], requiredDVNs: getRequiredDVNs(from.eid), - optionalDVNs: getOptionalDVNs(from.eid), + optionalDVNs: getOptionalDVNs(from.eid, to.eid), optionalDVNThreshold: OPTIONAL_DVNS_THRESHOLD, }, }, diff --git a/layerzero.testnet.dewire.config.ts b/layerzero.testnet.dewire.config.ts new file mode 100644 index 0000000..57d7593 --- /dev/null +++ b/layerzero.testnet.dewire.config.ts @@ -0,0 +1,53 @@ +/** + * Note: + * + * This config is part of the migration to the new spl token solana OFT. + * It can be deleted once de-wiring of the outdated token2022 OFT is successfully completed. + */ +import { EndpointId } from '@layerzerolabs/lz-definitions' +import { OmniPointHardhat } from '@layerzerolabs/toolbox-hardhat' + +const previousSolanaOftStoreAddress = '44F6EuNhHYmt7JRXvjzw5vJjGogdeVHRw1BQBEQ9NxBT' +const blockedMsgLibOnSolana = '2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB' + +// Define all contracts. +export const CONTRACTS: OmniPointHardhat[] = [ + { eid: EndpointId.SEPOLIA_V2_TESTNET, contractName: 'WXRPMintBurnOFTAdapter' }, + { eid: EndpointId.HYPERLIQUID_V2_TESTNET, contractName: 'WXRPMintBurnOFTAdapter' }, + { eid: EndpointId.SOLANA_V2_TESTNET, address: previousSolanaOftStoreAddress }, +] + +// Generate connections only from Solana devnet to EVM testnet chains +export const generateConnections = async () => { + const connections = [] + const solanaContract = CONTRACTS.find((contract) => contract.eid === EndpointId.SOLANA_V2_TESTNET) + const evmContracts = CONTRACTS.filter((contract) => contract.eid !== EndpointId.SOLANA_V2_TESTNET) + + if (!solanaContract) { + throw new Error('Solana contract not found in CONTRACTS') + } + + // Generate connections from Solana to all EVM chains. + for (const evmContract of evmContracts) { + connections.push({ + from: solanaContract, + to: evmContract, + config: { + sendLibrary: blockedMsgLibOnSolana, + }, + }) + } + + return connections +} + +export default async function () { + const connections = await generateConnections() + + return { + contracts: CONTRACTS.map((contract) => ({ + contract, + })), + connections, + } +} diff --git a/package.json b/package.json index 53588ff..86959d9 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "clean": "rm -rf target artifacts cache out .anchor", "compile": "concurrently -c auto --names forge,hardhat,anchor '$npm_execpath run compile:forge' '$npm_execpath run compile:hardhat' '$npm_execpath run compile:anchor'", - "compile:anchor": "anchor build", + "compile:anchor": "RUSTUP_TOOLCHAIN=nightly-2025-06-30 anchor build", "compile:forge": "forge build", "compile:hardhat": "hardhat compile", "gas:lzCompose": "forge script scripts/GasProfiler.s.sol:GasProfilerScript --via-ir --sig 'run_lzCompose(string,address,uint32,address,uint32,address,address,bytes[],uint256,uint256)'", @@ -16,20 +16,24 @@ "lint:fix": "eslint --fix '**/*.{js,ts,json}' && prettier --write . && solhint 'contracts/**/*.sol' --fix --noPrompt", "lint:js": "eslint '**/*.{js,ts,json}' && prettier --check .", "lint:sol": "solhint 'contracts/**/*.sol'", - "test": "$npm_execpath run test:forge && $npm_execpath run test:hardhat", + "test": "$npm_execpath run test:forge && $npm_execpath run test:hardhat && $npm_execpath run test:anchor", + "test:anchor": "anchor test", "test:forge": "forge test", "test:hardhat": "hardhat test" }, "resolutions": { "ethers": "^5.7.2", - "hardhat-deploy": "^0.12.1" + "hardhat-deploy": "^0.12.1", + "@solana/web3.js": "^1.98.0" }, "dependencies": { - "@layerzerolabs/devtools": "~2.0.1", - "@layerzerolabs/devtools-evm": "^3.0.0", + "@layerzerolabs/devtools": "~2.0.3", + "@layerzerolabs/devtools-evm": "~3.0.0", "@layerzerolabs/devtools-evm-hardhat": "^4.0.0", + "@layerzerolabs/devtools-solana": "~3.0.4", "@layerzerolabs/eslint-config-next": "~2.3.44", - "@layerzerolabs/hyperliquid-composer": "^1.0.3", + "@layerzerolabs/hyperliquid-composer": "^2.0.2", + "@layerzerolabs/io-devtools": "~0.3.0", "@layerzerolabs/lz-core": "^3.0.134", "@layerzerolabs/lz-definitions": "^3.0.134", "@layerzerolabs/lz-evm-messagelib-v2": "^3.0.134", @@ -37,6 +41,7 @@ "@layerzerolabs/lz-evm-protocol-v2": "^3.0.134", "@layerzerolabs/lz-evm-sdk-v2": "^3.0.134", "@layerzerolabs/lz-evm-v1-0.7": "^3.0.134", + "@layerzerolabs/lz-solana-sdk-v2": "^3.0.136", "@layerzerolabs/lz-utilities": "^3.0.134", "@layerzerolabs/lz-v2-utilities": "^3.0.134", "@layerzerolabs/metadata-tools": "^3.0.2", @@ -44,12 +49,27 @@ "@layerzerolabs/oapp-evm-upgradeable": "^0.1.2", "@layerzerolabs/oft-evm": "^3.2.1", "@layerzerolabs/oft-evm-upgradeable": "^3.2.0", + "@layerzerolabs/oft-v2-solana-sdk": "^3.0.136", "@layerzerolabs/prettier-config-next": "^2.3.44", + "@layerzerolabs/protocol-devtools": "^3.0.0", + "@layerzerolabs/protocol-devtools-evm": "~5.0.0", + "@layerzerolabs/protocol-devtools-solana": "^8.0.3", "@layerzerolabs/script-devtools-evm-foundry": "^1.0.0", "@layerzerolabs/solhint-config": "^3.0.134", "@layerzerolabs/test-devtools-evm-foundry": "~7.0.0", "@layerzerolabs/toolbox-foundry": "~0.1.13", "@layerzerolabs/toolbox-hardhat": "~0.6.12", + "@layerzerolabs/ua-devtools": "~5.0.0", + "@layerzerolabs/ua-devtools-evm": "~7.0.0", + "@layerzerolabs/ua-devtools-evm-hardhat": "~9.0.0", + "@layerzerolabs/ua-devtools-solana": "~8.0.2", + "@metaplex-foundation/mpl-token-metadata": "^3.2.1", + "@metaplex-foundation/mpl-toolbox": "^0.9.4", + "@metaplex-foundation/umi": "^0.9.2", + "@metaplex-foundation/umi-bundle-defaults": "^0.9.2", + "@metaplex-foundation/umi-eddsa-web3js": "^0.9.2", + "@metaplex-foundation/umi-public-keys": "^0.8.9", + "@metaplex-foundation/umi-web3js-adapters": "^0.9.2", "@nomicfoundation/hardhat-ethers": "^3.1.0", "@nomicfoundation/hardhat-verify": "^2.1.1", "@nomiclabs/hardhat-ethers": "^2.2.3", @@ -57,7 +77,12 @@ "@openzeppelin/contracts": "^5.4.0", "@openzeppelin/contracts-upgradeable": "^5.4.0", "@rushstack/eslint-patch": "^1.12.0", + "@solana-developers/helpers": "~2.8.1", + "@safe-global/safe-core-sdk-types": "^1.3.0", + "@solana/spl-token": "^0.4.8", + "@solana/web3.js": "~1.95.8", "@types/node": "~18.18.14", + "bs58": "^6.0.0", "concurrently": "~9.1.2", "dotenv": "^16.6.1", "eslint": "^8.57.1", @@ -77,14 +102,17 @@ "engines": { "node": ">=18.16.0" }, + "packageManager": "pnpm@10.17.0", "pnpm": { "overrides": { "ethers": "^5.7.2", - "hardhat-deploy": "^0.12.1" + "hardhat-deploy": "^0.12.1", + "@solana/web3.js": "^1.98.0" } }, "overrides": { "ethers": "^5.7.2", - "hardhat-deploy": "^0.12.1" + "hardhat-deploy": "^0.12.1", + "@solana/web3.js": "^1.98.0" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a3af871..586951c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,26 +7,33 @@ settings: overrides: ethers: ^5.7.2 hardhat-deploy: ^0.12.1 + '@solana/web3.js': ^1.98.0 importers: .: dependencies: '@layerzerolabs/devtools': - specifier: ~2.0.1 - version: 2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + specifier: ~2.0.3 + version: 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) '@layerzerolabs/devtools-evm': - specifier: ^3.0.0 - version: 3.0.0(jo52nddy263jgqv5tm5d6h6l4y) + specifier: ~3.0.0 + version: 3.0.0(12f7ac699b26ccb47df1abaabd2a94a9) '@layerzerolabs/devtools-evm-hardhat': specifier: ^4.0.0 - version: 4.0.0(fc3jrsl3gwkzaktl4lbr75yxly) + version: 4.0.0(fdad73f79aba17df6aeb1b3f7f199cbc) + '@layerzerolabs/devtools-solana': + specifier: ~3.0.4 + version: 3.0.4(d71aeb896849a5a916511ae075bd924f) '@layerzerolabs/eslint-config-next': specifier: ~2.3.44 version: 2.3.44(typescript@5.9.2) '@layerzerolabs/hyperliquid-composer': - specifier: ^1.0.3 - version: 1.0.3(rncsfq7prpd4x2t6py66ws27em) + specifier: ^2.0.2 + version: 2.0.2(22453134066ae3d5b4b3c8090071d359) + '@layerzerolabs/io-devtools': + specifier: ~0.3.0 + version: 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) '@layerzerolabs/lz-core': specifier: ^3.0.134 version: 3.0.134 @@ -38,7 +45,7 @@ importers: version: 3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-oapp-v2': specifier: ^3.0.134 - version: 3.0.134(5qj37ryyxgs2ov7ycombjhwncq) + version: 3.0.134(cdc9a005b3add4311166a146590ee4e0) '@layerzerolabs/lz-evm-protocol-v2': specifier: ^3.0.134 version: 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) @@ -48,6 +55,9 @@ importers: '@layerzerolabs/lz-evm-v1-0.7': specifier: ^3.0.134 version: 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@layerzerolabs/lz-solana-sdk-v2': + specifier: ^3.0.136 + version: 3.0.147(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@layerzerolabs/lz-utilities': specifier: ^3.0.134 version: 3.0.134(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) @@ -56,37 +66,82 @@ importers: version: 3.0.134 '@layerzerolabs/metadata-tools': specifier: ^3.0.2 - version: 3.0.2(@layerzerolabs/devtools-evm-hardhat@4.0.0(fc3jrsl3gwkzaktl4lbr75yxly))(@layerzerolabs/ua-devtools@5.0.1(a6hdbzasdsvgu3ndz3tgfize4u)) + version: 3.0.2(@layerzerolabs/devtools-evm-hardhat@4.0.0(fdad73f79aba17df6aeb1b3f7f199cbc))(@layerzerolabs/ua-devtools@5.0.1(65dc7f5c79b0faa85f9d82ed2d345648)) '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: 0.3.2(6b2bntffp5oh3n4ur2kgzua4ai) + version: 0.3.2(def64342eef69769a3ede3bff20ec454) '@layerzerolabs/oapp-evm-upgradeable': specifier: ^0.1.2 - version: 0.1.2(6b2bntffp5oh3n4ur2kgzua4ai) + version: 0.1.2(def64342eef69769a3ede3bff20ec454) '@layerzerolabs/oft-evm': specifier: ^3.2.1 - version: 3.2.1(wf4w5rqg52yfqco3osd3yat5dy) + version: 3.2.1(d7ffb4ff30b28b73f6b810e31084c2ee) '@layerzerolabs/oft-evm-upgradeable': specifier: ^3.2.0 - version: 3.2.0(wf4w5rqg52yfqco3osd3yat5dy) + version: 3.2.0(d7ffb4ff30b28b73f6b810e31084c2ee) + '@layerzerolabs/oft-v2-solana-sdk': + specifier: ^3.0.136 + version: 3.0.147(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@layerzerolabs/prettier-config-next': specifier: ^2.3.44 version: 2.3.44 + '@layerzerolabs/protocol-devtools': + specifier: ^3.0.0 + version: 3.0.1(@layerzerolabs/devtools@2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/protocol-devtools-evm': + specifier: ~5.0.0 + version: 5.0.1(4e2b97db86906cffbfb9a8b3bc18f622) + '@layerzerolabs/protocol-devtools-solana': + specifier: ^8.0.3 + version: 8.0.4(5e0c91c042d8d231ef7fad536bd998cb) '@layerzerolabs/script-devtools-evm-foundry': specifier: ^1.0.0 - version: 1.0.0(c5z2cllqcedew3jczcswndke2y) + version: 1.0.0(ddc6b0923e79f756c4d09ca081319a6f) '@layerzerolabs/solhint-config': specifier: ^3.0.134 version: 3.0.134(typescript@5.9.2) '@layerzerolabs/test-devtools-evm-foundry': specifier: ~7.0.0 - version: 7.0.0(c5z2cllqcedew3jczcswndke2y) + version: 7.0.0(ddc6b0923e79f756c4d09ca081319a6f) '@layerzerolabs/toolbox-foundry': specifier: ~0.1.13 version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.12 version: 0.6.12(@ethersproject/abstract-provider@5.8.0)(@ethersproject/abstract-signer@5.8.0)(@ethersproject/bignumber@5.8.0)(@ethersproject/constants@5.8.0)(@ethersproject/providers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@nomicfoundation/hardhat-ethers@3.1.0(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.9.2))(typescript@5.9.2)(utf-8-validate@5.0.10)))(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.9.2))(typescript@5.9.2)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.9.2))(typescript@5.9.2)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4)(utf-8-validate@5.0.10) + '@layerzerolabs/ua-devtools': + specifier: ~5.0.0 + version: 5.0.1(65dc7f5c79b0faa85f9d82ed2d345648) + '@layerzerolabs/ua-devtools-evm': + specifier: ~7.0.0 + version: 7.0.0(a8696ec934f2e811b96abb023d3e669c) + '@layerzerolabs/ua-devtools-evm-hardhat': + specifier: ~9.0.0 + version: 9.0.0(0f45e6a71604805add10fd962c424cfb) + '@layerzerolabs/ua-devtools-solana': + specifier: ~8.0.2 + version: 8.0.4(d78575199144cb92633a174d1c330235) + '@metaplex-foundation/mpl-token-metadata': + specifier: ^3.2.1 + version: 3.4.0(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/mpl-toolbox': + specifier: ^0.9.4 + version: 0.9.4(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi': + specifier: ^0.9.2 + version: 0.9.2 + '@metaplex-foundation/umi-bundle-defaults': + specifier: ^0.9.2 + version: 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-eddsa-web3js': + specifier: ^0.9.2 + version: 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-public-keys': + specifier: ^0.8.9 + version: 0.8.9 + '@metaplex-foundation/umi-web3js-adapters': + specifier: ^0.9.2 + version: 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-ethers': specifier: ^3.1.0 version: 3.1.0(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.9.2))(typescript@5.9.2)(utf-8-validate@5.0.10)) @@ -108,9 +163,24 @@ importers: '@rushstack/eslint-patch': specifier: ^1.12.0 version: 1.12.0 + '@safe-global/safe-core-sdk-types': + specifier: ^1.3.0 + version: 1.10.1 + '@solana-developers/helpers': + specifier: ~2.8.1 + version: 2.8.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/spl-token': + specifier: ^0.4.8 + version: 0.4.14(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/web3.js': + specifier: ^1.98.0 + version: 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@types/node': specifier: ~18.18.14 version: 18.18.14 + bs58: + specifier: ^6.0.0 + version: 6.0.0 concurrently: specifier: ~9.1.2 version: 9.1.2 @@ -208,6 +278,30 @@ packages: resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} + '@coral-xyz/anchor-errors@0.30.1': + resolution: {integrity: sha512-9Mkradf5yS5xiLWrl9WrpjqOrAV+/W2RQHDlbnAZBivoGpOs1ECjoDCkVk4aRG8ZdiFiB8zQEVlxf+8fKkmSfQ==} + engines: {node: '>=10'} + + '@coral-xyz/anchor@0.29.0': + resolution: {integrity: sha512-eny6QNG0WOwqV0zQ7cs/b1tIuzZGmP7U7EcH+ogt4Gdbl8HDmIYVMh/9aTmYZPaFWjtUaI8qSn73uYEXWfATdA==} + engines: {node: '>=11'} + + '@coral-xyz/anchor@0.30.1': + resolution: {integrity: sha512-gDXFoF5oHgpriXAaLpxyWBHdCs8Awgf/gLHIo6crv7Aqm937CNdY+x+6hoj7QR5vaJV7MxWSQ0NGFzL3kPbWEQ==} + engines: {node: '>=11'} + + '@coral-xyz/borsh@0.29.0': + resolution: {integrity: sha512-s7VFVa3a0oqpkuRloWVPdCK7hMbAMY270geZOGfCnaqexrP5dTIpbEHL33req6IYPPJ0hYa71cdvJ1h6V55/oQ==} + engines: {node: '>=10'} + peerDependencies: + '@solana/web3.js': ^1.98.0 + + '@coral-xyz/borsh@0.30.1': + resolution: {integrity: sha512-aaxswpPrCFKl8vZTbxLssA2RvwX2zmKLlRCIktJOwW+VpVwYtXRtlWiIP+c2pPRKneiTiWCN2GEMSH9j1zTlWQ==} + engines: {node: '>=10'} + peerDependencies: + '@solana/web3.js': ^1.98.0 + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -563,6 +657,13 @@ packages: '@types/node': optional: true + '@iota/bcs@1.3.0': + resolution: {integrity: sha512-R99rbggmRuRIhfPpmmceo87gRrVrfM1oZRhGhK5dmbOk5wooo3rMYzN/a0KzQ9Ieig/FisuV5uDEkFheQXr7WA==} + + '@iota/iota-sdk@1.7.1': + resolution: {integrity: sha512-ZUGPGldQPI2j9twUkylRuE/JkP9U4T7eOFdid4G8UufCs5VdepTISv76IoTSgn/K27xQhVjULsqx4rhlUWSXeA==} + engines: {node: '>=20'} + '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} @@ -618,8 +719,19 @@ packages: fp-ts: ^2.16.2 zod: ^3.22.4 - '@layerzerolabs/devtools@2.0.1': - resolution: {integrity: sha512-YwXVZ8fdfyJ3oc2nEVbaAs+vLkc0CuCwcWuTuhMy0GkySoW5kAZyJ3rANUNvOLdhq09VTev2hvlo9q5WeMdy9g==} + '@layerzerolabs/devtools-solana@3.0.4': + resolution: {integrity: sha512-RWZsWgG8u0gf6zon/rm5BE2WreSpHL/Li9EkJpxPIrgEs3bDQXB088NTMUBvhlmWGs4M1gCMiA49tUD2tR9V8Q==} + peerDependencies: + '@layerzerolabs/devtools': ~2.0.3 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@solana/web3.js': ^1.98.0 + bn.js: ^5.2.0 + fp-ts: ^2.16.2 + zod: ^3.22.4 + + '@layerzerolabs/devtools@2.0.3': + resolution: {integrity: sha512-kpMQerGyDDQw9B9HdN/yqToZR1oDtFNHmfDQu069hiz8699cu/hUqevHmDPOdEKX+3HsRY3Gn/BZ5JW8WQbFmA==} peerDependencies: '@ethersproject/bytes': ~5.7.0 '@layerzerolabs/io-devtools': ~0.3.1 @@ -636,14 +748,14 @@ packages: resolution: {integrity: sha512-tI+mKMx51qCrj+G42mrVR+5jAiRaiLCpnXiogjW7E3krbNbJenI1eYYX7U62ssXWXwTZfYSJ1Bw/zLAbs59sqw==} hasBin: true - '@layerzerolabs/hyperliquid-composer@1.0.3': - resolution: {integrity: sha512-5ZNyXNps1VACOhPXb4/9oXPuP+NAhfhsJVkWPYi1sugkXqFT9HLcz3DIAudTUPZ/Dc31cUtMq5KmhI5plx8Epg==} + '@layerzerolabs/hyperliquid-composer@2.0.2': + resolution: {integrity: sha512-VjogOuF3VGkQ7PuWiSHi4BdXHOESoGk2tuJh2z8zJnagGclOEbwpyGynJqgrh4N+9t53+dZXHye3mKF2JlvVHA==} hasBin: true peerDependencies: '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.12 '@layerzerolabs/lz-evm-protocol-v2': ^3.0.12 '@layerzerolabs/lz-evm-v1-0.7': ^3.0.12 - '@layerzerolabs/oapp-evm': ^0.3.2 + '@layerzerolabs/oapp-evm': ^0.4.0 '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 @@ -671,9 +783,18 @@ packages: '@layerzerolabs/lz-core@3.0.134': resolution: {integrity: sha512-vLobnvu9YOeNt982lpcj29Zmd1YaAKbkQDX9x9lqtPBDNSX604DLFhrOkscU1NIr8QXqgINeIzakCF8NOR2STA==} + '@layerzerolabs/lz-core@3.0.147': + resolution: {integrity: sha512-Of4mVyFwNbNsiGXXk/jofiV3kErxkbw8pYqcnbT4VfXQqRZb5e6rJJ3VDlfwl9Oue2kXMfdBk8dvOG6dVgfWWg==} + + '@layerzerolabs/lz-corekit-solana@3.0.147': + resolution: {integrity: sha512-yp5H4OwT/QX5Ik42JXlEC7XxTmwFE6mvnu7S0Tbnh7PfDGZTT8Gs6W0QrIYcKEsFC688wgt5ZDXYagpSwvPIjw==} + '@layerzerolabs/lz-definitions@3.0.134': resolution: {integrity: sha512-gSW7wQF7NciUFQJxfxj2KkcVGCD7XGx+vdvV2vK1d1dQebFepwug3x6MCEdAr2rkSc+Hq4oec2X65UnbLoZtlg==} + '@layerzerolabs/lz-definitions@3.0.147': + resolution: {integrity: sha512-mRpnoWi7eic50ZPCK9rmOPiQEuuNk8exZotBQKlfGwlgjzfhpQiF2H+QIgeESeMSqc0aC9P3azPWQgWJVeBwdQ==} + '@layerzerolabs/lz-evm-messagelib-v2@3.0.134': resolution: {integrity: sha512-sN0Tu3CMx6eKlsL8wYF3aL+gQGv61OnSmNtBFP653URGQDhWQhGWOKbNWXmNv57hSHTFvlizL2vrmZa66f4xoQ==} peerDependencies: @@ -723,12 +844,27 @@ packages: '@openzeppelin/contracts-upgradeable': 3.4.2-solc-0.7 || ^3.4.2 || ^4.0.0 || ^5.0.0 hardhat-deploy: ^0.12.1 + '@layerzerolabs/lz-foundation@3.0.147': + resolution: {integrity: sha512-TYatI03s7IJ5HlckfqEkTICHXzr7/wbl55KoNtqxyAfJvC4DwAfFQne5KAnoLQQTfR+3XHmfLJ5Pj+iGd9GbSg==} + + '@layerzerolabs/lz-serdes@3.0.147': + resolution: {integrity: sha512-0eQvK305gtaBslD3HFiQW2EEInajy7xzN/jyVt40VCSSreLLLJkak+SQzMhxiGwBLdFH6+RK+2RGLjx+tzll2Q==} + + '@layerzerolabs/lz-solana-sdk-v2@3.0.147': + resolution: {integrity: sha512-YecZc7XsXrHbMWC3Sg6KmDurlr5hvr25zTemGUxaIlhVfU89DMgRkFjEGQe0APQv9vkNqVGP4hRxmOXwKrF1bA==} + '@layerzerolabs/lz-utilities@3.0.134': resolution: {integrity: sha512-8yWvbvHYZld2CNb9tG/cGTwUFkVwCqQyHDSJP9Pd4n/fHWBhIwf9OHgJRWX4WogibYLI+1SLsy5mvxod8MZqUA==} + '@layerzerolabs/lz-utilities@3.0.147': + resolution: {integrity: sha512-rBfuOZB6Ef02qYOF+Rpv0txkeZaW/0jXAsBKiuY9FMVWVw6FZUgsBy1E5It9OTOwMfqlj99tq+OaywKRu8Oacw==} + '@layerzerolabs/lz-v2-utilities@3.0.134': resolution: {integrity: sha512-bF/WIHh2T7GOmaLNidu6dO2hRX7Y8hdagBA5p+h49ljQP76IQCZYUqlt1C1oR/Dj4G9MOJvVO5JEUkeUf8tPyw==} + '@layerzerolabs/lz-v2-utilities@3.0.147': + resolution: {integrity: sha512-ipou/sIABlSL5ulIOesSsFJEebcsZxONnYwGlqtcrTaZQGeYK5pmwPNfBIkQ6ta4980EEBYZ+GoGj5ovQYnGtA==} + '@layerzerolabs/metadata-tools@3.0.2': resolution: {integrity: sha512-C+LcNFMDXcanDlCOaXm7UGeOObN947BbOCP5mfGkdnKGso1I3+Tak/1QpCRMWvcz1zfa4jikF5KQsfY5bJQD4Q==} peerDependencies: @@ -773,6 +909,9 @@ packages: '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + '@layerzerolabs/oft-v2-solana-sdk@3.0.147': + resolution: {integrity: sha512-2ahvBXOSzHp1VIC+8QwdHLhXxBSGtXptpnKnmXsl4VPDnSyxgsmteU8sSbLQeSfVnF/aNnqMKaW0SMhlIG5Reg==} + '@layerzerolabs/prettier-config-next@2.3.44': resolution: {integrity: sha512-mIsxKLaelXHXXXvMEAE6Jc8IVydra0PesHquHYwvxFKwDhMhzfrnoRLLzbgCX/Zi1q0GGET/oMAKJTs6OWFPxQ==} @@ -792,6 +931,21 @@ packages: '@layerzerolabs/protocol-devtools': ~3.0.1 zod: ^3.22.4 + '@layerzerolabs/protocol-devtools-solana@8.0.4': + resolution: {integrity: sha512-FCfZ9NDXaqVvTyY+mhFvq8HR1uynMUgfC0ldZgdV+PODVUInKbsaRsu814JSW2boN/NwnscLUGmjGIg4dzqEjQ==} + peerDependencies: + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/devtools-solana': ~3.0.2 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@layerzerolabs/lz-solana-sdk-v2': ^3.0.0 + '@layerzerolabs/lz-v2-utilities': ^3.0.75 + '@layerzerolabs/protocol-devtools': ^3.0.1 + '@layerzerolabs/ua-devtools': ^5.0.1 + '@solana/web3.js': ^1.98.0 + fp-ts: ^2.16.2 + zod: ^3.22.4 + '@layerzerolabs/protocol-devtools@3.0.1': resolution: {integrity: sha512-5LndY2OD0PdodEv5IuhSP3RzbThxmE2B8twcrMGuPixrD1PjiIYqLvm2wznUMV/2NLiQrDdY1bOpd+5q9weibw==} peerDependencies: @@ -842,6 +996,9 @@ packages: hardhat: ^2.22.10 hardhat-deploy: ^0.12.1 + '@layerzerolabs/tron-utilities@3.0.147': + resolution: {integrity: sha512-lZoSA9/SMaoY2yFVPeSZwYXgSBTSsZ+M3XP+Ifve3CpcFvs/JrZt7eYJSRAvblT1rlNyVvr0tT7j1BJRJWWA6w==} + '@layerzerolabs/ua-devtools-evm-hardhat@9.0.0': resolution: {integrity: sha512-Wm/88JToOgFAJO0nKnpGMxQDD8mN37VFhz/ejE0DWbXsukp7IdX4ld4gQKM0MU7Yiajardhlvpa3Mwg+xHi8KQ==} peerDependencies: @@ -877,6 +1034,23 @@ packages: '@layerzerolabs/ua-devtools': ~5.0.0 zod: ^3.22.4 + '@layerzerolabs/ua-devtools-solana@8.0.4': + resolution: {integrity: sha512-TXW7VYEoRqxqS4A39CBsf3h8z36xZoMMTvDU3Uw6TQA+MsYxwtLtR4wQgfRV845EMLozvnEO8xaGFlHesm40aA==} + peerDependencies: + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/devtools-solana': ~3.0.2 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@layerzerolabs/lz-solana-sdk-v2': ^3.0.59 + '@layerzerolabs/lz-v2-utilities': ^3.0.75 + '@layerzerolabs/oft-v2-solana-sdk': ^3.0.59 + '@layerzerolabs/protocol-devtools': ^3.0.0 + '@layerzerolabs/protocol-devtools-solana': ~8.0.4 + '@layerzerolabs/ua-devtools': ^5.0.0 + '@solana/web3.js': ^1.98.0 + fp-ts: ^2.16.2 + zod: ^3.22.4 + '@layerzerolabs/ua-devtools@5.0.1': resolution: {integrity: sha512-acoxyJAYqF+di2/akGuWLa5Gdt7Z/8LLZD0LqOui34yjPuHYH88L4xxmKxqrs4Ga/uQnRKcF6Cauy9pjlQCj1A==} peerDependencies: @@ -908,6 +1082,103 @@ packages: '@mdn/browser-compat-data@5.7.6': resolution: {integrity: sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==} + '@metaplex-foundation/beet-solana@0.4.1': + resolution: {integrity: sha512-/6o32FNUtwK8tjhotrvU/vorP7umBuRFvBZrC6XCk51aKidBHe5LPVPA5AjGPbV3oftMfRuXPNd9yAGeEqeCDQ==} + + '@metaplex-foundation/beet@0.7.2': + resolution: {integrity: sha512-K+g3WhyFxKPc0xIvcIjNyV1eaTVJTiuaHZpig7Xx0MuYRMoJLLvhLTnUXhFdR5Tu2l2QSyKwfyXDgZlzhULqFg==} + + '@metaplex-foundation/mpl-token-metadata@3.4.0': + resolution: {integrity: sha512-AxBAYCK73JWxY3g9//z/C9krkR0t1orXZDknUPS4+GjwGH2vgPfsk04yfZ31Htka2AdS9YE/3wH7sMUBHKn9Rg==} + peerDependencies: + '@metaplex-foundation/umi': '>= 0.8.2 <= 1' + + '@metaplex-foundation/mpl-toolbox@0.10.0': + resolution: {integrity: sha512-84KD1L5cFyw5xnntHwL4uPwfcrkKSiwuDeypiVr92qCUFuF3ZENa2zlFVPu+pQcjTlod2LmEX3MhBmNjRMpdKg==} + peerDependencies: + '@metaplex-foundation/umi': '>= 0.8.2 <= 1' + + '@metaplex-foundation/mpl-toolbox@0.9.4': + resolution: {integrity: sha512-fd6JxfoLbj/MM8FG2x91KYVy1U6AjBQw4qjt7+Da3trzQaWnSaYHDcYRG/53xqfvZ9qofY1T2t53GXPlD87lnQ==} + peerDependencies: + '@metaplex-foundation/umi': '>= 0.8.2 < 1' + + '@metaplex-foundation/umi-bundle-defaults@0.9.2': + resolution: {integrity: sha512-kV3tfvgvRjVP1p9OFOtH+ibOtN9omVJSwKr0We4/9r45e5LTj+32su0V/rixZUkG1EZzzOYBsxhtIE0kIw/Hrw==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + '@solana/web3.js': ^1.98.0 + + '@metaplex-foundation/umi-downloader-http@0.9.2': + resolution: {integrity: sha512-tzPT9hBwenzTzAQg07rmsrqZfgguAXELbcJrsYMoASp5VqWFXYIP00g94KET6XLjWUXH4P1J2zoa6hGennPXHA==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + + '@metaplex-foundation/umi-eddsa-web3js@0.9.2': + resolution: {integrity: sha512-hhPCxXbYIp4BC4z9gK78sXpWLkNSrfv4ndhF5ruAkdIp7GcRVYKj0QnOUO6lGYGiIkNlw20yoTwOe1CT//OfTQ==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + '@solana/web3.js': ^1.98.0 + + '@metaplex-foundation/umi-http-fetch@0.9.2': + resolution: {integrity: sha512-YCZuBu24T9ZzEDe4+w12LEZm/fO9pkyViZufGgASC5NX93814Lvf6Ssjn/hZzjfA7CvZbvLFbmujc6CV3Q/m9Q==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + + '@metaplex-foundation/umi-options@0.8.9': + resolution: {integrity: sha512-jSQ61sZMPSAk/TXn8v8fPqtz3x8d0/blVZXLLbpVbo2/T5XobiI6/MfmlUosAjAUaQl6bHRF8aIIqZEFkJiy4A==} + + '@metaplex-foundation/umi-program-repository@0.9.2': + resolution: {integrity: sha512-g3+FPqXEmYsBa8eETtUE2gb2Oe3mqac0z3/Ur1TvAg5TtIy3mzRzOy/nza+sgzejnfcxcVg835rmpBaxpBnjDA==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + + '@metaplex-foundation/umi-public-keys@0.8.9': + resolution: {integrity: sha512-CxMzN7dgVGOq9OcNCJe2casKUpJ3RmTVoOvDFyeoTQuK+vkZ1YSSahbqC1iGuHEtKTLSjtWjKvUU6O7zWFTw3Q==} + + '@metaplex-foundation/umi-rpc-chunk-get-accounts@0.9.2': + resolution: {integrity: sha512-YRwVf6xH0jPBAUgMhEPi+UbjioAeqTXmjsN2TnmQCPAmHbrHrMRj0rlWYwFLWAgkmoxazYrXP9lqOFRrfOGAEA==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + + '@metaplex-foundation/umi-rpc-web3js@0.9.2': + resolution: {integrity: sha512-MqcsBz8B4wGl6jxsf2Jo/rAEpYReU9VCSR15QSjhvADHMmdFxCIZCCAgE+gDE2Vuanfl437VhOcP3g5Uw8C16Q==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + '@solana/web3.js': ^1.98.0 + + '@metaplex-foundation/umi-serializer-data-view@0.9.2': + resolution: {integrity: sha512-5vGptadJxUxvUcyrwFZxXlEc6Q7AYySBesizCtrBFUY8w8PnF2vzmS45CP1MLySEATNH6T9mD4Rs0tLb87iQyA==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + + '@metaplex-foundation/umi-serializers-core@0.8.9': + resolution: {integrity: sha512-WT82tkiYJ0Qmscp7uTj1Hz6aWQPETwaKLAENAUN5DeWghkuBKtuxyBKVvEOuoXerJSdhiAk0e8DWA4cxcTTQ/w==} + + '@metaplex-foundation/umi-serializers-encodings@0.8.9': + resolution: {integrity: sha512-N3VWLDTJ0bzzMKcJDL08U3FaqRmwlN79FyE4BHj6bbAaJ9LEHjDQ9RJijZyWqTm0jE7I750fU7Ow5EZL38Xi6Q==} + + '@metaplex-foundation/umi-serializers-numbers@0.8.9': + resolution: {integrity: sha512-NtBf1fnVNQJHFQjLFzRu2i9GGnigb9hOm/Gfrk628d0q0tRJB7BOM3bs5C61VAs7kJs4yd+pDNVAERJkknQ7Lg==} + + '@metaplex-foundation/umi-serializers@0.9.0': + resolution: {integrity: sha512-hAOW9Djl4w4ioKeR4erDZl5IG4iJdP0xA19ZomdaCbMhYAAmG/FEs5khh0uT2mq53/MnzWcXSUPoO8WBN4Q+Vg==} + + '@metaplex-foundation/umi-transaction-factory-web3js@0.9.2': + resolution: {integrity: sha512-fR1Kf21uylMFd1Smkltmj4jTNxhqSWf416owsJ+T+cvJi2VCOcOwq/3UFzOrpz78fA0RhsajKYKj0HYsRnQI1g==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + '@solana/web3.js': ^1.98.0 + + '@metaplex-foundation/umi-web3js-adapters@0.9.2': + resolution: {integrity: sha512-RQqUTtHYY9fmEMnq7s3Hiv/81flGaoI0ZVVoafnFVaQLnxU6QBKxtboRZHk43XtD9CiFh5f9izrMJX7iK7KlOA==} + peerDependencies: + '@metaplex-foundation/umi': ^0.9.2 + '@solana/web3.js': ^1.98.0 + + '@metaplex-foundation/umi@0.9.2': + resolution: {integrity: sha512-9i4Acm4pruQfJcpRrc2EauPBwkfDN0I9QTvJyZocIlKgoZwD6A6wH0PViH1AjOVG5CQCd1YI3tJd5XjYE1ElBw==} + '@mysten/bcs@1.8.0': resolution: {integrity: sha512-bDoLN1nN+XPONsvpNyNyqYHndM3PKWS419GLeRnbLoWyNm4bnyD1X4luEpJLLDq400hBuXiCan4RWjofvyTUIQ==} @@ -932,6 +1203,9 @@ packages: resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} engines: {node: ^14.21.3 || >=16} + '@noble/ed25519@1.7.5': + resolution: {integrity: sha512-xuS0nwRMQBvSxDa7UxMb61xTiH3MxTgUfhyPUALVIe0FlOAz4sjELwyDRyUvqeEYfRSG9qNjFIycqLZppg4RSA==} + '@noble/hashes@1.2.0': resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} @@ -1132,6 +1406,10 @@ packages: '@safe-global/protocol-kit@1.3.0': resolution: {integrity: sha512-zBhwHpaUggywmnR1Xm5RV22DpyjmVWYP3pnOl4rcf9LAc1k7IVmw6WIt2YVhHRaWGxVYMd4RitJX8Dx2+8eLZQ==} + '@safe-global/safe-core-sdk-types@1.10.1': + resolution: {integrity: sha512-BKvuYTLOlY16Rq6qCXglmnL6KxInDuXMFqZMaCzwDKiEh+uoHu3xCumG5tVtWOkCgBF4XEZXMqwZUiLcon7IsA==} + deprecated: 'WARNING: This project has been renamed to @safe-global/types-kit. Please, migrate from @safe-global/safe-core-sdk-types@5.1.0 to @safe-global/types-kit@1.0.0.' + '@safe-global/safe-core-sdk-types@2.3.0': resolution: {integrity: sha512-dU0KkDV1KJNf11ajbUjWiSi4ygdyWfhk1M50lTJWUdCn1/2Bsb/hICM8LoEk6DCoFumxaoCet02SmYakXsW2CA==} deprecated: 'WARNING: This project has been renamed to @safe-global/types-kit. Please, migrate from @safe-global/safe-core-sdk-types@5.1.0 to @safe-global/types-kit@1.0.0.' @@ -1202,12 +1480,102 @@ packages: resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} engines: {node: '>=14.16'} + '@solana-developers/helpers@2.8.0': + resolution: {integrity: sha512-K3SjX3f0NbCGBcbN40vIMfTicYFNj8bkImcF32JxiR1YmsXu2scb3449bG1CRk/5JBSA0pP4p+lhGU1nc2mEVg==} + + '@solana-developers/helpers@2.8.1': + resolution: {integrity: sha512-xvoOj+ewL18+h6fMrXp1vTss0WBLnhQHnBb6mMPfEQE32w0THlxm8OPXNUY8g4tREX7ugU5cDEP7c2teye1Z7A==} + + '@solana/buffer-layout-utils@0.2.0': + resolution: {integrity: sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==} + engines: {node: '>= 10'} + '@solana/buffer-layout@4.0.1': resolution: {integrity: sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==} engines: {node: '>=5.10'} - '@solana/web3.js@1.95.8': - resolution: {integrity: sha512-sBHzNh7dHMrmNS5xPD1d0Xa2QffW/RXaxu/OysRXBfwTp+LYqGGmMtCYYwrHPrN5rjAmJCsQRNAwv4FM0t3B6g==} + '@solana/codecs-core@2.0.0-rc.1': + resolution: {integrity: sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ==} + peerDependencies: + typescript: '>=5' + + '@solana/codecs-core@2.3.0': + resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-data-structures@2.0.0-rc.1': + resolution: {integrity: sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog==} + peerDependencies: + typescript: '>=5' + + '@solana/codecs-numbers@2.0.0-rc.1': + resolution: {integrity: sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ==} + peerDependencies: + typescript: '>=5' + + '@solana/codecs-numbers@2.3.0': + resolution: {integrity: sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/codecs-strings@2.0.0-rc.1': + resolution: {integrity: sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g==} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + typescript: '>=5' + + '@solana/codecs@2.0.0-rc.1': + resolution: {integrity: sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ==} + peerDependencies: + typescript: '>=5' + + '@solana/errors@2.0.0-rc.1': + resolution: {integrity: sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==} + hasBin: true + peerDependencies: + typescript: '>=5' + + '@solana/errors@2.3.0': + resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==} + engines: {node: '>=20.18.0'} + hasBin: true + peerDependencies: + typescript: '>=5.3.3' + + '@solana/options@2.0.0-rc.1': + resolution: {integrity: sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA==} + peerDependencies: + typescript: '>=5' + + '@solana/spl-token-group@0.0.7': + resolution: {integrity: sha512-V1N/iX7Cr7H0uazWUT2uk27TMqlqedpXHRqqAbVO2gvmJyT0E0ummMEAVQeXZ05ZhQ/xF39DLSdBp90XebWEug==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.98.0 + + '@solana/spl-token-metadata@0.1.6': + resolution: {integrity: sha512-7sMt1rsm/zQOQcUWllQX9mD2O6KhSAtY1hFR2hfFwgqfFWzSY9E9GDvFVNYUI1F0iQKcm6HmePU9QbKRXTEBiA==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.98.0 + + '@solana/spl-token@0.3.11': + resolution: {integrity: sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.98.0 + + '@solana/spl-token@0.4.14': + resolution: {integrity: sha512-u09zr96UBpX4U685MnvQsNzlvw9TiY005hk1vJmJr7gMJldoPG1eYU5/wNEyOA5lkMLiR/gOi9SFD4MefOYEsA==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.98.0 + + '@solana/web3.js@1.98.4': + resolution: {integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==} '@solidity-parser/parser@0.18.0': resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} @@ -1215,6 +1583,9 @@ packages: '@solidity-parser/parser@0.20.2': resolution: {integrity: sha512-rbu0bzwNvMcwAjH86hiEAcOeRI2EeK8zCkHDrFykh/Al8mvJeFmjy3UrE7GYQjNwOgbGUUtCn5/k8CB8zIu7QA==} + '@suchipi/femver@1.0.0': + resolution: {integrity: sha512-bprE8+K5V+DPX7q2e2K57ImqNBdfGHDIWaGI5xHxZoxbKOuQZn4wzPiUxOAHnsUr3w3xHrWXwN7gnG/iIuEMIg==} + '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} @@ -1243,6 +1614,10 @@ packages: '@ton/core': '>=0.59.0' '@ton/crypto': '>=3.2.0' + '@tronweb3/google-protobuf@3.21.4': + resolution: {integrity: sha512-joxgV4esCdyZ921AprMIG1T7HjkypquhbJ5qJti/priCBJhRE1z9GOxIEMvayxSVSRbMGIoJNE0Knrg3vpwM1w==} + deprecated: This package is deprecated. Please use the official package google-protobuf instead. + '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -1582,6 +1957,9 @@ packages: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} + ansicolors@0.3.2: + resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} + antlr4@4.13.2: resolution: {integrity: sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==} engines: {node: '>=16'} @@ -1639,6 +2017,9 @@ packages: resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} engines: {node: '>=0.8'} + assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} @@ -1812,6 +2193,10 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer-layout@1.2.2: + resolution: {integrity: sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==} + engines: {node: '>=4.5'} + buffer-to-arraybuffer@0.0.5: resolution: {integrity: sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ==} @@ -1898,6 +2283,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chardet@2.1.0: resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==} @@ -2005,6 +2394,14 @@ packages: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@14.0.2: + resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} + engines: {node: '>=20'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -2082,6 +2479,9 @@ packages: create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-fetch@3.2.0: + resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + cross-fetch@4.1.0: resolution: {integrity: sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==} @@ -2089,6 +2489,10 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + crypto-hash@1.3.0: + resolution: {integrity: sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg==} + engines: {node: '>=8'} + d@1.0.2: resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} engines: {node: '>=0.12'} @@ -2226,6 +2630,9 @@ packages: dom-walk@0.1.2: resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + dotenv@16.6.1: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} @@ -2541,9 +2948,15 @@ packages: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} + eventemitter3@3.1.2: + resolution: {integrity: sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==} + eventemitter3@4.0.4: resolution: {integrity: sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==} + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} @@ -2601,6 +3014,9 @@ packages: fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fastestsmallesttextencoderdecoder@1.0.22: + resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} + fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -3006,6 +3422,9 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + injectpromise@1.0.0: + resolution: {integrity: sha512-qNq5wy4qX4uWHcVFOEU+RqZkoVG65FhvGkyDWbuBxILMjK6A1LFf5A1mgXZkD4nRx5FCorD81X/XvPKp/zVfPA==} + ink-gradient@2.0.0: resolution: {integrity: sha512-d2BK/EzzBRoDL54NWkS3JGE4J8xtzwRVWxDAIkQ/eQ60XIzrFMtT5JlUqgV05Qlt32Jvk50qW51YqxGJggTuqA==} engines: {node: '>=10'} @@ -3133,6 +3552,10 @@ packages: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} + is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + is-negative-zero@2.0.3: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} @@ -3361,6 +3784,9 @@ packages: loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + lowercase-keys@2.0.0: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} @@ -3580,6 +4006,9 @@ packages: next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + node-addon-api@2.0.2: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} @@ -3637,6 +4066,10 @@ packages: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -3744,6 +4177,9 @@ packages: resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} engines: {node: '>=14.16'} + pako@2.1.0: + resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -3924,6 +4360,10 @@ packages: resolution: {integrity: sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==} engines: {node: '>=0.10.0'} + querystring-es3@0.2.1: + resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} + engines: {node: '>=0.4.x'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -4224,6 +4664,9 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} + snake-case@3.0.4: + resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} + solc@0.8.26: resolution: {integrity: sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==} engines: {node: '>=10.0.0'} @@ -4346,6 +4789,9 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + superstruct@0.15.5: + resolution: {integrity: sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==} + superstruct@2.0.2: resolution: {integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==} engines: {node: '>=14.0.0'} @@ -4440,6 +4886,9 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + toml@3.0.0: + resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + tough-cookie@2.5.0: resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} engines: {node: '>=0.8'} @@ -4455,6 +4904,9 @@ packages: resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} engines: {node: '>= 14.0.0'} + tronweb@5.3.4: + resolution: {integrity: sha512-79HEnwSAqyCKrT7QB8dkxad0RqYx3dSulEg4dfBQQVwzhRr+AqdE1yz+nfTUpftu54RejqaHjqz40ZzWNy077w==} + ts-api-utils@1.4.3: resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} engines: {node: '>=16'} @@ -4646,6 +5098,10 @@ packages: typescript: optional: true + validator@13.15.23: + resolution: {integrity: sha512-4yoz1kEWqUjzi5zsPbAS/903QXSYp0UOtHsPpp7p9rHAw/W+dkInskAE386Fat3oKRROwO98d9ZB0G4cObgUyw==} + engines: {node: '>= 0.10'} + varint@5.0.2: resolution: {integrity: sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==} @@ -4983,6 +5439,65 @@ snapshots: '@colors/colors@1.6.0': {} + '@coral-xyz/anchor-errors@0.30.1': {} + + '@coral-xyz/anchor@0.29.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@coral-xyz/borsh': 0.29.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@noble/hashes': 1.8.0 + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bn.js: 5.2.2 + bs58: 4.0.1 + buffer-layout: 1.2.2 + camelcase: 6.3.0 + cross-fetch: 3.2.0 + crypto-hash: 1.3.0 + eventemitter3: 4.0.7 + pako: 2.1.0 + snake-case: 3.0.4 + superstruct: 0.15.5 + toml: 3.0.0 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + + '@coral-xyz/anchor@0.30.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@coral-xyz/anchor-errors': 0.30.1 + '@coral-xyz/borsh': 0.30.1(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@noble/hashes': 1.8.0 + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bn.js: 5.2.2 + bs58: 4.0.1 + buffer-layout: 1.2.2 + camelcase: 6.3.0 + cross-fetch: 3.2.0 + crypto-hash: 1.3.0 + eventemitter3: 4.0.7 + pako: 2.1.0 + snake-case: 3.0.4 + superstruct: 0.15.5 + toml: 3.0.0 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + + '@coral-xyz/borsh@0.29.0(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))': + dependencies: + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bn.js: 5.2.2 + buffer-layout: 1.2.2 + + '@coral-xyz/borsh@0.30.1(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))': + dependencies: + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bn.js: 5.2.2 + buffer-layout: 1.2.2 + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -5563,6 +6078,30 @@ snapshots: optionalDependencies: '@types/node': 18.18.14 + '@iota/bcs@1.3.0': + dependencies: + bs58: 6.0.0 + + '@iota/iota-sdk@1.7.1(typescript@5.9.2)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.11.0) + '@iota/bcs': 1.3.0 + '@noble/curves': 1.9.7 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + '@suchipi/femver': 1.0.0 + bech32: 2.0.0 + bignumber.js: 9.3.1 + gql.tada: 1.8.13(graphql@16.11.0)(typescript@5.9.2) + graphql: 16.11.0 + tweetnacl: 1.0.3 + valibot: 0.36.0 + transitivePeerDependencies: + - '@gql.tada/svelte-support' + - '@gql.tada/vue-support' + - typescript + '@isaacs/balanced-match@4.0.1': {} '@isaacs/brace-expansion@5.0.0': @@ -5587,14 +6126,14 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@layerzerolabs/devtools-evm-hardhat@4.0.0(fc3jrsl3gwkzaktl4lbr75yxly)': + '@layerzerolabs/devtools-evm-hardhat@4.0.0(fdad73f79aba17df6aeb1b3f7f199cbc)': dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/abstract-signer': 5.8.0 '@ethersproject/contracts': 5.8.0 '@ethersproject/providers': 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) - '@layerzerolabs/devtools-evm': 3.0.0(jo52nddy263jgqv5tm5d6h6l4y) + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/devtools-evm': 3.0.0(12f7ac699b26ccb47df1abaabd2a94a9) '@layerzerolabs/export-deployments': 0.0.16 '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) '@layerzerolabs/lz-definitions': 3.0.134 @@ -5613,7 +6152,32 @@ snapshots: - supports-color - utf-8-validate - '@layerzerolabs/devtools-evm@3.0.0(jo52nddy263jgqv5tm5d6h6l4y)': + '@layerzerolabs/devtools-evm@3.0.0(12f7ac699b26ccb47df1abaabd2a94a9)': + dependencies: + '@ethersproject/abi': 5.8.0 + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/contracts': 5.8.0 + '@ethersproject/providers': 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) + '@layerzerolabs/lz-definitions': 3.0.134 + '@safe-global/api-kit': 1.3.1 + '@safe-global/protocol-kit': 1.3.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + fp-ts: 2.16.11 + p-memoize: 4.0.4 + zod: 3.25.76 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + + '@layerzerolabs/devtools-evm@3.0.0(61455fb0ab7185b357a251f5c1c0c1a4)': dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/abstract-provider': 5.8.0 @@ -5623,7 +6187,7 @@ snapshots: '@ethersproject/constants': 5.8.0 '@ethersproject/contracts': 5.8.0 '@ethersproject/providers': 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) '@layerzerolabs/lz-definitions': 3.0.134 '@safe-global/api-kit': 1.3.1 @@ -5638,7 +6202,25 @@ snapshots: - supports-color - utf-8-validate - '@layerzerolabs/devtools@2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76)': + '@layerzerolabs/devtools-solana@3.0.4(d71aeb896849a5a916511ae075bd924f)': + dependencies: + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) + '@layerzerolabs/lz-definitions': 3.0.134 + '@solana-developers/helpers': 2.8.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bn.js: 5.2.2 + fp-ts: 2.16.11 + p-memoize: 4.0.4 + zod: 3.25.76 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate + + '@layerzerolabs/devtools@2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76)': dependencies: '@ethersproject/bytes': 5.8.0 '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) @@ -5679,12 +6261,12 @@ snapshots: dependencies: typescript: 5.9.2 - '@layerzerolabs/hyperliquid-composer@1.0.3(rncsfq7prpd4x2t6py66ws27em)': + '@layerzerolabs/hyperliquid-composer@2.0.2(22453134066ae3d5b4b3c8090071d359)': dependencies: '@layerzerolabs/lz-evm-messagelib-v2': 3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-protocol-v2': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-v1-0.7': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@layerzerolabs/oapp-evm': 0.3.2(6b2bntffp5oh3n4ur2kgzua4ai) + '@layerzerolabs/oapp-evm': 0.3.2(def64342eef69769a3ede3bff20ec454) '@openzeppelin/contracts': 5.4.0 '@openzeppelin/contracts-upgradeable': 5.4.0(@openzeppelin/contracts@5.4.0) commander: 11.1.0 @@ -5716,13 +6298,43 @@ snapshots: '@layerzerolabs/lz-core@3.0.134': {} - '@layerzerolabs/lz-definitions@3.0.134': - dependencies: - tiny-invariant: 1.3.3 + '@layerzerolabs/lz-core@3.0.147': {} - '@layerzerolabs/lz-evm-messagelib-v2@3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4)': + '@layerzerolabs/lz-corekit-solana@3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': dependencies: - '@axelar-network/axelar-gmp-sdk-solidity': 5.10.0 + '@layerzerolabs/lz-core': 3.0.147 + '@layerzerolabs/lz-utilities': 3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-eddsa-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-program-repository': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-rpc-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-transaction-factory-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@noble/hashes': 1.8.0 + '@noble/secp256k1': 1.7.1 + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bip39: 3.1.0 + ed25519-hd-key: 1.3.0 + memoizee: 0.4.17 + transitivePeerDependencies: + - '@gql.tada/svelte-support' + - '@gql.tada/vue-support' + - bufferutil + - debug + - encoding + - typescript + - utf-8-validate + + '@layerzerolabs/lz-definitions@3.0.134': + dependencies: + tiny-invariant: 1.3.3 + + '@layerzerolabs/lz-definitions@3.0.147': + dependencies: + tiny-invariant: 1.3.3 + + '@layerzerolabs/lz-evm-messagelib-v2@3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4)': + dependencies: + '@axelar-network/axelar-gmp-sdk-solidity': 5.10.0 '@chainlink/contracts-ccip': 0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) '@eth-optimism/contracts': 0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) '@layerzerolabs/lz-evm-protocol-v2': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) @@ -5732,7 +6344,7 @@ snapshots: hardhat-deploy: 0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) solidity-bytes-utils: 0.8.4 - '@layerzerolabs/lz-evm-oapp-v2@3.0.134(5qj37ryyxgs2ov7ycombjhwncq)': + '@layerzerolabs/lz-evm-oapp-v2@3.0.134(cdc9a005b3add4311166a146590ee4e0)': dependencies: '@layerzerolabs/lz-evm-messagelib-v2': 3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-protocol-v2': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) @@ -5773,13 +6385,113 @@ snapshots: '@openzeppelin/contracts-upgradeable': 5.4.0(@openzeppelin/contracts@5.4.0) hardhat-deploy: 0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@layerzerolabs/lz-foundation@3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@layerzerolabs/lz-definitions': 3.0.147 + '@layerzerolabs/lz-utilities': 3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@noble/ed25519': 1.7.5 + '@noble/hashes': 1.8.0 + '@noble/secp256k1': 1.7.1 + '@scure/base': 1.2.6 + bech32: 2.0.0 + memoizee: 0.4.17 + transitivePeerDependencies: + - '@gql.tada/svelte-support' + - '@gql.tada/vue-support' + - bufferutil + - debug + - encoding + - typescript + - utf-8-validate + + '@layerzerolabs/lz-serdes@3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@coral-xyz/anchor': 0.29.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@layerzerolabs/lz-core': 3.0.147 + '@layerzerolabs/lz-utilities': 3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@layerzerolabs/tron-utilities': 3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + aptos: 1.21.0 + bip39: 3.1.0 + ed25519-hd-key: 1.3.0 + ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + memoizee: 0.4.17 + tronweb: 5.3.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - '@gql.tada/svelte-support' + - '@gql.tada/vue-support' + - bufferutil + - debug + - encoding + - typescript + - utf-8-validate + + '@layerzerolabs/lz-solana-sdk-v2@3.0.147(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@layerzerolabs/lz-corekit-solana': 3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@layerzerolabs/lz-definitions': 3.0.147 + '@layerzerolabs/lz-foundation': 3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@layerzerolabs/lz-serdes': 3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@layerzerolabs/lz-utilities': 3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@layerzerolabs/lz-v2-utilities': 3.0.147 + '@metaplex-foundation/beet': 0.7.2 + '@metaplex-foundation/beet-solana': 0.4.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@metaplex-foundation/mpl-toolbox': 0.9.4(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-eddsa-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-program-repository': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-rpc-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-web3js-adapters': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@solana/spl-token': 0.3.11(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bn.js: 5.2.2 + bs58: 5.0.0 + tiny-invariant: 1.3.3 + transitivePeerDependencies: + - '@gql.tada/svelte-support' + - '@gql.tada/vue-support' + - bufferutil + - debug + - encoding + - fastestsmallesttextencoderdecoder + - supports-color + - typescript + - utf-8-validate + '@layerzerolabs/lz-utilities@3.0.134(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': dependencies: '@ethersproject/bytes': 5.8.0 '@initia/initia.js': 1.0.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@layerzerolabs/lz-definitions': 3.0.134 '@mysten/sui': 1.38.0(typescript@5.9.2) - '@solana/web3.js': 1.95.8(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@ton/core': 0.59.1(@ton/crypto@3.3.0) + '@ton/crypto': 3.3.0 + '@ton/ton': 15.1.0(@ton/core@0.59.1(@ton/crypto@3.3.0))(@ton/crypto@3.3.0) + aptos: 1.21.0 + bip39: 3.1.0 + dayjs: 1.11.18 + ed25519-hd-key: 1.3.0 + ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + memoizee: 0.4.17 + picocolors: 1.0.0 + pino: 8.21.0 + transitivePeerDependencies: + - '@gql.tada/svelte-support' + - '@gql.tada/vue-support' + - bufferutil + - debug + - encoding + - typescript + - utf-8-validate + + '@layerzerolabs/lz-utilities@3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@initia/initia.js': 1.0.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@iota/iota-sdk': 1.7.1(typescript@5.9.2) + '@layerzerolabs/lz-definitions': 3.0.147 + '@mysten/sui': 1.38.0(typescript@5.9.2) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@ton/core': 0.59.1(@ton/crypto@3.3.0) '@ton/crypto': 3.3.0 '@ton/ton': 15.1.0(@ton/core@0.59.1(@ton/crypto@3.3.0))(@ton/crypto@3.3.0) @@ -5811,12 +6523,23 @@ snapshots: bs58: 5.0.0 tiny-invariant: 1.3.3 - '@layerzerolabs/metadata-tools@3.0.2(@layerzerolabs/devtools-evm-hardhat@4.0.0(fc3jrsl3gwkzaktl4lbr75yxly))(@layerzerolabs/ua-devtools@5.0.1(a6hdbzasdsvgu3ndz3tgfize4u))': + '@layerzerolabs/lz-v2-utilities@3.0.147': dependencies: - '@layerzerolabs/devtools-evm-hardhat': 4.0.0(fc3jrsl3gwkzaktl4lbr75yxly) - '@layerzerolabs/ua-devtools': 5.0.1(a6hdbzasdsvgu3ndz3tgfize4u) + '@ethersproject/abi': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/solidity': 5.8.0 + bs58: 5.0.0 + tiny-invariant: 1.3.3 + + '@layerzerolabs/metadata-tools@3.0.2(@layerzerolabs/devtools-evm-hardhat@4.0.0(fdad73f79aba17df6aeb1b3f7f199cbc))(@layerzerolabs/ua-devtools@5.0.1(65dc7f5c79b0faa85f9d82ed2d345648))': + dependencies: + '@layerzerolabs/devtools-evm-hardhat': 4.0.0(fdad73f79aba17df6aeb1b3f7f199cbc) + '@layerzerolabs/ua-devtools': 5.0.1(65dc7f5c79b0faa85f9d82ed2d345648) - '@layerzerolabs/oapp-evm-upgradeable@0.1.2(6b2bntffp5oh3n4ur2kgzua4ai)': + '@layerzerolabs/oapp-evm-upgradeable@0.1.2(def64342eef69769a3ede3bff20ec454)': dependencies: '@layerzerolabs/lz-evm-messagelib-v2': 3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-protocol-v2': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) @@ -5828,7 +6551,7 @@ snapshots: - bufferutil - utf-8-validate - '@layerzerolabs/oapp-evm@0.3.2(6b2bntffp5oh3n4ur2kgzua4ai)': + '@layerzerolabs/oapp-evm@0.3.2(def64342eef69769a3ede3bff20ec454)': dependencies: '@layerzerolabs/lz-evm-messagelib-v2': 3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-protocol-v2': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) @@ -5840,31 +6563,57 @@ snapshots: - bufferutil - utf-8-validate - '@layerzerolabs/oft-evm-upgradeable@3.2.0(wf4w5rqg52yfqco3osd3yat5dy)': + '@layerzerolabs/oft-evm-upgradeable@3.2.0(d7ffb4ff30b28b73f6b810e31084c2ee)': dependencies: '@layerzerolabs/lz-evm-messagelib-v2': 3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-protocol-v2': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-v1-0.7': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@layerzerolabs/oapp-evm': 0.3.2(6b2bntffp5oh3n4ur2kgzua4ai) + '@layerzerolabs/oapp-evm': 0.3.2(def64342eef69769a3ede3bff20ec454) '@openzeppelin/contracts': 5.4.0 '@openzeppelin/contracts-upgradeable': 5.4.0(@openzeppelin/contracts@5.4.0) - '@layerzerolabs/oft-evm@3.2.1(wf4w5rqg52yfqco3osd3yat5dy)': + '@layerzerolabs/oft-evm@3.2.1(d7ffb4ff30b28b73f6b810e31084c2ee)': dependencies: '@layerzerolabs/lz-evm-messagelib-v2': 3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-protocol-v2': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-v1-0.7': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@layerzerolabs/oapp-evm': 0.3.2(6b2bntffp5oh3n4ur2kgzua4ai) + '@layerzerolabs/oapp-evm': 0.3.2(def64342eef69769a3ede3bff20ec454) '@openzeppelin/contracts': 5.4.0 '@openzeppelin/contracts-upgradeable': 5.4.0(@openzeppelin/contracts@5.4.0) + '@layerzerolabs/oft-v2-solana-sdk@3.0.147(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@layerzerolabs/lz-foundation': 3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@layerzerolabs/lz-solana-sdk-v2': 3.0.147(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@layerzerolabs/lz-v2-utilities': 3.0.147 + '@metaplex-foundation/beet': 0.7.2 + '@metaplex-foundation/beet-solana': 0.4.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-eddsa-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-program-repository': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-web3js-adapters': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bn.js: 5.2.2 + dotenv: 16.6.1 + transitivePeerDependencies: + - '@gql.tada/svelte-support' + - '@gql.tada/vue-support' + - bufferutil + - debug + - encoding + - fastestsmallesttextencoderdecoder + - supports-color + - typescript + - utf-8-validate + '@layerzerolabs/prettier-config-next@2.3.44': dependencies: prettier: 3.6.2 prettier-plugin-packagejson: 2.5.19(prettier@3.6.2) prettier-plugin-solidity: 1.4.3(prettier@3.6.2) - '@layerzerolabs/protocol-devtools-evm@5.0.1(s2x3iqqexa5adx5ssy3krjpzsu)': + '@layerzerolabs/protocol-devtools-evm@5.0.1(4e2b97db86906cffbfb9a8b3bc18f622)': dependencies: '@ethersproject/abstract-provider': 5.8.0 '@ethersproject/abstract-signer': 5.8.0 @@ -5872,28 +6621,42 @@ snapshots: '@ethersproject/constants': 5.8.0 '@ethersproject/contracts': 5.8.0 '@ethersproject/providers': 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) - '@layerzerolabs/devtools-evm': 3.0.0(jo52nddy263jgqv5tm5d6h6l4y) + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/devtools-evm': 3.0.0(12f7ac699b26ccb47df1abaabd2a94a9) '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) '@layerzerolabs/lz-definitions': 3.0.134 - '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) p-memoize: 4.0.4 zod: 3.25.76 - '@layerzerolabs/protocol-devtools@3.0.1(@layerzerolabs/devtools@2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76)': + '@layerzerolabs/protocol-devtools-solana@8.0.4(5e0c91c042d8d231ef7fad536bd998cb)': dependencies: - '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/devtools-solana': 3.0.4(d71aeb896849a5a916511ae075bd924f) '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) '@layerzerolabs/lz-definitions': 3.0.134 + '@layerzerolabs/lz-solana-sdk-v2': 3.0.147(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@layerzerolabs/lz-v2-utilities': 3.0.134 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/ua-devtools': 5.0.1(65dc7f5c79b0faa85f9d82ed2d345648) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + fp-ts: 2.16.11 zod: 3.25.76 - '@layerzerolabs/script-devtools-evm-foundry@1.0.0(c5z2cllqcedew3jczcswndke2y)': + '@layerzerolabs/protocol-devtools@3.0.1(@layerzerolabs/devtools@2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76)': + dependencies: + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) + '@layerzerolabs/lz-definitions': 3.0.134 + zod: 3.25.76 + + '@layerzerolabs/script-devtools-evm-foundry@1.0.0(ddc6b0923e79f756c4d09ca081319a6f)': dependencies: '@layerzerolabs/lz-evm-messagelib-v2': 3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-protocol-v2': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-v1-0.7': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@layerzerolabs/oapp-evm': 0.3.2(6b2bntffp5oh3n4ur2kgzua4ai) - '@layerzerolabs/oft-evm': 3.2.1(wf4w5rqg52yfqco3osd3yat5dy) + '@layerzerolabs/oapp-evm': 0.3.2(def64342eef69769a3ede3bff20ec454) + '@layerzerolabs/oft-evm': 3.2.1(d7ffb4ff30b28b73f6b810e31084c2ee) '@openzeppelin/contracts': 5.4.0 '@openzeppelin/contracts-upgradeable': 5.4.0(@openzeppelin/contracts@5.4.0) @@ -5903,13 +6666,13 @@ snapshots: transitivePeerDependencies: - typescript - '@layerzerolabs/test-devtools-evm-foundry@7.0.0(c5z2cllqcedew3jczcswndke2y)': + '@layerzerolabs/test-devtools-evm-foundry@7.0.0(ddc6b0923e79f756c4d09ca081319a6f)': dependencies: '@layerzerolabs/lz-evm-messagelib-v2': 3.0.134(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@eth-optimism/contracts@0.6.0(bufferutil@4.0.9)(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@layerzerolabs/lz-evm-protocol-v2@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4))(@layerzerolabs/lz-evm-v1-0.7@3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-protocol-v2': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) '@layerzerolabs/lz-evm-v1-0.7': 3.0.134(@openzeppelin/contracts-upgradeable@5.4.0(@openzeppelin/contracts@5.4.0))(@openzeppelin/contracts@5.4.0)(hardhat-deploy@0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@layerzerolabs/oapp-evm': 0.3.2(6b2bntffp5oh3n4ur2kgzua4ai) - '@layerzerolabs/oft-evm': 3.2.1(wf4w5rqg52yfqco3osd3yat5dy) + '@layerzerolabs/oapp-evm': 0.3.2(def64342eef69769a3ede3bff20ec454) + '@layerzerolabs/oft-evm': 3.2.1(d7ffb4ff30b28b73f6b810e31084c2ee) '@openzeppelin/contracts': 5.4.0 '@openzeppelin/contracts-upgradeable': 5.4.0(@openzeppelin/contracts@5.4.0) @@ -5927,20 +6690,20 @@ snapshots: '@ethersproject/bytes': 5.8.0 '@ethersproject/contracts': 5.8.0 '@ethersproject/hash': 5.8.0 - '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) - '@layerzerolabs/devtools-evm': 3.0.0(jo52nddy263jgqv5tm5d6h6l4y) - '@layerzerolabs/devtools-evm-hardhat': 4.0.0(fc3jrsl3gwkzaktl4lbr75yxly) + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/devtools-evm': 3.0.0(61455fb0ab7185b357a251f5c1c0c1a4) + '@layerzerolabs/devtools-evm-hardhat': 4.0.0(fdad73f79aba17df6aeb1b3f7f199cbc) '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) '@layerzerolabs/lz-definitions': 3.0.134 '@layerzerolabs/lz-evm-sdk-v1': 3.0.134(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@layerzerolabs/lz-evm-sdk-v2': 3.0.134(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@layerzerolabs/lz-v2-utilities': 3.0.134 - '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) - '@layerzerolabs/protocol-devtools-evm': 5.0.1(s2x3iqqexa5adx5ssy3krjpzsu) + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/protocol-devtools-evm': 5.0.1(4e2b97db86906cffbfb9a8b3bc18f622) '@layerzerolabs/test-devtools-evm-hardhat': 0.5.2(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.9.2))(typescript@5.9.2)(utf-8-validate@5.0.10))(solidity-bytes-utils@0.8.4) - '@layerzerolabs/ua-devtools': 5.0.1(a6hdbzasdsvgu3ndz3tgfize4u) - '@layerzerolabs/ua-devtools-evm': 7.0.0(e3vuenvbu6epsppdeuvjflw3fy) - '@layerzerolabs/ua-devtools-evm-hardhat': 9.0.0(f4nrqiblzwgsv76l6kc345xzui) + '@layerzerolabs/ua-devtools': 5.0.1(65dc7f5c79b0faa85f9d82ed2d345648) + '@layerzerolabs/ua-devtools-evm': 7.0.0(a8696ec934f2e811b96abb023d3e669c) + '@layerzerolabs/ua-devtools-evm-hardhat': 9.0.0(0f45e6a71604805add10fd962c424cfb) '@nomicfoundation/hardhat-ethers': 3.1.0(ethers@5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.9.2))(typescript@5.9.2)(utf-8-validate@5.0.10)) ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) fp-ts: 2.16.11 @@ -5966,49 +6729,80 @@ snapshots: - supports-color - utf-8-validate - '@layerzerolabs/ua-devtools-evm-hardhat@9.0.0(f4nrqiblzwgsv76l6kc345xzui)': + '@layerzerolabs/tron-utilities@3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@layerzerolabs/lz-utilities': 3.0.147(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + tronweb: 5.3.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - '@gql.tada/svelte-support' + - '@gql.tada/vue-support' + - bufferutil + - debug + - encoding + - typescript + - utf-8-validate + + '@layerzerolabs/ua-devtools-evm-hardhat@9.0.0(0f45e6a71604805add10fd962c424cfb)': dependencies: '@ethersproject/abi': 5.8.0 '@ethersproject/bytes': 5.8.0 '@ethersproject/contracts': 5.8.0 '@ethersproject/hash': 5.8.0 - '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) - '@layerzerolabs/devtools-evm': 3.0.0(jo52nddy263jgqv5tm5d6h6l4y) - '@layerzerolabs/devtools-evm-hardhat': 4.0.0(fc3jrsl3gwkzaktl4lbr75yxly) + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/devtools-evm': 3.0.0(12f7ac699b26ccb47df1abaabd2a94a9) + '@layerzerolabs/devtools-evm-hardhat': 4.0.0(fdad73f79aba17df6aeb1b3f7f199cbc) '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) '@layerzerolabs/lz-definitions': 3.0.134 - '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) - '@layerzerolabs/protocol-devtools-evm': 5.0.1(s2x3iqqexa5adx5ssy3krjpzsu) - '@layerzerolabs/ua-devtools': 5.0.1(a6hdbzasdsvgu3ndz3tgfize4u) - '@layerzerolabs/ua-devtools-evm': 7.0.0(e3vuenvbu6epsppdeuvjflw3fy) + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/protocol-devtools-evm': 5.0.1(4e2b97db86906cffbfb9a8b3bc18f622) + '@layerzerolabs/ua-devtools': 5.0.1(65dc7f5c79b0faa85f9d82ed2d345648) + '@layerzerolabs/ua-devtools-evm': 7.0.0(a8696ec934f2e811b96abb023d3e669c) ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) hardhat: 2.26.3(bufferutil@4.0.9)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.9.2))(typescript@5.9.2)(utf-8-validate@5.0.10) hardhat-deploy: 0.12.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) p-memoize: 4.0.4 typescript: 5.9.2 - '@layerzerolabs/ua-devtools-evm@7.0.0(e3vuenvbu6epsppdeuvjflw3fy)': + '@layerzerolabs/ua-devtools-evm@7.0.0(a8696ec934f2e811b96abb023d3e669c)': dependencies: '@ethersproject/constants': 5.8.0 '@ethersproject/contracts': 5.8.0 - '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) - '@layerzerolabs/devtools-evm': 3.0.0(jo52nddy263jgqv5tm5d6h6l4y) + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/devtools-evm': 3.0.0(12f7ac699b26ccb47df1abaabd2a94a9) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) + '@layerzerolabs/lz-definitions': 3.0.134 + '@layerzerolabs/lz-v2-utilities': 3.0.134 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/protocol-devtools-evm': 5.0.1(4e2b97db86906cffbfb9a8b3bc18f622) + '@layerzerolabs/ua-devtools': 5.0.1(65dc7f5c79b0faa85f9d82ed2d345648) + p-memoize: 4.0.4 + zod: 3.25.76 + + '@layerzerolabs/ua-devtools-solana@8.0.4(d78575199144cb92633a174d1c330235)': + dependencies: + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/devtools-solana': 3.0.4(d71aeb896849a5a916511ae075bd924f) '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) '@layerzerolabs/lz-definitions': 3.0.134 + '@layerzerolabs/lz-solana-sdk-v2': 3.0.147(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@layerzerolabs/lz-v2-utilities': 3.0.134 - '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) - '@layerzerolabs/protocol-devtools-evm': 5.0.1(s2x3iqqexa5adx5ssy3krjpzsu) - '@layerzerolabs/ua-devtools': 5.0.1(a6hdbzasdsvgu3ndz3tgfize4u) + '@layerzerolabs/oft-v2-solana-sdk': 3.0.147(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/protocol-devtools-solana': 8.0.4(5e0c91c042d8d231ef7fad536bd998cb) + '@layerzerolabs/ua-devtools': 5.0.1(65dc7f5c79b0faa85f9d82ed2d345648) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + fp-ts: 2.16.11 p-memoize: 4.0.4 zod: 3.25.76 - '@layerzerolabs/ua-devtools@5.0.1(a6hdbzasdsvgu3ndz3tgfize4u)': + '@layerzerolabs/ua-devtools@5.0.1(65dc7f5c79b0faa85f9d82ed2d345648)': dependencies: - '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/devtools': 2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76) '@layerzerolabs/lz-definitions': 3.0.134 '@layerzerolabs/lz-v2-utilities': 3.0.134 - '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.3(@ethersproject/bytes@5.8.0)(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76))(@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink-table@3.1.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2))(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.25.76))(@layerzerolabs/lz-definitions@3.0.134)(zod@3.25.76) zod: 3.25.76 '@ledgerhq/devices@8.5.1': @@ -6045,6 +6839,134 @@ snapshots: '@mdn/browser-compat-data@5.7.6': {} + '@metaplex-foundation/beet-solana@0.4.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@metaplex-foundation/beet': 0.7.2 + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bs58: 5.0.0 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - typescript + - utf-8-validate + + '@metaplex-foundation/beet@0.7.2': + dependencies: + ansicolors: 0.3.2 + assert: 2.1.0 + bn.js: 5.2.2 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@metaplex-foundation/mpl-token-metadata@3.4.0(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/mpl-toolbox': 0.10.0(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/mpl-toolbox@0.10.0(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/mpl-toolbox@0.9.4(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/umi-bundle-defaults@0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-downloader-http': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-eddsa-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-http-fetch': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-program-repository': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-rpc-chunk-get-accounts': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-rpc-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@metaplex-foundation/umi-serializer-data-view': 0.9.2(@metaplex-foundation/umi@0.9.2) + '@metaplex-foundation/umi-transaction-factory-web3js': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - encoding + + '@metaplex-foundation/umi-downloader-http@0.9.2(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/umi-eddsa-web3js@0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-web3js-adapters': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@noble/curves': 1.9.7 + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + + '@metaplex-foundation/umi-http-fetch@0.9.2(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + '@metaplex-foundation/umi-options@0.8.9': {} + + '@metaplex-foundation/umi-program-repository@0.9.2(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/umi-public-keys@0.8.9': + dependencies: + '@metaplex-foundation/umi-serializers-encodings': 0.8.9 + + '@metaplex-foundation/umi-rpc-chunk-get-accounts@0.9.2(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/umi-rpc-web3js@0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-web3js-adapters': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + + '@metaplex-foundation/umi-serializer-data-view@0.9.2(@metaplex-foundation/umi@0.9.2)': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + + '@metaplex-foundation/umi-serializers-core@0.8.9': {} + + '@metaplex-foundation/umi-serializers-encodings@0.8.9': + dependencies: + '@metaplex-foundation/umi-serializers-core': 0.8.9 + + '@metaplex-foundation/umi-serializers-numbers@0.8.9': + dependencies: + '@metaplex-foundation/umi-serializers-core': 0.8.9 + + '@metaplex-foundation/umi-serializers@0.9.0': + dependencies: + '@metaplex-foundation/umi-options': 0.8.9 + '@metaplex-foundation/umi-public-keys': 0.8.9 + '@metaplex-foundation/umi-serializers-core': 0.8.9 + '@metaplex-foundation/umi-serializers-encodings': 0.8.9 + '@metaplex-foundation/umi-serializers-numbers': 0.8.9 + + '@metaplex-foundation/umi-transaction-factory-web3js@0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + '@metaplex-foundation/umi-web3js-adapters': 0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + + '@metaplex-foundation/umi-web3js-adapters@0.9.2(@metaplex-foundation/umi@0.9.2)(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))': + dependencies: + '@metaplex-foundation/umi': 0.9.2 + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + buffer: 6.0.3 + + '@metaplex-foundation/umi@0.9.2': + dependencies: + '@metaplex-foundation/umi-options': 0.8.9 + '@metaplex-foundation/umi-public-keys': 0.8.9 + '@metaplex-foundation/umi-serializers': 0.9.0 + '@mysten/bcs@1.8.0': dependencies: '@mysten/utils': 0.2.0 @@ -6092,6 +7014,8 @@ snapshots: dependencies: '@noble/hashes': 1.8.0 + '@noble/ed25519@1.7.5': {} + '@noble/hashes@1.2.0': {} '@noble/hashes@1.3.3': {} @@ -6299,6 +7223,17 @@ snapshots: - supports-color - utf-8-validate + '@safe-global/safe-core-sdk-types@1.10.1': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/contracts': 5.8.0 + '@safe-global/safe-deployments': 1.37.45 + web3-core: 1.10.4 + web3-utils: 1.10.4 + transitivePeerDependencies: + - encoding + - supports-color + '@safe-global/safe-core-sdk-types@2.3.0': dependencies: '@ethersproject/bignumber': 5.8.0 @@ -6409,18 +7344,178 @@ snapshots: '@sindresorhus/is@5.6.0': {} + '@solana-developers/helpers@2.8.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@coral-xyz/anchor': 0.30.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/spl-token': 0.4.14(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/spl-token-metadata': 0.1.6(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bn.js: 5.2.2 + bs58: 6.0.0 + dotenv: 16.6.1 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate + + '@solana-developers/helpers@2.8.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@coral-xyz/anchor': 0.30.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/spl-token': 0.4.14(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/spl-token-metadata': 0.1.6(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bn.js: 5.2.2 + bs58: 6.0.0 + dotenv: 16.6.1 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate + + '@solana/buffer-layout-utils@0.2.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@solana/buffer-layout': 4.0.1 + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bigint-buffer: 1.1.5 + bignumber.js: 9.3.1 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate + '@solana/buffer-layout@4.0.1': dependencies: buffer: 6.0.3 - '@solana/web3.js@1.95.8(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + '@solana/codecs-core@2.0.0-rc.1(typescript@5.9.2)': + dependencies: + '@solana/errors': 2.0.0-rc.1(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/codecs-core@2.3.0(typescript@5.9.2)': + dependencies: + '@solana/errors': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/codecs-data-structures@2.0.0-rc.1(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.9.2) + '@solana/errors': 2.0.0-rc.1(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/codecs-numbers@2.0.0-rc.1(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.0.0-rc.1(typescript@5.9.2) + '@solana/errors': 2.0.0-rc.1(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/codecs-numbers@2.3.0(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/codecs-strings@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.9.2) + '@solana/errors': 2.0.0-rc.1(typescript@5.9.2) + fastestsmallesttextencoderdecoder: 1.0.22 + typescript: 5.9.2 + + '@solana/codecs@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-data-structures': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-strings': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/options': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/errors@2.0.0-rc.1(typescript@5.9.2)': + dependencies: + chalk: 5.6.2 + commander: 12.1.0 + typescript: 5.9.2 + + '@solana/errors@2.3.0(typescript@5.9.2)': + dependencies: + chalk: 5.6.2 + commander: 14.0.2 + typescript: 5.9.2 + + '@solana/options@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-data-structures': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-strings': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.0.0-rc.1(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/spl-token-group@0.0.7(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - typescript + + '@solana/spl-token-metadata@0.1.6(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - typescript + + '@solana/spl-token@0.3.11(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@solana/buffer-layout': 4.0.1 + '@solana/buffer-layout-utils': 0.2.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/spl-token-metadata': 0.1.6(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + buffer: 6.0.3 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate + + '@solana/spl-token@0.4.14(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@solana/buffer-layout': 4.0.1 + '@solana/buffer-layout-utils': 0.2.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/spl-token-group': 0.0.7(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/spl-token-metadata': 0.1.6(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + buffer: 6.0.3 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate + + '@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': dependencies: '@babel/runtime': 7.28.4 '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@solana/buffer-layout': 4.0.1 + '@solana/codecs-numbers': 2.3.0(typescript@5.9.2) agentkeepalive: 4.6.0 - bigint-buffer: 1.1.5 bn.js: 5.2.2 borsh: 0.7.0 bs58: 4.0.1 @@ -6433,12 +7528,15 @@ snapshots: transitivePeerDependencies: - bufferutil - encoding + - typescript - utf-8-validate '@solidity-parser/parser@0.18.0': {} '@solidity-parser/parser@0.20.2': {} + '@suchipi/femver@1.0.0': {} + '@swc/helpers@0.5.17': dependencies: tslib: 2.8.1 @@ -6478,6 +7576,8 @@ snapshots: transitivePeerDependencies: - debug + '@tronweb3/google-protobuf@3.21.4': {} + '@tsconfig/node10@1.0.11': {} '@tsconfig/node12@1.0.11': {} @@ -6815,6 +7915,8 @@ snapshots: ansi-styles@6.2.3: {} + ansicolors@0.3.2: {} + antlr4@4.13.2: {} anymatch@3.1.3: @@ -6897,6 +7999,14 @@ snapshots: assert-plus@1.0.0: {} + assert@2.1.0: + dependencies: + call-bind: 1.0.8 + is-nan: 1.3.2 + object-is: 1.1.6 + object.assign: 4.1.7 + util: 0.12.5 + assertion-error@1.1.0: {} ast-metadata-inferer@0.8.1: @@ -7102,6 +8212,8 @@ snapshots: buffer-from@1.1.2: {} + buffer-layout@1.2.2: {} + buffer-to-arraybuffer@0.0.5: {} buffer-xor@1.0.3: {} @@ -7200,6 +8312,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chalk@5.6.2: {} + chardet@2.1.0: {} check-error@1.0.3: @@ -7319,6 +8433,10 @@ snapshots: commander@11.1.0: {} + commander@12.1.0: {} + + commander@14.0.2: {} + commander@2.20.3: {} commander@8.3.0: {} @@ -7404,6 +8522,12 @@ snapshots: create-require@1.1.1: {} + cross-fetch@3.2.0: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + cross-fetch@4.1.0: dependencies: node-fetch: 2.7.0 @@ -7416,6 +8540,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crypto-hash@1.3.0: {} + d@1.0.2: dependencies: es5-ext: 0.10.64 @@ -7525,6 +8651,11 @@ snapshots: dom-walk@0.1.2: {} + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + dotenv@16.6.1: {} dunder-proto@1.0.1: @@ -8021,8 +9152,12 @@ snapshots: event-target-shim@5.0.1: {} + eventemitter3@3.1.2: {} + eventemitter3@4.0.4: {} + eventemitter3@4.0.7: {} + eventemitter3@5.0.1: {} events@3.3.0: {} @@ -8102,6 +9237,8 @@ snapshots: fast-uri@3.1.0: {} + fastestsmallesttextencoderdecoder@1.0.22: {} + fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -8634,6 +9771,8 @@ snapshots: ini@1.3.8: {} + injectpromise@1.0.0: {} + ink-gradient@2.0.0(ink@3.2.0(bufferutil@4.0.9)(react@17.0.2)(utf-8-validate@5.0.10))(react@17.0.2): dependencies: gradient-string: 1.2.0 @@ -8788,6 +9927,11 @@ snapshots: is-map@2.0.3: {} + is-nan@1.3.2: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + is-negative-zero@2.0.3: {} is-number-object@1.1.1: @@ -9006,6 +10150,10 @@ snapshots: dependencies: get-func-name: 2.0.2 + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + lowercase-keys@2.0.0: {} lowercase-keys@3.0.0: {} @@ -9215,6 +10363,11 @@ snapshots: next-tick@1.1.0: {} + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + node-addon-api@2.0.2: {} node-addon-api@5.1.0: {} @@ -9248,6 +10401,11 @@ snapshots: object-inspect@1.13.4: {} + object-is@1.1.6: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + object-keys@1.1.1: {} object.assign@4.1.7: @@ -9366,6 +10524,8 @@ snapshots: registry-url: 6.0.1 semver: 7.7.2 + pako@2.1.0: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -9540,6 +10700,8 @@ snapshots: object-assign: 4.1.1 strict-uri-encode: 1.1.0 + querystring-es3@0.2.1: {} + queue-microtask@1.2.3: {} quick-format-unescaped@4.0.4: {} @@ -9930,6 +11092,11 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 + snake-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + solc@0.8.26(debug@4.4.3): dependencies: command-exists: 1.2.9 @@ -10092,6 +11259,8 @@ snapshots: strip-json-comments@3.1.1: {} + superstruct@0.15.5: {} + superstruct@2.0.2: {} supports-color@5.5.0: @@ -10207,6 +11376,8 @@ snapshots: toidentifier@1.0.1: {} + toml@3.0.0: {} + tough-cookie@2.5.0: dependencies: psl: 1.15.0 @@ -10218,6 +11389,26 @@ snapshots: triple-beam@1.4.1: {} + tronweb@5.3.4(bufferutil@4.0.9)(utf-8-validate@5.0.10): + dependencies: + '@babel/runtime': 7.28.4 + '@ethersproject/abi': 5.8.0 + '@tronweb3/google-protobuf': 3.21.4 + axios: 1.12.2 + bignumber.js: 9.3.1 + ethereum-cryptography: 2.2.1 + ethers: 5.8.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + eventemitter3: 3.1.2 + injectpromise: 1.0.0 + lodash: 4.17.21 + querystring-es3: 0.2.1 + semver: 5.7.2 + validator: 13.15.23 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + ts-api-utils@1.4.3(typescript@5.9.2): dependencies: typescript: 5.9.2 @@ -10417,6 +11608,8 @@ snapshots: optionalDependencies: typescript: 5.9.2 + validator@13.15.23: {} + varint@5.0.2: {} vary@1.1.2: {} diff --git a/solana/mainnet/Deployment.md b/solana/mainnet/Deployment.md new file mode 100644 index 0000000..102b5fa --- /dev/null +++ b/solana/mainnet/Deployment.md @@ -0,0 +1,236 @@ +# Mainnet deployment + +## Requirements + +Ofts are deployed and wired on Ethereum and Hyperliquid + +### Versions checks: + +```bash + anchor -V && solana -V && rustc -V && spl-token -V +``` + +``` + anchor-cli 0.32.1 + solana-cli 2.3.0 (src:a2e21dda; feat:3640012085, client:Agave) + rustc 1.90.0-nightly (35f603652 2025-06-29) + spl-token-cli 5.3.0 +``` + +(agave-install for solana versions) + +## Deploy + +1. Generate new keypair for deployer + + ```bash + DEPLOYER_KEYPAIR=~/deployments/wxrp/mainnet.json + solana-keygen new -o $DEPLOYER_KEYPAIR + ``` + + Assigning `pubkey` as deployer address. + + ```bash + DEPLOYER_ADDR=FqbEHeg8hH36M9A56wBbKu3k1PD81cKFfPD9zpzL7AoU # Lz owned + ``` + +2. Set configuration for Solana CLI + + ```bash + solana config set -k $DEPLOYER_KEYPAIR + solana config set --url https://api.mainnet-beta.solana.com + solana config get + solana address + ``` + +3. Generate new keypair for OFT program + + ```bash + solana-keygen new -o target/deploy/oft-keypair.json -f + # Note: -f overwrites any exisitng keys in that location + ``` + + Use `pubkey` as OFT_ID. + + ```bash + OFT_ID=H5WWM7uWHbmZjThKyPbjNGvAagizKA9zzchZWwn79W99 + ``` + +4. Build Solana OFT (verifiable) + + ```bash + anchor build -v -e OFT_ID=$OFT_ID + ``` + +5. Deploy OFT + + ```bash + solana program deploy --program-id target/deploy/oft-keypair.json target/verifiable/oft.so + ``` + + ``` + Program Id: H5WWM7uWHbmZjThKyPbjNGvAagizKA9zzchZWwn79W99 + + Signature: nfjDsmm3VV7jNmF3nrQxtcZzFn1oX268r5HbFGUaiY2hjdaaxLHmiKixWq5pXcTbMa2MS8PDqC2MZ8nXpGo7a7Y + ``` + + https://solscan.io/account/H5WWM7uWHbmZjThKyPbjNGvAagizKA9zzchZWwn79W99 + + +## Multisig vaults and roles + +Admin: https://app.squads.so/squads/FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E/home +Ops: https://app.squads.so/squads/2WpgARMHmfvvy6sqij5KfKvQFJen7R1DwEocmuMgfjX9/home + +```bash + ADMIN_SQUADS_VAULT_ADDR=FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E + OPS_SQUADS_VAULT_ADDR=2WpgARMHmfvvy6sqij5KfKvQFJen7R1DwEocmuMgfjX9 +``` + +``` + Admin Multisig: + - Token and OFT program Owner and Delegate + - Upgrade authority + - Token metadata update authority + - Other authorities for different extensions + + Operator Multisig: + - Mint authority (Minting) + - Permanent Delegate (Burning) (note, that permanent delegate can transfer tokens from any account) + - Freeze Authority (Blacklisting) + - Pausable Authority (Pausing) +``` + +## Create OFT + +1. Init OFT + + ```bash + npx hardhat lz:oft:solana:create --eid 30168 --name "Wrapped XRP" --symbol "wXRP" --local-decimals 6 --shared-decimals 6 --uri "" --seller-fee-basis-points 0 --token-metadata-is-mutable true --token-program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA --program-id H5WWM7uWHbmZjThKyPbjNGvAagizKA9zzchZWwn79W99 --amount 0 --additional-minters $OPS_SQUADS_VAULT_ADDR + # Note: Additional minters should be a squads vault address -> https://app.squads.so/squads + # The address will be combined with oft store address to create native multisig + # so OFT program can mint/burn tokens but also squads multisig + ``` + + ``` + createMultisigTx: https://solscan.io/tx/5sd3dZaLPXKJwnRoKFycYPY69wDXk7ndvmEvwi22mCHTDVfa1GrfEJwubuoDbHEAb5tdHxyMBA8K2MbzDJhUfcnH?cluster=mainnet-beta + created SPL multisig @ E5GXVzJbuN7iPJAfNB23SMXgQLXWGkqRWgvsq4Dg156o + createTokenTx: https://solscan.io/tx/qbJuF791MnLxoY1jnARYDhmrhTmiAk4DzNPseLWEa3muXcTd5rAPmtXkg8gJv6qxWQkxerWwnojokDqrDZNTL3E?cluster=mainnet-beta + initOftTx: https://solscan.io/tx/3EuXvbstEh2ZW1Qekm4WXWTV1y1kTFB8e2v3RZ2DbqBZoKoeA3G7bQYYErseqKVbU3WTzL5jSzdsa7SXYWFLZLpC?cluster=mainnet-beta + setAuthorityTx: https://solscan.io/tx/4ZYuHTx98aYx5QqJtjfyTjcbrdVZCWyqjEXxKyebwTa3Vmqso27hQFxxJc5MrL4dGtKX9uvULniS62VUuZRmGLw2?cluster=mainnet-beta + ``` + +2. Adjust owner in `consts/mainnet.ts` to $DEPLOYER_ADDR + +3. Init config (Solana specific) - one account per non-solana chain (3 chains) + + ```bash + pnpm hardhat lz:oft:solana:init-config --oapp-config layerzero.mainnet.config.ts + ``` + +4. Wire Solana outwards (to Eth, Optimism and Hyperliquid) + + ```bash + pnpm hardhat lz:oapp:wire --oapp-config layerzero.mainnet.config.ts --skip-connections-from-eids 30101,30111,30367 + ``` + + `10 txs - setPeer x3, setUln x6, setEnfOpt x1` + +5. Prepare calldata to wire inwards to Solana + + ```bash + pnpm hardhat lz:oapp:wire --oapp-config layerzero.mainnet.config.ts --signer $ADMIN_SQUADS_VAULT_ADDR --skip-connections-from-eids 30168 --output-filename mainnet-txs.log + ``` + +6. Adjust owner in `consts/mainnet.ts` to $ADMIN_SQUADS_VAULT_ADDR + +## Transfer ownership + +1. Transfer delegate and ownership for solana OFT + +pnpm hardhat lz:oapp:wire --oapp-config layerzero.mainnet.config.ts --skip-connections-from-eids 30101,30111,30367 + +npx hardhat lz:ownable:transfer-ownership --oapp-config layerzero.mainnet.config.ts + +2. Update OFT program upgrade authority + + ```bash + solana program set-upgrade-authority $OFT_ID --new-upgrade-authority $ADMIN_SQUADS_VAULT_ADDR --skip-new-upgrade-authority-signer-check -um + solana program show $OFT_ID + ``` + + ``` + Account Type: Program + Authority: FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E + + + Program Id: H5WWM7uWHbmZjThKyPbjNGvAagizKA9zzchZWwn79W99 + Owner: BPFLoaderUpgradeab1e11111111111111111111111 + ProgramData Address: 2wnZELFtb6Aw2VQTU3CMN4pKAcx5RQdj26m99ui3gkec + Authority: FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E + Last Deployed In Slot: 386914855 + Data Length: 571200 (0x8b740) bytes + Balance: 3.97675608 SOL + ``` + +3. Transfer pauser/unpauser and admin/delegate + + From `deployments/solana-mainnet/OFT.json` + + ```bash + OFT_STORE=FwF2zxV5MaFZfq3pgfcgzJqKWBRyYsiVNVEXqxgshKaH + pnpm hardhat lz:oft:solana:set-config --eid 30168 --oft-store $OFT_STORE --program-id $OFT_ID --pauser $ADMIN_SQUADS_VAULT_ADDR + pnpm hardhat lz:oft:solana:set-config --eid 30168 --oft-store $OFT_STORE --program-id $OFT_ID --unpauser $ADMIN_SQUADS_VAULT_ADDR + pnpm hardhat lz:oft:solana:set-config --eid 30168 --oft-store $OFT_STORE --program-id $OFT_ID --new-delegate $ADMIN_SQUADS_VAULT_ADDR + pnpm hardhat lz:oft:solana:set-config --eid 30168 --oft-store $OFT_STORE --program-id $OFT_ID --new-admin $ADMIN_SQUADS_VAULT_ADDR + ``` + + ```bash + pnpm hardhat lz:oft:solana:debug --action delegate --eid 30168 + pnpm hardhat lz:oft:solana:debug --action admin --eid 30168 + ``` + + ``` + Delegate: FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E + Admin: FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E + ``` + +# Test + +1. Send Solana to Eth + + ```bash + pnpm hardhat lz:oft:send --src-eid 30168 --dst-eid 30101 --to --amount 2 --token-program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA + ``` + +2. And back + + ```bash + pnpm hardhat lz:oft:send --src-eid 30101 --dst-eid 30168 --to $DEPLOYER_ADDR --oft-address --amount 1 + ``` + + (Eth - 30101, Solana - 30168, Hyperliquid - 30367, Optimism - 30111) + +## Verification (mainnet only) + +1. Locally + `solana-verify get-executable-hash ./target/verifiable/oft.so` + +2. On chain + `solana-verify get-program-hash $OFT_ID` + +3. Verify on chain + `solana-verify verify-from-repo -um --program-id $OFT_ID --library-name oft -- --config env.OFT_ID=\'$OFT_ID\'` + `solana-verify remote submit-job --program-id $OFT_ID --uploader $DEPLOYER_ADDR` + +## Helpers + +1. Debug + + Use any of OFT_STORE,GET_ADMIN,GET_DELEGATE,CHECKS,GET_TOKEN,GET_PEERS,RATE_LIMITS. + + ```bash + pnpm hardhat lz:oft:solana:debug --action delegate --eid 30168 + pnpm hardhat lz:oft:solana:debug --action admin --eid 30168 + pnpm hardhat lz:oft:solana:debug --action checks --eid 30168 + ``` diff --git a/solana/mainnet/README.md b/solana/mainnet/README.md new file mode 100644 index 0000000..0c93d1a --- /dev/null +++ b/solana/mainnet/README.md @@ -0,0 +1,163 @@ +# Setup for lz-tool + +Prepare `.env` based on `.env.example` + +```bash + export SOLANA_KEYPAIR_PATH=~/deployments/wxrp/mainnet.json # Solana +``` + +Alternatively the default will be used `~/.config/solana/id.json` + +Recommended RPC provider for Solana -> https://www.helius.dev/ + +# Sending tokens from and to Solana + +1. Send Solana to Eth + + ```bash + pnpm hardhat lz:oft:send --src-eid 30168 --dst-eid 30101 --to --amount 2 --token-program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA + ``` + +2. And back + + ```bash + pnpm hardhat lz:oft:send --src-eid 30101 --dst-eid 30168 --to --oft-address --amount 1 + ``` + + (Eth - 30101, Solana - 30168, Hyperliquid - 30367, Optimism - 30111) + +# Squads and phantom wallet + +Mainnet version - https://app.squads.so/ + +Alternatively Metamask wallet supports Solana and works fine. + +# OFT instructions as multisig (squads) + +## Pause/unpause OFT + +1. Generate transaction + + Use `lz:oft:solana:set-config` to pause or unpause the OFT + + ```bash + pnpm hardhat lz:oft:solana:set-config \ + --eid 30168 \ + --oft-store $OFT_STORE \ + --program-id $OFT_ID \ + --paused false \ + --compute-unit-price-scale-factor 4 --output-base58 + ``` + +# Token instructions as multisig (squads) + +## Mint + +1. Generate transaction + + ```bash + SOL_ADDR=E1LSQ86sxrmkjBthCR8PKpiKrq5YFLxr41VbSZ2XKSJD + TOKEN_ADDR=6UpQcMAb5xMzxc7ZfPaVMgx3KqsvKZdT5U718BzD5We2 + MULTISIG_ADDR=E5GXVzJbuN7iPJAfNB23SMXgQLXWGkqRWgvsq4Dg156o + OPS_SQUADS_VAULT_ADDR=2WpgARMHmfvvy6sqij5KfKvQFJen7R1DwEocmuMgfjX9 + pnpm hardhat lz:solana:mint --token-addr $TOKEN_ADDR --user-addr $SOL_ADDR --amount 10 --eid 30168 --multisig-addr $MULTISIG_ADDR --squads-addr $OPS_SQUADS_VAULT_ADDR --signer-addr $OPS_SQUADS_VAULT_ADDR + ``` + +2. Verify with explorer + + https://explorer.solana.com/tx/inspector?cluster=devnet + +3. Import to Tx builder as base58 tx. Simulate, propose and sign. + + https://backup.app.squads.so/#/transactions/ + + Note: remember to set multisig and rpc url to `https://api.devnet.solana.com` + +4. Check the balance + + ```bash + spl-token balance $TOKEN_ADDR --owner $SOL_ADDR + ``` + +## Burn + +1. Generate transaction + + ```bash + pnpm hardhat lz:solana:burn --token-addr $TOKEN_ADDR --user-addr $SOL_ADDR --amount 1 --eid 30168 --squads-addr $OPS_SQUADS_VAULT_ADDR --signer-addr $OPS_SQUADS_VAULT_ADDR + ``` + +## Blacklist user (or unblacklist) + +1. Generate transaction + + Use `lz:solana:blacklist` to pause token and `lz:solana:unblacklist` to unpause + + ```bash + pnpm hardhat lz:solana:blacklist \ + --eid 30168 \ + --token-addr $TOKEN_ADDR \ + --user-addr $USER_ADDR \ + --multisig-addr $MULTISIG_ADDR \ + --signer-addr $OPS_SQUADS_VAULT_ADDR + ``` + +## Change metadata + +```bash + pnpm hardhat lz:solana:update-metadata --token-addr $TOKEN_ADDR --eid 30168 --squads-addr $ADMIN_SQUADS_VAULT_ADDR --field Uri --value https://ipfs.io/ipfs/bafkreig6wrikw4oj4j4j3aws2jaaf2vztpmcuixfe2rgjfp4ua5qlwkpz4 +``` + +## Update blacklist (aka freeze) authority + + ```bash + pnpm hardhat lz:solana:set-freeze-authority \ + --eid 30168 \ + --token-addr $TOKEN_ADDR \ + --multisig-addr $MULTISIG_ADDR \ + --squads-addr $OPS_SQUADS_VAULT_ADDR \ + --signer-addr $OPS_SQUADS_VAULT_ADDR \ + --new-authority-addr $NEW_FREEZE_AUTHORITY + ``` + + +## Update metadata authority + + ```bash + pnpm hardhat lz:solana:set-metadata-authority \ + --eid 30168 \ + --token-addr $TOKEN_ADDR \ + --current-authority $CURRENT_AUTHORITY \ + --new-authority-addr $NEW_AUTHORITY + ``` + + +# Wiring instructions EVMs to Solana + +```bash + pnpm hardhat lz:oapp:wire --oapp-config layerzero.mainnet.config.ts --signer $ADMIN_SQUADS_VAULT_ADDR --skip-connections-from-eids 30168 --output-filename tx-data/all-evm-mainnet-txs.log +``` + +# Wiring instructions Solana to EVMs as multisig (squads) + +Required: + +```bash + cargo install bs58-cli +``` + +## Wire Solana outwards as multisig (squads) + +1. Prepare change tx + +```bash + pnpm hardhat lz:oapp:wire --oapp-config layerzero.mainnet.config.ts --signer $ADMIN_SQUADS_VAULT_ADDR --output-filename tx-data/solana-mainnet-txs.log --skip-connections-from-eids 30101,30111,30367 +``` + +2. Convert each calladata from `tx-data/solana-mainnet-txs.log` to base58 + +```bash + echo "0201080c7ffa2b58d45fd5a2fe855a8115f1948b7744c38af71f281fbd212ff3b322bd0f2176f6d374c8f31f8676e913dfd53496c4fb10c996ea8d9e077920546ce8bc24906b37d9940bedde5c6f7e605c3f774993d084de4d55f6733867263a05d96a74ff4b00a690db853244ac95f729d22190f052fa48deaa8c04d392449a0e314e3616b7830c3f8a44c810ca87de56e032889c358ec75d4732bf7361862658acb2af29ada86fcdf809dfbe3361053fd30d3b26e4d26c031aeb39402efc871f9c31e43bb66c6947983775eb253df3d1c9818c2f958899b64a23b05a51bc8ed358f6e95aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18b619e429a1de67854bd455ee6643f568d6236cde8e9442a3abf029f016faae63064addff32f7e70f064aaeb7199486126df6abfa7e1b33d41a4673fab17868534ecd3ea8ab2798656e0feeb82bf86fd956d0f9017f29ecb30ac3e2738946f4489f6b5e2feee246bf3f87d58e36d7a5821ba27d48475708e46b09308afe3d912eacbee4ab52b8b832ab774fde91370b7195c1b1d360eac37784465e7d3a0ab6bee01070c01050604080403020b0a090887016c9e9aafd462344234e9dcd39e2f02d13047276d6cfaecb10fda22b86e022311edd05fb5aad5fb04aa9d000003000000530000000100000000000000ff0201000000000200000010f76722686ec33f3e58a48458950e7faff5c7e788c7e8b164e2504ffb801c4633cdb9fb56d28a2f028cbb36c254a7d54c92f0419b53e44ddcc0a5c373f854f2" | xxd -r -p | bs58 +``` + +3. Verify with explorer https://explorer.solana.com/tx/inspector?cluster=devnet and upload to https://backup.app.squads.so diff --git a/solana/testnet/Deployment.md b/solana/testnet/Deployment.md new file mode 100644 index 0000000..d19965b --- /dev/null +++ b/solana/testnet/Deployment.md @@ -0,0 +1,199 @@ +# Testnet deployment + +Note: On Solana the devnet is default network for testing. +We'll use only devnet in all scenarios. +The testnet is used for stress tests. + +## Requirements + +Ofts are deployed and wired on Ethereum and Hyperliquid + +### Versions checks: + +```bash + anchor -V && solana -V && rustc -V && spl-token -V +``` + +``` + anchor-cli 0.32.1 + solana-cli 2.3.0 (src:a2e21dda; feat:3640012085, client:Agave) + rustc 1.90.0-nightly (35f603652 2025-06-29) + spl-token-cli 5.3.0 +``` + +(agave-install for solana versions) + +## Deploy + +1. Generate new keypair for deployer + + ```bash + DEPLOYER_KEYPAIR=~/deployments/wxrp/testnet.json + solana-keygen new -o $DEPLOYER_KEYPAIR + ``` + + Assigning `pubkey` as deployer address. + + ```bash + DEPLOYER_ADDR=HJagyGRc3w4TxdaidAWjA6tjSbxj8UHeJpytdtGimJ6a # Lz owned + ``` + +2. Set configuration for Solana CLI + + ```bash + solana config set -k $DEPLOYER_KEYPAIR + solana config set --url https://api.devnet.solana.com + solana config get + ``` + +3. Generate new keypair for OFT program + + ```bash + solana-keygen new -o target/deploy/oft-keypair.json -f + # Note: -f overwrites any exisitng keys in that location + ``` + + Use `pubkey` as OFT_ID. + + ```bash + OFT_ID=ANBPMYzXfRt5xwwGDzakyjHCeCr2jkLJrN5E8z8vSspD + ``` + +4. Build Solana OFT (verifiable) + + ```bash + anchor build -v -e OFT_ID=$OFT_ID + ``` + +5. Deploy OFT + + ```bash + solana program deploy --program-id target/deploy/oft-keypair.json target/verifiable/oft.so + ``` + +## Create OFT + +1. Init OFT + + ```bash + SQUADS_VAULT_ADDR=Hy6h65XTsDkR6DBcGjr33WTpCJpM9dyLywYyu81vPKob + SOLANA_KEYPAIR_PATH=$DEPLOYER_KEYPAIR + npx hardhat lz:oft:solana:create --eid 40168 --name "Wrapped XRP" --symbol "WXRP" --local-decimals 6 --shared-decimals 6 --uri "www.hextrust.com" --seller-fee-basis-points 0 --token-metadata-is-mutable true --token-program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA --program-id $OFT_ID --amount 10000000 --additional-minters $SQUADS_VAULT_ADDR + # Note: Additional minters should be a squads vault address -> https://app.squads.so/squads + # The address will be combined with oft store address to create native multisig + # so OFT program can mint/burn tokens but also squads multisig + ``` + + ``` + createMultisigTx: https://solscan.io/tx/2qdBj5k4Ddvusq7Qv7QfGVeVfCk9AA16vfj37qriUWZjL9c9ZMYsUKM3kHPSZpADzTi6xK59LP2hLMcHmdYrBu4G?cluster=devnet + created SPL multisig @ 8vWTyXD3rVza9Fvr5oN7QuhASGEyMYi6Dzj7pZGRXCCG + createTokenTx: https://solscan.io/tx/5aiTCUrM5hp5LbvKWiir9xaAPMf5s58V4q9KKZB94x8sZN9DmQ74eHjYjQRJSr1VDLfejPuotd1hrrWhNe4r5BL8?cluster=devnet + initOftTx: https://solscan.io/tx/2FQdLyugpapgdTqgGepryUfxqZLhZSmrrxnWjiLJiAvt4s6aZida1ATDD3UNF5ESb8nyWAzmryQPRsc63qMTHDtc?cluster=devnet + ``` + +2. Init config (Solana specific) - one account per non-solana chain + + ```bash + pnpm hardhat lz:oft:solana:init-config --oapp-config layerzero.testnet.config.ts + ``` + +3. Adjust owner in `consts/testnet.ts` to $DEPLOYER_ADDR + +4. Wire Solana outwards (to Sepolia and Hyperliquid) + + ```bash + pnpm hardhat lz:oapp:wire --oapp-config layerzero.testnet.config.ts --skip-connections-from-eids 40161,40362 + ``` + +5. Prepare calldata to wire inwards to Solana + + ```bash + pnpm hardhat lz:oapp:wire --oapp-config layerzero.testnet.config.ts --signer $SQUADS_VAULT_ADDR --skip-connections-from-eids 40168 --output-filename testnet-txs.log + ``` + +6. Adjust owner in `consts/testnet.ts` to $SQUADS_VAULT_ADDR + +## Transfer ownership +TODO once wired +1. Transfer delegate and ownership for solana OFT + +pnpm hardhat lz:oapp:wire --oapp-config layerzero.mainnet.config.ts --skip-connections-from-eids 30101,30111,30367 + +npx hardhat lz:ownable:transfer-ownership --oapp-config layerzero.mainnet.config.ts + +2. Update OFT program upgrade authority + + ```bash + solana program set-upgrade-authority $OFT_ID --new-upgrade-authority $ADMIN_SQUADS_VAULT_ADDR --skip-new-upgrade-authority-signer-check -um + solana program show $OFT_ID + ``` + + ``` + Account Type: Program + Authority: FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E + + + Program Id: H5WWM7uWHbmZjThKyPbjNGvAagizKA9zzchZWwn79W99 + Owner: BPFLoaderUpgradeab1e11111111111111111111111 + ProgramData Address: 2wnZELFtb6Aw2VQTU3CMN4pKAcx5RQdj26m99ui3gkec + Authority: FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E + Last Deployed In Slot: 386914855 + Data Length: 571200 (0x8b740) bytes + Balance: 3.97675608 SOL + ``` + +3. Transfer pauser/unpauser and admin/delegate + + From `deployments/solana-mainnet/OFT.json` + + ```bash + OFT_STORE=FwF2zxV5MaFZfq3pgfcgzJqKWBRyYsiVNVEXqxgshKaH + pnpm hardhat lz:oft:solana:set-config --eid 30168 --oft-store $OFT_STORE --program-id $OFT_ID --pauser $ADMIN_SQUADS_VAULT_ADDR + pnpm hardhat lz:oft:solana:set-config --eid 30168 --oft-store $OFT_STORE --program-id $OFT_ID --unpauser $ADMIN_SQUADS_VAULT_ADDR + pnpm hardhat lz:oft:solana:set-config --eid 30168 --oft-store $OFT_STORE --program-id $OFT_ID --new-delegate $ADMIN_SQUADS_VAULT_ADDR + pnpm hardhat lz:oft:solana:set-config --eid 30168 --oft-store $OFT_STORE --program-id $OFT_ID --new-admin $ADMIN_SQUADS_VAULT_ADDR + ``` + + ```bash + pnpm hardhat lz:oft:solana:debug --action delegate --eid 30168 + pnpm hardhat lz:oft:solana:debug --action admin --eid 30168 + ``` + + ``` + Delegate: FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E + Admin: FPg2KxupxTMNFk4PwBXBVF2PSvVfKyL9QBWi21huA47E + ``` + +# Test + +1. Send Solana to Eth + + ```bash + pnpm hardhat lz:oft:send --src-eid 30168 --dst-eid 30101 --to --amount 2 --token-program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA + ``` + +2. And back + + ```bash + pnpm hardhat lz:oft:send --src-eid 30101 --dst-eid 30168 --to $DEPLOYER_ADDR --oft-address --amount 1 + ``` + + (Eth - 30101, Solana - 30168, Hyperliquid - 30367, Optimism - 30111) + + +## Create Squads multisig (testnet only) + +On mainnet it costs ~0.10-0.15 SOL and can be done via interface. + +Docs: https://docs.squads.so/main/development/cli/commands#multisig-create +Permissions list: https://docs.squads.so/main/development/reference/permissions + +```bash + squads-multisig-cli multisig-create --rpc-url https://api.devnet.solana.com --keypair $DEPLOYER_KEYPAIR --threshold 1 --members "$DEPLOYER_ADDR,7" --members "B2edFYj5sC4GV4FbHKSJnFfMVWmEgP96u3pLxxJbkjXy,7" --members "8jZviur8nvByf7uypy13SAT22FeeVmeenpzK5tQE8oKm,7" +``` + +``` + ✅ Created Multisig: GcXaQZmVmBkFKuKNCzbYeoXs9Vc1VZ3za1zxdtjXFdR5. Signature: 3MBxTQEu2X4qA5UjfpY4TiWJP3BLhhPVJf7wncZnh1ojUM5Vea4YbvBKECWQL8CjcC2WV4rG2i2HG8eamxht9arU +``` + +Get the index 0 vault from https://backup.app.squads.so and assign to `SQUADS_VAULT_ADDR=Hy6h65XTsDkR6DBcGjr33WTpCJpM9dyLywYyu81vPKob`. diff --git a/solana/testnet/README.md b/solana/testnet/README.md new file mode 100644 index 0000000..6e96257 --- /dev/null +++ b/solana/testnet/README.md @@ -0,0 +1,123 @@ +# Setup for lz-tool + +Prepare `.env` based on `.env.example` + +```bash + export SOLANA_KEYPAIR_PATH=~/deployments/wxrp/testnet.json # Solana +``` + +Alternatively the default will be used `~/.config/solana/id.json` + +# Sending tokens from and to Solana + +1. Send Solana to Eth + + ```bash + pnpm hardhat lz:oft:send --src-eid 40168 --dst-eid 40161 --to --amount 2 --token-program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb + ``` + +2. And back + + ```bash + pnpm hardhat lz:oft:send --src-eid 40161 --dst-eid 40168 --to --oft-address --amount 1 + ``` + + (Sepolia - 40161, Solana - 40168, Hyperliquid testnet - 40362) + +# Squads and phantom wallet + +Mainnet version works without any issues - https://app.squads.so/ + +Testnet version doesn't automatically detect testnet - https://backup.app.squads.so +It is required to change Phantom setting to testnet - https://docs.adrena.trade/guides/how-to-change-to-devnet-in-phantom-wallet + +Alternatively Metamask wallet supports Solana and works fine. + +# Token instructions as multisig (squads) + +## Mint + +1. Generate transaction + + ```bash + SOL_ADDR=7XeCYeAzpFxByBa3fBLe8NZdqXp8kc7JANGv5fNTkhpE + TOKEN_ADDR=wxrpANtqnkD1b9Ux8KSVX2ZRChkkmpiKf2Vj5qo4WQ9 + MULTISIG_ADDR=ByB7kbz989r7Wq1E9d7GKrodfqhtuUePBQ77BtuxZq1t + SQUADS_VAULT_ADDR=Hy6h65XTsDkR6DBcGjr33WTpCJpM9dyLywYyu81vPKob + SIGNER_ADDR=B2edFYj5sC4GV4FbHKSJnFfMVWmEgP96u3pLxxJbkjXy + pnpm hardhat lz:solana:mint --token-addr $TOKEN_ADDR --user-addr $SOL_ADDR --amount 100 --eid 40168 --multisig-addr $MULTISIG_ADDR --squads-addr $SQUADS_VAULT_ADDR --signer-addr $SIGNER_ADDR + ``` + +2. Verify with explorer + + https://explorer.solana.com/tx/inspector?cluster=devnet + +3. Import to Tx builder as base58 tx. Simulate, propose and sign. + + https://backup.app.squads.so/#/transactions/ + + Note: remember to set multisig and rpc url to `https://api.devnet.solana.com` + +4. Check the balance + + ```bash + spl-token balance $TOKEN_ADDR --owner $SOL_ADDR + ``` + +## Burn + +1. Generate transaction + + ```bash + pnpm hardhat lz:solana:burn --token-addr $TOKEN_ADDR --user-addr $SOL_ADDR --amount 100 --eid 40168 --squads-addr $SQUADS_VAULT_ADDR --signer-addr $SIGNER_ADDR + ``` + +## Pause/unpause token + +1. Generate transaction + + Use `lz:solana:pause` to pause token and `lz:solana:resume` to unpause + + ```bash + pnpm hardhat lz:solana:pause --token-addr $TOKEN_ADDR --eid 40168 --squads-addr $SQUADS_VAULT_ADDR --signer-addr $SIGNER_ADDR + ``` + +## Blacklist user (or unblacklist) + +1. Generate transaction + + Use `lz:solana:blacklist` to pause token and `lz:solana:unblacklist` to unpause + + ```bash + pnpm hardhat lz:solana:blacklist --token-addr $TOKEN_ADDR --user-addr $SOL_ADDR --eid 40168 --squads-addr $SQUADS_VAULT_ADDR + ``` + +# Wiring instructions EVMs to Solana + +```bash + pnpm hardhat lz:oapp:wire --oapp-config layerzero.testnet.config.ts --signer $SQUADS_VAULT_ADDR --skip-connections-from-eids 40168 --output-filename testnet-txs.log +``` + +# Wiring instructions Solana to EVMs as multisig (squads) + +Required: + +```bash + cargo install bs58-cli +``` + +## Wire Solana outwards as multisig (squads) + +1. Prepare change tx + +```bash + pnpm hardhat lz:oapp:wire --oapp-config layerzero.testnet.config.ts --signer $SQUADS_VAULT_ADDR --output-filename testnet-txs.log --skip-connections-from-eids 40161,40362 +``` + +2. Convert each calladata from `testnet-txs.log` to base58 + +```bash + echo "0201080c7ffa2b58d45fd5a2fe855a8115f1948b7744c38af71f281fbd212ff3b322bd0f2176f6d374c8f31f8676e913dfd53496c4fb10c996ea8d9e077920546ce8bc24906b37d9940bedde5c6f7e605c3f774993d084de4d55f6733867263a05d96a74ff4b00a690db853244ac95f729d22190f052fa48deaa8c04d392449a0e314e3616b7830c3f8a44c810ca87de56e032889c358ec75d4732bf7361862658acb2af29ada86fcdf809dfbe3361053fd30d3b26e4d26c031aeb39402efc871f9c31e43bb66c6947983775eb253df3d1c9818c2f958899b64a23b05a51bc8ed358f6e95aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18b619e429a1de67854bd455ee6643f568d6236cde8e9442a3abf029f016faae63064addff32f7e70f064aaeb7199486126df6abfa7e1b33d41a4673fab17868534ecd3ea8ab2798656e0feeb82bf86fd956d0f9017f29ecb30ac3e2738946f4489f6b5e2feee246bf3f87d58e36d7a5821ba27d48475708e46b09308afe3d912eacbee4ab52b8b832ab774fde91370b7195c1b1d360eac37784465e7d3a0ab6bee01070c01050604080403020b0a090887016c9e9aafd462344234e9dcd39e2f02d13047276d6cfaecb10fda22b86e022311edd05fb5aad5fb04aa9d000003000000530000000100000000000000ff0201000000000200000010f76722686ec33f3e58a48458950e7faff5c7e788c7e8b164e2504ffb801c4633cdb9fb56d28a2f028cbb36c254a7d54c92f0419b53e44ddcc0a5c373f854f2" | xxd -r -p | bs58 +``` + +3. Verify with explorer https://explorer.solana.com/tx/inspector?cluster=devnet and upload to https://backup.app.squads.so diff --git a/tasks/common/config.get.ts b/tasks/common/config.get.ts new file mode 100644 index 0000000..4d06584 --- /dev/null +++ b/tasks/common/config.get.ts @@ -0,0 +1,212 @@ +import { PublicKey } from '@solana/web3.js' +import { task } from 'hardhat/config' +import { ActionType } from 'hardhat/types' + +import { OmniPoint, createDefaultApplicative } from '@layerzerolabs/devtools' +import { createConnectedContractFactory, getNetworkNameForEid } from '@layerzerolabs/devtools-evm-hardhat' +import { createLogger, printCrossTable, setDefaultLogLevel } from '@layerzerolabs/io-devtools' +import { ChainType, EndpointId, endpointIdToChainType, getNetworkForChainId } from '@layerzerolabs/lz-definitions' +import { EndpointV2 } from '@layerzerolabs/protocol-devtools-solana' +import { OAppOmniGraph } from '@layerzerolabs/ua-devtools' +import { createOAppFactory } from '@layerzerolabs/ua-devtools-evm' +import { + OAppOmniGraphHardhatSchema, + SUBTASK_LZ_OAPP_CONFIG_LOAD, + type SubtaskLoadConfigTaskArgs, + TASK_LZ_OAPP_CONFIG_GET, +} from '@layerzerolabs/ua-devtools-evm-hardhat' +import { getReceiveConfig, getSendConfig } from '@layerzerolabs/ua-devtools-evm-hardhat' + +import { getSolanaReceiveConfig, getSolanaSendConfig } from './taskHelper' +import { createSolanaConnectionFactory } from './utils' + +interface TaskArgs { + logLevel?: string + oappConfig: string +} + +/** + * Helper function to determine if the point is Solana + * @param point {OmniPoint} + */ +const isSolana = (point: OmniPoint) => endpointIdToChainType(point.eid) === ChainType.SOLANA +const isMoveVM = (point: OmniPoint) => + endpointIdToChainType(point.eid) === ChainType.APTOS || endpointIdToChainType(point.eid) === ChainType.INITIA + +/** + * Helper function to get the hardhat.config.ts network name for a given endpoint id, or use the convention of + * networkName-environment for Solana. + * @param eid {EndpointId} + */ +const getNetworkName = (eid: EndpointId) => { + const { chainName, env } = getNetworkForChainId(eid) + const hardhatUnsupportedEids: EndpointId[] = [ + EndpointId.SOLANA_V2_TESTNET, + EndpointId.SOLANA_V2_MAINNET, + EndpointId.APTOS_V2_MAINNET, + EndpointId.APTOS_V2_TESTNET, + EndpointId.MOVEMENT_V2_MAINNET, + EndpointId.MOVEMENT_V2_TESTNET, + EndpointId.INITIA_V2_MAINNET, + EndpointId.INITIA_V2_TESTNET, + ] + + if (hardhatUnsupportedEids.includes(eid)) { + return `${chainName}-${env}` + } else { + return getNetworkNameForEid(eid as any) + } +} + +const action: ActionType = async ({ logLevel = 'info', oappConfig }, hre) => { + setDefaultLogLevel(logLevel) + const logger = createLogger(logLevel) + + // const hardhatGraph = await getLzConfig(oappConfig) + // const transformer = createOmniGraphHardhatTransformer() + // const graph: OAppOmniGraph = await transformer(hardhatGraph) + + const graph: OAppOmniGraph = await hre.run(SUBTASK_LZ_OAPP_CONFIG_LOAD, { + configPath: oappConfig, + schema: OAppOmniGraphHardhatSchema, + task: TASK_LZ_OAPP_CONFIG_GET, + } satisfies SubtaskLoadConfigTaskArgs) + + const evmSdkFactory = createOAppFactory(createConnectedContractFactory()) + const configs: Record> = {} + + // Iterate over the graph of connections not from Solana + const tasks = graph.connections + .filter(({ vector: { from } }) => !isSolana(from) && !isMoveVM(from)) + .map(({ vector: { from, to } }) => async () => { + const endpointV2Sdk = await (await evmSdkFactory(from)).getEndpointSDK() + + // OApp User Set Config + const receiveCustomConfig = await getReceiveConfig(endpointV2Sdk, to.eid, from.address, true) + const sendCustomConfig = await getSendConfig(endpointV2Sdk, to.eid, from.address, true) + const [sendCustomLibrary, sendCustomUlnConfig, sendCustomExecutorConfig] = sendCustomConfig ?? [] + const [receiveCustomLibrary, receiveCustomUlnConfig] = receiveCustomConfig ?? [] + + // Default Config + const receiveDefaultConfig = await getReceiveConfig(endpointV2Sdk, to.eid) + const sendDefaultConfig = await getSendConfig(endpointV2Sdk, to.eid) + const [sendDefaultLibrary, sendDefaultUlnConfig, sendDefaultExecutorConfig] = sendDefaultConfig ?? [] + const [receiveDefaultLibrary, receiveDefaultUlnConfig] = receiveDefaultConfig ?? [] + + // OApp Config + const receiveOAppConfig = await getReceiveConfig(endpointV2Sdk, to.eid, from.address) + const sendOAppConfig = await getSendConfig(endpointV2Sdk, to.eid, from.address) + const [sendOAppLibrary, sendOAppUlnConfig, sendOAppExecutorConfig] = sendOAppConfig ?? [] + const [receiveOAppLibrary, receiveOAppUlnConfig] = receiveOAppConfig ?? [] + + const localNetworkName = getNetworkName(from.eid) + const remoteNetworkName = getNetworkName(to.eid) + + // Update the global state + configs[localNetworkName] = { + ...configs[localNetworkName], + [remoteNetworkName]: { + defaultSendLibrary: sendOAppLibrary, + defaultReceiveLibrary: receiveOAppLibrary, + sendUlnConfig: sendOAppUlnConfig, + sendExecutorConfig: sendOAppExecutorConfig, + receiveUlnConfig: receiveOAppUlnConfig, + }, + } + + console.log( + printCrossTable( + [ + { + localNetworkName, + remoteNetworkName, + sendLibrary: sendCustomLibrary, + receiveLibrary: receiveCustomLibrary, + sendUlnConfig: sendCustomUlnConfig, + sendExecutorConfig: sendCustomExecutorConfig, + receiveUlnConfig: receiveCustomUlnConfig, + }, + { + localNetworkName, + remoteNetworkName, + sendLibrary: sendDefaultLibrary, + receiveLibrary: receiveDefaultLibrary, + sendUlnConfig: sendDefaultUlnConfig, + sendExecutorConfig: sendDefaultExecutorConfig, + receiveUlnConfig: receiveDefaultUlnConfig, + }, + { + localNetworkName, + remoteNetworkName, + sendLibrary: sendOAppLibrary, + receiveLibrary: receiveOAppLibrary, + sendUlnConfig: sendOAppUlnConfig, + sendExecutorConfig: sendOAppExecutorConfig, + receiveUlnConfig: receiveOAppUlnConfig, + }, + ], + ['', 'Custom OApp Config', 'Default OApp Config', 'Active OApp Config'] + ) + ) + }) + // Iterate over the graph of connections from Solana + const solTasks = graph.connections + .filter(({ vector: { from } }) => isSolana(from)) + .map(({ vector: { from, to } }) => async () => { + const endpointV2Sdk = new EndpointV2( + await createSolanaConnectionFactory()(from.eid), + from, + new PublicKey(from.address) // doesn't matter as we are not sending transactions + ) + // OApp Config + const receiveOAppConfig = await getSolanaReceiveConfig(endpointV2Sdk, to.eid, from.address) + const sendOAppConfig = await getSolanaSendConfig(endpointV2Sdk, to.eid, from.address) + const [sendOAppLibrary, sendOAppUlnConfig, sendOAppExecutorConfig] = sendOAppConfig ?? [] + const [receiveOAppLibrary, receiveOAppUlnConfig] = receiveOAppConfig ?? [] + + const localNetworkName = getNetworkName(from.eid) + const remoteNetworkName = getNetworkName(to.eid) + + // Update the global state + configs[localNetworkName] = { + ...configs[localNetworkName], + [remoteNetworkName]: { + defaultSendLibrary: sendOAppLibrary, + defaultReceiveLibrary: receiveOAppLibrary, + sendUlnConfig: sendOAppUlnConfig, + sendExecutorConfig: sendOAppExecutorConfig, + receiveUlnConfig: receiveOAppUlnConfig, + }, + } + // Defaults are treated much differently in Solana, so we only output the active OApp config. + console.log( + printCrossTable( + [ + { + localNetworkName, + remoteNetworkName, + sendLibrary: sendOAppLibrary, + receiveLibrary: receiveOAppLibrary, + sendUlnConfig: sendOAppUlnConfig, + sendExecutorConfig: sendOAppExecutorConfig, + receiveUlnConfig: receiveOAppUlnConfig, + }, + ], + ['', 'Active OApp Config'] + ) + ) + }) + + // We allow this script to be executed either in parallel or in series + const applicative = createDefaultApplicative(logger) + await applicative(tasks) + await applicative(solTasks) + + return configs +} + +task( + TASK_LZ_OAPP_CONFIG_GET, + 'Outputs Custom OApp Config, Default OApp Config, and Active OApp Config. Each config contains Send & Receive Libraries, Send Uln & Executor Configs, and Receive Executor Configs', + action +) diff --git a/tasks/common/sendOFT.ts b/tasks/common/sendOFT.ts new file mode 100644 index 0000000..083e9e8 --- /dev/null +++ b/tasks/common/sendOFT.ts @@ -0,0 +1,106 @@ +import { task, types } from 'hardhat/config' +import { HardhatRuntimeEnvironment } from 'hardhat/types' + +import { ChainType, endpointIdToChainType, endpointIdToNetwork } from '@layerzerolabs/lz-definitions' + +import { EvmArgs, sendEvm } from '../evm/sendEvm' +import { SolanaArgs, sendSolana } from '../solana/sendSolana' + +import { SendResult } from './types' +import { DebugLogger, KnownOutputs, KnownWarnings, getBlockExplorerLink } from './utils' + +interface MasterArgs { + srcEid: number + dstEid: number + amount: string + to: string + /** Minimum amount to receive in case of custom slippage or fees (human readable units, e.g. "1.5") */ + minAmount?: string + /** Extra options for sending additional gas units to lzReceive, lzCompose, or receiver address */ + extraOptions?: string + /** Arbitrary bytes message to deliver alongside the OFT */ + composeMsg?: string + /** EVM: 20-byte hex; Solana: base58 PDA of the store */ + oftAddress?: string + /** Solana only: override the OFT program ID (base58) */ + oftProgramId?: string + tokenProgram?: string + computeUnitPriceScaleFactor?: number + addressLookupTables?: string +} + +task('lz:oft:send', 'Sends OFT tokens cross‐chain from any supported chain') + .addParam('srcEid', 'Source endpoint ID', undefined, types.int) + .addParam('dstEid', 'Destination endpoint ID', undefined, types.int) + .addParam('amount', 'Amount to send (human readable units, e.g. "1.5")', undefined, types.string) + .addParam('to', 'Base58 recipient (Solana) or bytes20-encoded target (EVM)', undefined, types.string) + .addOptionalParam( + 'minAmount', + 'Minimum amount to receive in case of custom slippage or fees (human readable units, e.g. "1.5")', + undefined, + types.string + ) + .addOptionalParam( + 'extraOptions', + 'Extra options for sending additional gas units to lzReceive, lzCompose, or receiver address', + undefined, + types.string + ) + .addOptionalParam('composeMsg', 'Arbitrary bytes message to deliver alongside the OFT', undefined, types.string) + .addOptionalParam( + 'oftAddress', + 'Override the source local deployment OFT address (20-byte hex for EVM, base58 PDA for Solana)', + undefined, + types.string + ) + .addOptionalParam('oftProgramId', 'Solana only: override the OFT program ID (base58)', undefined, types.string) + .addOptionalParam('tokenProgram', 'Solana Token Program pubkey', undefined, types.string) + .addOptionalParam('computeUnitPriceScaleFactor', 'Solana compute unit price scale factor', 4, types.float) + .addOptionalParam( + 'addressLookupTables', + 'Solana address lookup tables (comma separated base58 list)', + undefined, + types.string + ) + .setAction(async (args: MasterArgs, hre: HardhatRuntimeEnvironment) => { + const chainType = endpointIdToChainType(args.srcEid) + let result: SendResult + + if (args.oftAddress || args.oftProgramId) { + DebugLogger.printWarning( + KnownWarnings.USING_OVERRIDE_OFT, + `For network: ${endpointIdToNetwork(args.srcEid)}, OFT: ${args.oftAddress + (args.oftProgramId ? `, OFT program: ${args.oftProgramId}` : '')}` + ) + } + + // route to the correct function based on the chain type + if (chainType === ChainType.EVM) { + result = await sendEvm(args as EvmArgs, hre) + } else if (chainType === ChainType.SOLANA) { + result = await sendSolana({ + ...args, + addressLookupTables: args.addressLookupTables ? args.addressLookupTables.split(',') : [], + } as SolanaArgs) + } else { + throw new Error(`The chain type ${chainType} is not implemented in sendOFT for this example`) + } + + DebugLogger.printLayerZeroOutput( + KnownOutputs.SENT_VIA_OFT, + `Successfully sent ${args.amount} tokens from ${endpointIdToNetwork(args.srcEid)} to ${endpointIdToNetwork(args.dstEid)}` + ) + // print the explorer link for the srcEid from metadata + const explorerLink = await getBlockExplorerLink(args.srcEid, result.txHash) + // if explorer link is available, print the tx hash link + if (explorerLink) { + DebugLogger.printLayerZeroOutput( + KnownOutputs.TX_HASH, + `Explorer link for source chain ${endpointIdToNetwork(args.srcEid)}: ${explorerLink}` + ) + } + // print the LayerZero Scan link from metadata + DebugLogger.printLayerZeroOutput( + KnownOutputs.EXPLORER_LINK, + `LayerZero Scan link for tracking all cross-chain transaction details: ${result.scanLink}` + ) + }) diff --git a/tasks/common/taskHelper.ts b/tasks/common/taskHelper.ts new file mode 100644 index 0000000..9983de3 --- /dev/null +++ b/tasks/common/taskHelper.ts @@ -0,0 +1,72 @@ +import { OmniAddress } from '@layerzerolabs/devtools' +import { EndpointId } from '@layerzerolabs/lz-definitions' +import { UlnProgram } from '@layerzerolabs/lz-solana-sdk-v2' +import { + IEndpointV2, + Timeout, + Uln302ConfigType, + Uln302ExecutorConfig, + Uln302UlnConfig, +} from '@layerzerolabs/protocol-devtools' + +/** + * Get the receive config for a Solana OApp + * @param endpointV2Sdk {IEndpointV2} SDK for the endpoint + * @param remoteEid {EndpointId} remote eid + * @param address {OmniAddress} address of the OApp + */ +export async function getSolanaReceiveConfig( + endpointV2Sdk: IEndpointV2, + remoteEid: EndpointId, + address: OmniAddress +): Promise<[OmniAddress, Uln302UlnConfig, Timeout] | undefined> { + let receiveLibraryAddress = UlnProgram.PROGRAM_ADDRESS + try { + const [receiveLibrary] = await endpointV2Sdk.getReceiveLibrary(address, remoteEid) + if (receiveLibrary) { + receiveLibraryAddress = receiveLibrary + } + } catch { + // no action is necessary as upon error, we will just use the default UlnProgram.PROGRAM_ADDRESS + } + return [ + receiveLibraryAddress, + await endpointV2Sdk.getAppUlnConfig( + address, + UlnProgram.PROGRAM_ID.toBase58(), + remoteEid, + Uln302ConfigType.Receive + ), + { + lib: UlnProgram.PROGRAM_ID.toBase58(), + expiry: 0n, // unsupported for Solana + }, + ] +} + +/** + * Get the send config for a Solana OApp. + * @param endpointV2Sdk {IEndpointV2} SDK for the endpoint + * @param eid {EndpointId} remote eid + * @param address {OmniAddress} address of the OApp + */ +export async function getSolanaSendConfig( + endpointV2Sdk: IEndpointV2, + eid: EndpointId, + address: OmniAddress +): Promise<[OmniAddress, Uln302UlnConfig, Uln302ExecutorConfig] | undefined> { + let sendLibraryAddress = UlnProgram.PROGRAM_ADDRESS + try { + const sendLibrary = await endpointV2Sdk.getSendLibrary(address, eid) + if (sendLibrary) { + sendLibraryAddress = sendLibrary + } + } catch { + // no action is necessary as upon error, we will just use the default UlnProgram.PROGRAM_ADDRESS + } + return [ + sendLibraryAddress, + await endpointV2Sdk.getAppUlnConfig(address, UlnProgram.PROGRAM_ID.toBase58(), eid, Uln302ConfigType.Send), + await endpointV2Sdk.getAppExecutorConfig(address, sendLibraryAddress, eid), + ] +} diff --git a/tasks/common/types.ts b/tasks/common/types.ts new file mode 100644 index 0000000..2c4bf0d --- /dev/null +++ b/tasks/common/types.ts @@ -0,0 +1,24 @@ +import { decode } from '@coral-xyz/anchor/dist/cjs/utils/bytes/bs58' +import { Keypair, PublicKey } from '@solana/web3.js' +import { CLIArgumentType } from 'hardhat/types' + +export const keyPair: CLIArgumentType = { + name: 'keyPair', + parse(name: string, value: string) { + return Keypair.fromSecretKey(decode(value)) + }, + validate() {}, +} + +export const publicKey: CLIArgumentType = { + name: 'keyPair', + parse(name: string, value: string) { + return new PublicKey(value) + }, + validate() {}, +} + +export interface SendResult { + txHash: string // EVM: receipt.transactionHash, Solana: base58 sig + scanLink: string // LayerZeroScan link for cross-chain tracking +} diff --git a/tasks/common/utils.ts b/tasks/common/utils.ts new file mode 100644 index 0000000..d589c5e --- /dev/null +++ b/tasks/common/utils.ts @@ -0,0 +1,194 @@ +import { safeFetchMetadataFromSeeds } from '@metaplex-foundation/mpl-token-metadata' +import { fromWeb3JsPublicKey, toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters' +import { TOKEN_PROGRAM_ID, getTokenMetadata } from '@solana/spl-token' +import { Connection, PublicKey } from '@solana/web3.js' + +import { OmniPoint } from '@layerzerolabs/devtools' +import { createConnectedContractFactory } from '@layerzerolabs/devtools-evm-hardhat' +import { createSolanaConnectionFactory, createSolanaSignerFactory } from '@layerzerolabs/devtools-solana' +import { createLogger } from '@layerzerolabs/io-devtools' +import { ChainType, EndpointId, endpointIdToChainType, endpointIdToNetwork } from '@layerzerolabs/lz-definitions' +import { UlnProgram } from '@layerzerolabs/lz-solana-sdk-v2' +import { toWeb3Connection } from '@layerzerolabs/lz-solana-sdk-v2/umi' +import { Options } from '@layerzerolabs/lz-v2-utilities' +import { IOApp } from '@layerzerolabs/ua-devtools' +import { createOAppFactory } from '@layerzerolabs/ua-devtools-evm' +import { createOFTFactory } from '@layerzerolabs/ua-devtools-solana' + +import type { Umi, PublicKey as UmiPublicKey } from '@metaplex-foundation/umi' + +export { createSolanaConnectionFactory } + +const logger = createLogger() + +type DeploymentMetadata = { + blockExplorers?: Array<{ url?: string }> + [key: string]: unknown +} + +export const deploymentMetadataUrl = 'https://metadata.layerzero-api.com/v1/metadata/deployments' + +export enum MSG_TYPE { + SEND = 1, + SEND_AND_CALL = 2, +} + +/** + * Given a srcEid and on-chain tx hash, return + * `https://…blockExplorers[0].url/tx/`, or undefined. + */ + +export async function getBlockExplorerLink(srcEid: number, txHash: string): Promise { + const network = endpointIdToNetwork(srcEid) // e.g. "animechain-mainnet" + const res = await fetch(deploymentMetadataUrl) + if (!res.ok) return + const all = (await res.json()) as Record + const meta = all[network] + const explorer = meta?.blockExplorers?.[0]?.url + if (explorer) { + // many explorers use `/tx/` + return `${explorer.replace(/\/+$/, '')}/tx/${txHash}` + } + return +} + +export const createSdkFactory = ( + userAccount: PublicKey, + programId: PublicKey, + connectionFactory = createSolanaConnectionFactory() +) => { + // To create a EVM/Solana SDK factory we need to merge the EVM and the Solana factories into one + const evmSdkFactory = createOAppFactory(createConnectedContractFactory()) + const solanaSdkFactory = createOFTFactory( + // The first parameter to createOFTFactory is a user account factory + // + // This is a function that receives an OmniPoint ({ eid, address } object) + // and returns a user account to be used with that SDK. + // + // For our purposes this will always be the user account coming from the secret key passed in + () => userAccount, + // The second parameter is a program ID factory + // + // This is a function that receives an OmniPoint ({ eid, address } object) + // and returns a program ID to be used with that SDK. + // + // Since we only have one OFT deployed, this will always be the program ID passed as a CLI parameter. + // + // In situations where we might have multiple configs with OFTs using multiple program IDs, + // this function needs to decide which one to use. + () => programId, + // Last but not least the SDK will require a connection + connectionFactory + ) + + // the return value is an SDK factory that receives an OmniPoint and returns an SDK + return async (point: OmniPoint): Promise => { + if (endpointIdToChainType(point.eid) === ChainType.SOLANA) { + return solanaSdkFactory(point) + } else if (endpointIdToChainType(point.eid) === ChainType.EVM) { + return evmSdkFactory(point) + } else { + logger.error(`Unsupported chain type for EID ${point.eid}`) + throw new Error(`Unsupported chain type for EID ${point.eid}`) + } + } +} + +export { createSolanaSignerFactory } + +export function uint8ArrayToHex(uint8Array: Uint8Array, prefix = false): string { + const hexString = Buffer.from(uint8Array).toString('hex') + return prefix ? `0x${hexString}` : hexString +} + +function formatBigIntForDisplay(n: bigint) { + return n.toLocaleString().replace(/,/g, '_') +} + +export function isEmptyOptionsEvm(optionsHex?: string): boolean { + return !optionsHex || optionsHex === '0x' || optionsHex === '0x0003' // 0x0003 is an empty options type 3 +} + +export function isEmptyOptionsSolana(optionsBytes?: Uint8Array): boolean { + if (!optionsBytes) { + return true // Treat undefined or null as empty options + } + return Buffer.from(optionsBytes).toString('hex') === '0003' // empty options type 3 without 0x prefix +} + +export function decodeLzReceiveOptions(hex: string): string { + try { + // Handle empty/undefined values first + if (!hex || hex === '0x') return 'No options set' + const options = Options.fromOptions(hex) + const lzReceiveOpt = options.decodeExecutorLzReceiveOption() + return lzReceiveOpt + ? `gas: ${formatBigIntForDisplay(lzReceiveOpt.gas)} , value: ${formatBigIntForDisplay(lzReceiveOpt.value)} wei` + : 'No executor options' + } catch (e) { + return `Invalid options (${hex.slice(0, 12)}...)` + } +} + +export async function getSolanaUlnConfigPDAs( + remote: EndpointId, + connection: Connection, + ulnAddress: PublicKey, + oftStore: PublicKey +) { + const uln = new UlnProgram.Uln(new PublicKey(ulnAddress)) + const sendConfig = uln.getSendConfigState(connection, new PublicKey(oftStore), remote) + + const receiveConfig = uln.getReceiveConfigState(connection, new PublicKey(oftStore), remote) + + return await Promise.all([sendConfig, receiveConfig]) +} + +export enum SolanaTokenProgramType { + SPL = 'SPL', + Token2022 = 'Token2022', +} + +export function tokenProgramAddressToType(tokenProgramAddress: string | PublicKey): SolanaTokenProgramType { + const address = typeof tokenProgramAddress === 'string' ? new PublicKey(tokenProgramAddress) : tokenProgramAddress + const tokenProgramMap: Record = { + [TOKEN_PROGRAM_ID.toBase58()]: SolanaTokenProgramType.SPL, + } + const addressStr = address.toBase58() + const name = tokenProgramMap[addressStr] + if (!name) { + throw new Error(`Invalid token program address: ${addressStr}. Expected either SPL Token or Token2022.`) + } + return name +} + +type TokenMetadata = { + updateAuthority?: UmiPublicKey + isMutable?: boolean + name?: string + symbol?: string + uri?: string +} + +export async function getSolanaTokenMetadata( + umi: Umi, + mint: UmiPublicKey, + tokenProgramType: SolanaTokenProgramType +): Promise { + let response + switch (tokenProgramType) { + case SolanaTokenProgramType.SPL: + response = await safeFetchMetadataFromSeeds(umi, { mint }) + return { + updateAuthority: response?.updateAuthority, + isMutable: response?.isMutable, + name: response?.name, + symbol: response?.symbol, + uri: response?.uri, + } + default: + throw new Error(`Unsupported token program type: ${tokenProgramType}`) + } +} + +export { createLogger, DebugLogger, KnownErrors, KnownOutputs, KnownWarnings } from '@layerzerolabs/io-devtools' diff --git a/tasks/common/wire.ts b/tasks/common/wire.ts new file mode 100644 index 0000000..acb0e40 --- /dev/null +++ b/tasks/common/wire.ts @@ -0,0 +1,226 @@ +import { PublicKey } from '@solana/web3.js' +import { subtask, task } from 'hardhat/config' + +import { firstFactory } from '@layerzerolabs/devtools' +import { SUBTASK_LZ_SIGN_AND_SEND, types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat' +import { setTransactionSizeBuffer } from '@layerzerolabs/devtools-solana' +import { type LogLevel, createLogger } from '@layerzerolabs/io-devtools' +import { DebugLogger, KnownErrors } from '@layerzerolabs/io-devtools' +import { ChainType, endpointIdToChainType } from '@layerzerolabs/lz-definitions' +import { type IOApp, type OAppConfigurator, type OAppOmniGraph, configureOwnable } from '@layerzerolabs/ua-devtools' +import { + SUBTASK_LZ_OAPP_WIRE_CONFIGURE, + type SubtaskConfigureTaskArgs, + TASK_LZ_OAPP_WIRE, + TASK_LZ_OWNABLE_TRANSFER_OWNERSHIP, +} from '@layerzerolabs/ua-devtools-evm-hardhat' + +import { getSolanaDeployment, useWeb3Js } from '../solana' +import { findSolanaEndpointIdInGraph } from '../solana/utils' + +import { publicKey as publicKeyType } from './types' +import { + createSdkFactory, + createSolanaConnectionFactory, + createSolanaSignerFactory, + getSolanaUlnConfigPDAs, +} from './utils' + +import type { SignAndSendTaskArgs } from '@layerzerolabs/devtools-evm-hardhat/tasks' + +/** + * Additional CLI arguments for our custom wire task + */ +interface Args { + logLevel: LogLevel + multisigKey?: PublicKey + isSolanaInitConfig: boolean // For internal use only. This helps us to control which code runs depdending on whether the task ran is wire or init-config + oappConfig: string + internalConfigurator?: OAppConfigurator + dryRun?: boolean +} + +/** + * We extend the default wiring task to add functionality required by Solana + */ +task(TASK_LZ_OAPP_WIRE) + .addParam('multisigKey', 'The MultiSig key', undefined, publicKeyType, true) + // We use this argument to get around the fact that we want to both override the task action for the wiring task + // and wrap this task with custom configurators + // + // By default, this argument will be left empty and the default OApp configurator will be used. + // The tasks that are using custom configurators will override this argument with the configurator of their choice + .addParam('internalConfigurator', 'FOR INTERNAL USE ONLY', undefined, devtoolsTypes.fn, true) + .addParam('isSolanaInitConfig', 'FOR INTERNAL USE ONLY', undefined, devtoolsTypes.boolean, true) + .setAction(async (args: Args, hre, runSuper) => { + const logger = createLogger(args.logLevel) + + // + // + // ENVIRONMENT SETUP + // + // + + // The Solana transaction size estimation algorithm is not very accurate, so we increase its tolerance by 192 bytes + setTransactionSizeBuffer(192) + + // + // + // USER INPUT + // + // + + // construct the user's keypair via the SOLANA_PRIVATE_KEY env var + const keypair = (await useWeb3Js()).web3JsKeypair // note: this can be replaced with getSolanaKeypair() if we are okay to export that + const userAccount = keypair.publicKey + + const solanaEid = await findSolanaEndpointIdInGraph(hre, args.oappConfig) + const solanaDeployment = getSolanaDeployment(solanaEid) + + // Then we grab the programId from the args + const programId = new PublicKey(solanaDeployment.programId) + + // TODO: refactor to instead use a function such as verifySolanaDeployment that also checks for oftStore key + if (!programId) { + logger.error('Missing programId in solana deployment') + return + } + const configurator = args.internalConfigurator + + // + // + // TOOLING SETUP + // + // + + // We'll need a connection factory to be able to query the Solana network + // + // If you haven't set RPC_URL_SOLANA and/or RPC_URL_SOLANA_TESTNET environment variables, + // the factory will use the default public RPC URLs + const connectionFactory = createSolanaConnectionFactory() + + // We'll need SDKs to be able to use devtools + const sdkFactory = createSdkFactory(userAccount, programId, connectionFactory) + + // We'll also need a signer factory + const solanaSignerFactory = createSolanaSignerFactory(keypair, connectionFactory, args.multisigKey) + + // + // + // SUBTASK OVERRIDES + // + // + + // We'll need to override the default implementation of the configure subtask + // (responsible for collecting the on-chain configuration of the contracts + // and coming up with the transactions that need to be sent to the network) + // + // The only thing we are overriding is the sdkFactory parameter - we supply the SDK factory we created above + subtask( + SUBTASK_LZ_OAPP_WIRE_CONFIGURE, + 'Configure OFT', + async (subtaskArgs: SubtaskConfigureTaskArgs, _hre, runSuper) => { + // start of pre-wiring checks. we only do this when the current task is wire. if the current task is init-config, we shouldn't run this. + if (!args.isSolanaInitConfig && !args.dryRun) { + logger.verbose('Running pre-wiring checks...') + const { graph } = subtaskArgs + for (const connection of graph.connections) { + // check if from Solana Endpoint + if (endpointIdToChainType(connection.vector.from.eid) === ChainType.SOLANA) { + if (connection.config?.sendLibrary) { + // Check if this is BlockedMessageLib - if so, skip the config checks + const BLOCKED_MESSAGE_LIB_SOLANA_MAINNET = + '2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB' + const BLOCKED_MESSAGE_LIB_SOLANA_TESTNET = + '2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB' + const sendLibraryAddress = connection.config.sendLibrary + + // Check if this is a BlockedMessageLib address for either mainnet or testnet + if ( + sendLibraryAddress === BLOCKED_MESSAGE_LIB_SOLANA_MAINNET || + sendLibraryAddress === BLOCKED_MESSAGE_LIB_SOLANA_TESTNET + ) { + logger.verbose( + `Skipping ULN config checks for BlockedMessageLib on ${connection.vector.from.eid}` + ) + continue + } + + logger.verbose(`Send library found. Checking if ULN configs have been initialized...`) + + try { + // Use the SDK to check if configs exist + const [sendConfig, receiveConfig] = await getSolanaUlnConfigPDAs( + connection.vector.to.eid, + await connectionFactory(connection.vector.from.eid), + new PublicKey(connection.config.sendLibrary), + new PublicKey(connection.vector.from.address) + ) + + logger.verbose( + `ULN configs checked successfully for ${connection.vector.from.eid} -> ${connection.vector.to.eid}` + ) + } catch (error) { + logger.verbose(`Error checking ULN configs: ${error}`) + DebugLogger.printErrorAndFixSuggestion( + KnownErrors.ULN_INIT_CONFIG_SKIPPED, + `ULN configs on ${connection.vector.from.eid} not initialized for remote ${connection.vector.to.eid}.` + ) + throw new Error('ULN configs not initialized. Please run init-config task first.') + } + } else { + logger.debug( + `No sendLibrary found in connection config for ${connection.vector.from.eid} -> ${connection.vector.to.eid}` + ) + } + } + } + // end of pre-wiring checks + } + + return runSuper({ + ...subtaskArgs, + configurator: configurator ?? subtaskArgs.configurator, + sdkFactory, + graph: { + ...subtaskArgs.graph, + contracts: subtaskArgs.graph.contracts.filter((contract) => { + const chainType = endpointIdToChainType(contract.point.eid) + return chainType !== ChainType.APTOS && chainType !== ChainType.INITIA + }), + connections: subtaskArgs.graph.connections.filter((connection) => { + const fromChainType = endpointIdToChainType(connection.vector.from.eid) + return fromChainType !== ChainType.APTOS && fromChainType !== ChainType.INITIA + }), + }, + }) + } + ) + + // We'll also need to override the default implementation of the signAndSend subtask + // (responsible for sending transactions to the network and waiting for confirmations) + // + // In this subtask we need to override the createSigner function so that it uses the Solana + // signer for all Solana transactions + subtask(SUBTASK_LZ_SIGN_AND_SEND, 'Sign OFT transactions', (args: SignAndSendTaskArgs, _hre, runSuper) => + runSuper({ + ...args, + createSigner: firstFactory(solanaSignerFactory, args.createSigner), + }) + ) + + return runSuper(args) + }) + +// We'll change the default ownership transfer task to use our wire implementation +// +// The reason for this is the fact that the ownership transfer task has a deficiency +// and that is the fact that it does not support a custom SDK factory as of yet +// +// The two tasks are identical and the only drawback of this approach is the fact +// that the logs will say "Wiring OApp" instead of "Transferring ownership" +task(TASK_LZ_OWNABLE_TRANSFER_OWNERSHIP) + .addParam('multisigKey', 'The MultiSig key', undefined, publicKeyType, true) + .setAction(async (args: Args, hre) => { + return hre.run(TASK_LZ_OAPP_WIRE, { ...args, internalConfigurator: configureOwnable }) + }) diff --git a/tasks/evm/sendEvm.ts b/tasks/evm/sendEvm.ts new file mode 100644 index 0000000..f4f2129 --- /dev/null +++ b/tasks/evm/sendEvm.ts @@ -0,0 +1,143 @@ +import bs58 from 'bs58' +import { BigNumber, ContractTransaction } from 'ethers' +import { parseUnits } from 'ethers/lib/utils' +import { HardhatRuntimeEnvironment } from 'hardhat/types' + +import { makeBytes32 } from '@layerzerolabs/devtools' +import { createGetHreByEid } from '@layerzerolabs/devtools-evm-hardhat' +import { createLogger, promptToContinue } from '@layerzerolabs/io-devtools' +import { ChainType, endpointIdToChainType, endpointIdToNetwork } from '@layerzerolabs/lz-definitions' + +import layerzeroConfig from '../../layerzero.testnet.config' +import { SendResult } from '../common/types' +import { DebugLogger, KnownErrors, MSG_TYPE, isEmptyOptionsEvm } from '../common/utils' +import { getLayerZeroScanLink } from '../solana' +const logger = createLogger() +export interface EvmArgs { + srcEid: number + dstEid: number + amount: string + to: string + minAmount?: string + extraOptions?: string + composeMsg?: string + oftAddress?: string +} +export async function sendEvm( + { srcEid, dstEid, amount, to, minAmount, extraOptions, composeMsg, oftAddress }: EvmArgs, + hre: HardhatRuntimeEnvironment +): Promise { + if (endpointIdToChainType(srcEid) !== ChainType.EVM) { + throw new Error(`non-EVM srcEid (${srcEid}) not supported here`) + } + const getHreByEid = createGetHreByEid(hre) + let srcEidHre: HardhatRuntimeEnvironment + try { + srcEidHre = await getHreByEid(srcEid) + } catch (error) { + DebugLogger.printErrorAndFixSuggestion( + KnownErrors.ERROR_GETTING_HRE, + `For network: ${endpointIdToNetwork(srcEid)}, OFT: ${oftAddress}` + ) + throw error + } + + const { deployer } = await hre.getNamedAccounts() + const signer = await hre.ethers.getSigner(deployer) + + // 1️⃣ resolve the OFT wrapper address + let wrapperAddress: string + if (oftAddress) { + wrapperAddress = oftAddress + } else { + const { contracts } = typeof layerzeroConfig === 'function' ? await layerzeroConfig() : layerzeroConfig + const wrapper = contracts.find((c) => c.contract.eid === srcEid) + if (!wrapper) throw new Error(`No config for EID ${srcEid}`) + wrapperAddress = wrapper.contract.contractName + ? (await srcEidHre.deployments.get(wrapper.contract.contractName)).address + : wrapper.contract.address! + } + + // 2️⃣ load OFT ABI + const oftArtifact = await srcEidHre.artifacts.readArtifact('WXRPMintBurnOFTAdapter') + const oft = await srcEidHre.ethers.getContractAt(oftArtifact.abi, wrapperAddress) // signer removed + + // 3️⃣ fetch the underlying ERC-20 + const underlying = await oft.token() + // 4️⃣ fetch decimals from the underlying token + const erc20 = await srcEidHre.ethers.getContractAt('WXRPToken', underlying) // signer removed + const decimals: number = await erc20.decimals() + // 5️⃣ normalize the user-supplied amount + const amountUnits: BigNumber = parseUnits(amount, decimals) + // Decide how to encode `to` based on target chain: + const dstChain = endpointIdToChainType(dstEid) + let toBytes: string + if (dstChain === ChainType.SOLANA) { + // Base58→32-byte buffer + toBytes = makeBytes32(bs58.decode(to)) + } else { + // hex string → Uint8Array → zero-pad to 32 bytes + toBytes = makeBytes32(to) + } + // 6️⃣ build sendParam and dispatch + const sendParam = { + dstEid, + to: toBytes, + amountLD: amountUnits.toString(), + minAmountLD: minAmount ? parseUnits(minAmount, decimals).toString() : amountUnits.toString(), + extraOptions: extraOptions ? extraOptions.toString() : '0x', + composeMsg: composeMsg ? composeMsg.toString() : '0x', + oftCmd: '0x', + } + + // Check whether there are extra options or enforced options. If not, warn the user. + // Read on Message Options: https://docs.layerzero.network/v2/concepts/message-options + if (!extraOptions) { + try { + const enforcedOptions = composeMsg + ? await oft.enforcedOptions(dstEid, MSG_TYPE.SEND_AND_CALL) + : await oft.enforcedOptions(dstEid, MSG_TYPE.SEND) + + if (isEmptyOptionsEvm(enforcedOptions)) { + const proceed = await promptToContinue( + 'No extra options were included and OFT has no set enforced options. Your quote / send will most likely fail. Continue?' + ) + if (!proceed) { + throw new Error('Aborted due to missing options') + } + } + } catch (error) { + logger.debug(`Failed to check enforced options: ${error}`) + } + } + + // 6️⃣ Quote (MessagingFee = { nativeFee, lzTokenFee }) + logger.info('Quoting the native gas cost for the send transaction...') + let msgFee: { nativeFee: BigNumber; lzTokenFee: BigNumber } + try { + msgFee = await oft.quoteSend(sendParam, false) + } catch (error) { + DebugLogger.printErrorAndFixSuggestion( + KnownErrors.ERROR_QUOTING_NATIVE_GAS_COST, + `For network: ${endpointIdToNetwork(srcEid)}, OFT: ${oftAddress}` + ) + throw error + } + logger.info('Sending the transaction...') + let tx: ContractTransaction + try { + tx = await oft.send(sendParam, msgFee, signer.address, { + value: msgFee.nativeFee, + }) + } catch (error) { + DebugLogger.printErrorAndFixSuggestion( + KnownErrors.ERROR_SENDING_TRANSACTION, + `For network: ${endpointIdToNetwork(srcEid)}, OFT: ${oftAddress}` + ) + throw error + } + const receipt = await tx.wait() + const txHash = receipt.transactionHash + const scanLink = getLayerZeroScanLink(txHash, srcEid >= 40_000 && srcEid < 50_000) + return { txHash, scanLink } +} diff --git a/tasks/index.ts b/tasks/index.ts new file mode 100644 index 0000000..51d34a0 --- /dev/null +++ b/tasks/index.ts @@ -0,0 +1,14 @@ +import './common/config.get' +import './common/wire' +import './common/sendOFT' +import './solana/initConfig' +import './solana/createOFT' +import './solana/debug' +import './solana/setOFTConfig' +import './solana/helpers/burn' +import './solana/helpers/mint' +import './solana/helpers/blacklist' +import './solana/helpers/unblacklist' +import './solana/helpers/updateMetadata' +import './solana/helpers/setFreezeAuthority' +import './solana/helpers/setMetadataAuthority' diff --git a/tasks/solana/createOFT.ts b/tasks/solana/createOFT.ts new file mode 100644 index 0000000..a9c8f56 --- /dev/null +++ b/tasks/solana/createOFT.ts @@ -0,0 +1,400 @@ +import { + CreateV1InstructionAccounts, + CreateV1InstructionArgs, + TokenStandard, + createV1, + mintV1, +} from '@metaplex-foundation/mpl-token-metadata' +import { AuthorityType, setAuthority } from '@metaplex-foundation/mpl-toolbox' +import { + createNoopSigner, + createSignerFromKeypair, + percentAmount, + publicKey, + transactionBuilder, +} from '@metaplex-foundation/umi' +import { fromWeb3JsPublicKey, toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters' +import { TOKEN_PROGRAM_ID } from '@solana/spl-token' +import { PublicKey } from '@solana/web3.js' +import bs58 from 'bs58' +import { task } from 'hardhat/config' + +import { formatTokenAmount } from '@layerzerolabs/devtools' +import { types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat' +import { assertAccountInitialized, localDecimalsToMaxWholeTokens } from '@layerzerolabs/devtools-solana' +import { promptToContinue } from '@layerzerolabs/io-devtools' +import { EndpointId } from '@layerzerolabs/lz-definitions' +import { OFT_DECIMALS as DEFAULT_SHARED_DECIMALS, oft } from '@layerzerolabs/oft-v2-solana-sdk' + +import { checkMultisigSigners, createMintAuthorityMultisig } from './multisig' + +import { + TransactionType, + addComputeUnitInstructions, + deriveConnection, + deriveKeys, + getExplorerTxLink, + saveSolanaDeployment, +} from './index' + +const DEFAULT_LOCAL_DECIMALS = 9 + +interface CreateOFTTaskArgs { + /** + * The initial supply to mint on solana. + */ + amount: number + + /** + * The endpoint ID for the Solana network. + */ + eid: EndpointId + + /** + * The number of decimal places to use for the token. + */ + localDecimals: number + + /** + * OFT shared decimals. + */ + sharedDecimals: number + + /** + * The optional token mint ID, for Mint-And-Burn-Adapter only. + */ + mint?: string + + /** + * The name of the token. + */ + name: string + + /** + * The program ID for the OFT program. + */ + programId: string + + /** + * The seller fee basis points for Metaplex's Token Metadata standard (not enforced on-chain). This is not related to OFT fees. + */ + sellerFeeBasisPoints: number + + /** + * The symbol of the token. + */ + symbol: string + + /** + * Whether the token metadata is mutable. + */ + tokenMetadataIsMutable: boolean + + /** + * The CSV list of additional minters. + */ + additionalMinters?: string[] + + /** + * The token program ID, for Mint-And-Burn-Adapter only. + */ + tokenProgram: string + + /** + * If you plan to have only the OFTStore and no additional minters. This is not reversible, and will result in + * losing the ability to mint new tokens for everything but the OFTStore. You should really be intentional about + * using this flag, as it is not reversible. + */ + onlyOftStore: boolean + + /** + * The URI for the token metadata. + */ + uri: string + + computeUnitPriceScaleFactor: number + + /** + * The freeze authority address (only supported in onlyOftStore mode). + */ + freezeAuthority?: string + + /** + * Whether to continue without confirmation. + */ + ci: boolean +} + +// Define a Hardhat task for creating OFT on Solana +// * Create the SPL Multisig account for mint authority +// * Mint the new SPL Token +// * Initialize the OFT Store account +// * Set the mint authority to the multisig account. If not in only OFT Store mode, also set the freeze authority to the multisig account. +// Note: Only supports SPL Token Standard. +task('lz:oft:solana:create', 'Mints new SPL Token and creates new OFT Store account') + .addOptionalParam('amount', 'The initial supply to mint on solana', undefined, devtoolsTypes.int) + .addParam('eid', 'Solana mainnet (30168) or testnet (40168)', undefined, devtoolsTypes.eid) + .addOptionalParam('localDecimals', 'Token local decimals (default=9)', DEFAULT_LOCAL_DECIMALS, devtoolsTypes.int) + .addOptionalParam('sharedDecimals', 'OFT shared decimals (default=6)', DEFAULT_SHARED_DECIMALS, devtoolsTypes.int) + .addParam('name', 'Token Name', 'MockOFT', devtoolsTypes.string) + .addOptionalParam('mint', 'The Token mint public key (used for MABA only)', undefined, devtoolsTypes.string) + .addParam('programId', 'The OFT Program id') + .addParam('sellerFeeBasisPoints', 'Seller fee basis points', 0, devtoolsTypes.int) // Note: This is for Metaplex's Token Metadata standard (not enforced on-chain). This is not related to OFT fees. + .addParam('symbol', 'Token Symbol', 'MOFT', devtoolsTypes.string) + .addParam('tokenMetadataIsMutable', 'Token metadata is mutable', true, devtoolsTypes.boolean) + .addParam('additionalMinters', 'Comma-separated list of additional minters', undefined, devtoolsTypes.csv, true) + .addOptionalParam( + 'onlyOftStore', + 'If you plan to have only the OFTStore and no additional minters. This is not reversible, and will result in losing the ability to mint new tokens by everything but the OFTStore.', + false, + devtoolsTypes.boolean + ) + .addParam( + 'tokenProgram', + 'The Token Program public key (used for MABA only)', + TOKEN_PROGRAM_ID.toBase58(), + devtoolsTypes.string + ) + .addParam('uri', 'URI for token metadata', '', devtoolsTypes.string) + .addParam( + 'freezeAuthority', + 'The Freeze Authority address (only in onlyOftStore mode)', + '', + devtoolsTypes.string, + true + ) + .addParam('computeUnitPriceScaleFactor', 'The compute unit price scale factor', 4, devtoolsTypes.float, true) + .addFlag('ci', 'Continue without confirmation') + .setAction( + async ({ + amount, + eid, + localDecimals: decimals, + sharedDecimals, + mint: mintStr, + name, + programId: programIdStr, + sellerFeeBasisPoints, + symbol, + tokenMetadataIsMutable: isMutable, + additionalMinters: additionalMintersAsStrings, + onlyOftStore, + tokenProgram: tokenProgramStr, + uri, + freezeAuthority: freezeAuthorityStr, + computeUnitPriceScaleFactor, + ci, + }: CreateOFTTaskArgs) => { + const isMABA = !!mintStr // the difference between MABA and OFT Adapter is that MABA uses mint/burn mechanism whereas OFT Adapter uses lock/unlock mechanism + if (tokenProgramStr !== TOKEN_PROGRAM_ID.toBase58() && !isMABA) { + throw new Error('Non-Mint-And-Burn-Adapter does not support custom token programs') + } + if (isMABA && amount) { + throw new Error('Mint-And-Burn-Adapter does not support minting tokens') + } + if (decimals < sharedDecimals) { + throw new Error('Solana token local decimals must be greater than or equal to OFT shared decimals') + } + const tokenProgramId = publicKey(tokenProgramStr) + const { connection, umi, umiWalletKeyPair, umiWalletSigner } = await deriveConnection(eid) + const { programId, lockBox, escrowPK, oftStorePda, eddsa } = deriveKeys(programIdStr) + + const additionalMinters = additionalMintersAsStrings?.map((minter) => new PublicKey(minter)) ?? [] + + // BOF: Validate combination of parameters + if (!additionalMintersAsStrings) { + if (!onlyOftStore) { + throw new Error( + 'If you want to proceed with only the OFT Store having the ability to mint, please specify --only-oft-store true. Note that this also means the Freeze Authority will be immediately renounced, unless --freeze-authority is specified.' + ) + } + } + + if (freezeAuthorityStr && !onlyOftStore) { + throw new Error('`--freeze-authority` is only supported in `--only-oft-store true` mode') + } + + if (onlyOftStore && additionalMintersAsStrings && additionalMintersAsStrings?.length > 0) { + throw new Error( + 'Cannot set both --only-oft-store and --additional-minters; these options are mutually exclusive.' + ) + } + + if (onlyOftStore && !ci) { + const continueWithOnlyOftStore = await promptToContinue( + `You have chosen \`--only-oft-store true\`. This means that only the OFT Store will be able to mint new tokens${freezeAuthorityStr ? '' : ' and that the Freeze Authority will be immediately renounced'}. Continue?` + ) + if (!continueWithOnlyOftStore) { + return + } + } + + // EOF: Validate combination of parameters + + const maxSupplyRaw = localDecimalsToMaxWholeTokens(decimals) + const { full, compact } = formatTokenAmount(maxSupplyRaw) + const maxSupplyStatement = `You have chosen ${decimals} local decimals. The maximum supply of your Solana OFT token will be ${full} (~${compact}).\n` + const confirmMaxSupply = await promptToContinue(maxSupplyStatement) + if (!confirmMaxSupply) { + return + } + + let mintAuthorityPublicKey: PublicKey = toWeb3JsPublicKey(oftStorePda) // we default to the OFT Store as the Mint Authority when there are no additional minters + + if (additionalMintersAsStrings) { + // we only need a multisig when we have additional minters + mintAuthorityPublicKey = await createMintAuthorityMultisig( + connection, + umi, + eid, + umiWalletSigner, + toWeb3JsPublicKey(oftStorePda), + toWeb3JsPublicKey(tokenProgramId), // Only configurable for MABA + additionalMinters, + computeUnitPriceScaleFactor + ) + console.log(`created SPL multisig @ ${mintAuthorityPublicKey.toBase58()}`) + await checkMultisigSigners(connection, mintAuthorityPublicKey, [ + toWeb3JsPublicKey(oftStorePda), + ...additionalMinters, + ]) + } + + // BOF: determine freeze authority + // important: this must be placed after multisig creation + let freezeAuthority: PublicKey | null = null + if (freezeAuthorityStr && onlyOftStore) { + freezeAuthority = new PublicKey(freezeAuthorityStr) // will error if invalid + const continueFreezeAuthority = await promptToContinue( + `Freeze Authority will be set to ${freezeAuthority.toBase58()}. Continue?` + ) + if (!continueFreezeAuthority) { + return + } + } else { + // onlyOftStore mode: if freezeAuthority is not provided, we set it to null + // additional minters mode: set freezeAuthority to mintAuthorityPublicKey (SPL Multisig) + freezeAuthority = onlyOftStore ? null : mintAuthorityPublicKey + } + // EOF: determine freeze authority + + const mint = isMABA + ? createNoopSigner(publicKey(mintStr)) + : createSignerFromKeypair(umi, eddsa.generateKeypair()) + const isTestnet = eid == EndpointId.SOLANA_V2_TESTNET + if (!isMABA) { + const createV1Args: CreateV1InstructionAccounts & CreateV1InstructionArgs = { + mint, + name, + symbol, + decimals, + uri, + isMutable, + sellerFeeBasisPoints: percentAmount(sellerFeeBasisPoints), + authority: umiWalletSigner, // authority is transferred later + tokenStandard: TokenStandard.Fungible, + } + let txBuilder = transactionBuilder().add(createV1(umi, createV1Args)) + if (amount) { + // recreate txBuilder since it is immutable + txBuilder = transactionBuilder() + .add(txBuilder) + .add( + mintV1(umi, { + ...createV1Args, + mint: publicKey(createV1Args.mint), + authority: umiWalletSigner, + amount, + tokenOwner: umiWalletSigner.publicKey, + tokenStandard: TokenStandard.Fungible, + }) + ) + } + txBuilder = await addComputeUnitInstructions( + connection, + umi, + eid, + txBuilder, + umiWalletSigner, + computeUnitPriceScaleFactor, + TransactionType.CreateToken + ) + const createTokenTx = await txBuilder.sendAndConfirm(umi) + await assertAccountInitialized(connection, toWeb3JsPublicKey(mint.publicKey)) + console.log(`createTokenTx: ${getExplorerTxLink(bs58.encode(createTokenTx.signature), isTestnet)}`) + } + + const lockboxSigner = createSignerFromKeypair({ eddsa: eddsa }, lockBox) + let txBuilder = transactionBuilder().add( + oft.initOft( + { + payer: umiWalletSigner, + admin: umiWalletKeyPair.publicKey, + mint: mint.publicKey, + escrow: lockboxSigner, + }, + oft.types.OFTType.Native, + sharedDecimals, + { + oft: programId, + token: tokenProgramId, + } + ) + ) + txBuilder = await addComputeUnitInstructions( + connection, + umi, + eid, + txBuilder, + umiWalletSigner, + computeUnitPriceScaleFactor, + TransactionType.InitOft + ) + const { signature } = await txBuilder.sendAndConfirm(umi) + console.log(`initOftTx: ${getExplorerTxLink(bs58.encode(signature), isTestnet)}`) + + if (!isMABA) { + let txBuilder = transactionBuilder() + .add( + setAuthority(umi, { + owned: mint.publicKey, + owner: umiWalletSigner, + newAuthority: fromWeb3JsPublicKey(mintAuthorityPublicKey), + authorityType: AuthorityType.MintTokens, + }) + ) + .add( + setAuthority(umi, { + owned: mint.publicKey, + owner: umiWalletSigner, + newAuthority: freezeAuthority ? fromWeb3JsPublicKey(freezeAuthority) : null, + authorityType: AuthorityType.FreezeAccount, + }) + ) + txBuilder = await addComputeUnitInstructions( + connection, + umi, + eid, + txBuilder, + umiWalletSigner, + computeUnitPriceScaleFactor, + TransactionType.SetAuthority + ) + const { signature } = await txBuilder.sendAndConfirm(umi) + console.log(`setAuthorityTx: ${getExplorerTxLink(bs58.encode(signature), isTestnet)}`) + } + if (isMABA) { + console.log( + `Please note that for MABA mode, you must carry out the change of Mint Authority before making any cross-chain transfers. For more details: https://github.com/LayerZero-Labs/devtools/tree/main/examples/oft-solana#for-oft-mint-and-burn-adapter-maba` + ) + } + saveSolanaDeployment( + eid, + programIdStr, + mint.publicKey, + mintAuthorityPublicKey.toBase58(), + escrowPK, + oftStorePda + ) + } + ) diff --git a/tasks/solana/debug.ts b/tasks/solana/debug.ts new file mode 100644 index 0000000..6ab198d --- /dev/null +++ b/tasks/solana/debug.ts @@ -0,0 +1,502 @@ +import { fetchMint } from '@metaplex-foundation/mpl-toolbox' +import { PublicKey as UmiPublicKey, publicKey, unwrapOption } from '@metaplex-foundation/umi' +import { fromWeb3JsPublicKey, toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters' +import { Keypair, PublicKey } from '@solana/web3.js' +import { task } from 'hardhat/config' + +import { OmniPoint, denormalizePeer } from '@layerzerolabs/devtools' +import { types } from '@layerzerolabs/devtools-evm-hardhat' +import { isSquadsV4Vault } from '@layerzerolabs/devtools-solana' +import { EndpointId, getNetworkForChainId } from '@layerzerolabs/lz-definitions' +import { EndpointPDADeriver, EndpointProgram } from '@layerzerolabs/lz-solana-sdk-v2' +import { EndpointProgram as EndpointProgramUmi } from '@layerzerolabs/lz-solana-sdk-v2/umi' +import { IMetadata, defaultFetchMetadata } from '@layerzerolabs/metadata-tools' +import { OftPDA, oft } from '@layerzerolabs/oft-v2-solana-sdk' +import { EndpointV2 } from '@layerzerolabs/protocol-devtools-solana' + +import { getSolanaReceiveConfig, getSolanaSendConfig } from '../common/taskHelper' +import { + DebugLogger, + SolanaTokenProgramType, + createSolanaConnectionFactory, + decodeLzReceiveOptions, + getSolanaTokenMetadata, + tokenProgramAddressToType, + uint8ArrayToHex, +} from '../common/utils' + +import { deriveConnection, getSolanaDeployment } from './index' + +const DEBUG_ACTIONS = { + OFT_STORE: 'oft-store', + GET_ADMIN: 'admin', + GET_DELEGATE: 'delegate', + CHECKS: 'checks', + GET_TOKEN: 'token', + GET_PEERS: 'peers', + RATE_LIMITS: 'rate-limits', +} + +/** + * Get the OFTStore account from the task arguments, the deployment file, or throw an error. + * @param {EndpointId} eid + * @param {string} oftStore + */ +const getOftStore = (eid: EndpointId, oftStore?: string) => publicKey(oftStore ?? getSolanaDeployment(eid).oftStore) + +function getChainKeyForEid(metadata: IMetadata, eid: number): string { + const eidStr = String(eid) + for (const objectKey in metadata) { + const entry = metadata[objectKey] + if (typeof entry?.deployments !== 'undefined') { + for (const deployment of entry.deployments) { + if (deployment.eid === eidStr) { + return deployment.chainKey + } + } + } + } + throw new Error(`Can't find chainKey for eid: "${eid}".`) +} + +function formatDvnAddresses(addresses: string[], metadata?: IMetadata, chainKey?: string): string { + const dvnMap = (chainKey && metadata ? metadata[chainKey]?.dvns : undefined) as + | Record + | undefined + return addresses.map((addr) => dvnMap?.[addr]?.canonicalName ?? addr).join(', ') +} + +type DebugTaskArgs = { + eid: EndpointId + oftStore?: string + endpoint: string + dstEids: EndpointId[] + action?: string +} + +task('lz:oft:solana:debug', 'Manages OFTStore and OAppRegistry information') + .addParam( + 'eid', + 'Solana mainnet (30168) or testnet (40168). Defaults to mainnet.', + EndpointId.SOLANA_V2_MAINNET, + types.eid + ) + .addParam( + 'oftStore', + 'The OFTStore public key. Derived from deployments if not provided.', + undefined, + types.string, + true + ) + .addParam('endpoint', 'The Endpoint public key', EndpointProgram.PROGRAM_ID.toBase58(), types.string) + .addOptionalParam('dstEids', 'Destination eids to check (comma-separated list)', [], types.csv) + .addOptionalParam( + 'action', + `The action to perform: ${Object.keys(DEBUG_ACTIONS).join(', ')} (defaults to all)`, + undefined, + types.string + ) + .setAction(async (taskArgs: DebugTaskArgs) => { + const { eid, oftStore: oftStoreArg, endpoint, dstEids, action } = taskArgs + const { umi, connection } = await deriveConnection(eid, true) + const oftStore = getOftStore(eid, oftStoreArg) + const metadata = await defaultFetchMetadata() + const sourceChainKey = getChainKeyForEid(metadata, eid) + + let oftStoreInfo + try { + oftStoreInfo = await oft.accounts.fetchOFTStore(umi, oftStore) + } catch (e) { + console.error(`Failed to fetch OFTStore at ${oftStore.toString()}:`, e) + return + } + const nonceAccountChecksInfo: Partial< + Record + > = {} + + const mintAccount = await fetchMint(umi, publicKey(oftStoreInfo.tokenMint)) + const tokenProgramType = tokenProgramAddressToType(mintAccount.header.owner) + + const epDeriver = new EndpointPDADeriver(new PublicKey(endpoint)) + const [oAppRegistry] = epDeriver.oappRegistry(toWeb3JsPublicKey(oftStore)) + const oAppRegistryInfo = await EndpointProgram.accounts.OAppRegistry.fromAccountAddress( + connection, + oAppRegistry + ) + + if (!oAppRegistryInfo) { + console.warn('OAppRegistry info not found.') + return + } + + const oftDeriver = new OftPDA(oftStoreInfo.header.owner) + + const tokenMetadata = await getSolanaTokenMetadata(umi, publicKey(oftStoreInfo.tokenMint), tokenProgramType) + + const adminIsSquadsV4Vault = await isSquadsV4Vault(oftStoreInfo.admin) + const delegateIsSquadsV4Vault = await isSquadsV4Vault(oAppRegistryInfo?.delegate?.toBase58()) + + // Fetch program upgrade authority + let programUpgradeAuthority: PublicKey | null = null + try { + const targetProgramId = new PublicKey(oftStoreInfo.header.owner) + const programAccount = await connection.getAccountInfo(targetProgramId) + if (!programAccount?.data) { + programUpgradeAuthority = null + } else { + const programDataAddress = new PublicKey(programAccount.data.slice(4, 36)) + const programDataAccount = await connection.getAccountInfo(programDataAddress) + + // BPF Loader Upgradeable program data structure: + // Bytes 0-3: Program data discriminator (should be 3) + // Bytes 4-11: Slot (u64) + // Byte 12: Option discriminant (0 = None, 1 = Some) + // Bytes 13-44: Authority (32 bytes, if option = 1) + const hasAuthority = programDataAccount?.data && programDataAccount.data.length >= 13 && programDataAccount.data[12] === 1 + if (hasAuthority && programDataAccount.data.length >= 45) { + programUpgradeAuthority = new PublicKey(programDataAccount.data.slice(13, 45)) + } else { + programUpgradeAuthority = null + } + } + } catch (e) { + // Program might not be upgradeable or account might not exist + console.warn(`Could not fetch program upgrade authority: ${e}`) + programUpgradeAuthority = null + } + + const printOftStore = async () => { + DebugLogger.header('OFT Store Information') + DebugLogger.keyValue('OFT Program', oftStoreInfo.header.owner) + DebugLogger.keyValue('OFT Program Upgrade Authority', programUpgradeAuthority?.toBase58() ?? 'None (immutable)') + DebugLogger.keyValue('OFT Type', oft.types.OFTType[oftStoreInfo.oftType]) + DebugLogger.keyValue('OFT Admin', oftStoreInfo.admin) + DebugLogger.keyValue('Token Mint', oftStoreInfo.tokenMint) + DebugLogger.keyValue('Token Escrow', oftStoreInfo.tokenEscrow) + DebugLogger.keyValue('Endpoint Program', oftStoreInfo.endpointProgram) + DebugLogger.keyValue('Paused', oftStoreInfo.paused) + DebugLogger.keyValue('Pauser', unwrapOption(oftStoreInfo.pauser, () => 'None')) + DebugLogger.keyValue('Unpauser', unwrapOption(oftStoreInfo.unpauser, () => 'None')) + DebugLogger.separator() + } + + const printAdmin = async () => { + const admin = oftStoreInfo.admin + DebugLogger.keyValue('Admin', admin) + } + + const printDelegate = async () => { + const delegate = oAppRegistryInfo?.delegate?.toBase58() + DebugLogger.header('OApp Registry Information') + DebugLogger.keyValue('Delegate', delegate) + DebugLogger.separator() + } + + const printToken = async () => { + DebugLogger.header('Token Information') + DebugLogger.keyValue('Mint Address', oftStoreInfo.tokenMint) + DebugLogger.keyValue('Token Name', tokenMetadata?.name ?? 'N/A') + DebugLogger.keyValue('Token Symbol', tokenMetadata?.symbol ?? 'N/A') + DebugLogger.keyValue('Token URI', tokenMetadata?.uri ?? 'N/A') + DebugLogger.keyValue('Token Program', tokenProgramType) + DebugLogger.keyValue('Mint Authority', unwrapOption(mintAccount.mintAuthority)) + DebugLogger.keyValue( + 'Freeze Authority', + unwrapOption(mintAccount.freezeAuthority, () => 'None') + ) + DebugLogger.keyValue('Metadata Update Authority', tokenMetadata?.updateAuthority ?? 'N/A (no Metaplex Metadata)') + DebugLogger.keyValue('Metadata is mutable', tokenMetadata?.isMutable ?? 'N/A') + DebugLogger.separator() + } + + const printChecks = async () => { + const delegate = oAppRegistryInfo?.delegate?.toBase58() + + DebugLogger.header('Checks') + DebugLogger.keyValue('Admin (Owner) same as Delegate', oftStoreInfo.admin === delegate) + DebugLogger.keyValue( + 'Token Mint Authority is OFT Store', + unwrapOption(mintAccount.mintAuthority) === oftStore + ) + DebugLogger.keyValue('Admin is Squads V4 Vault', adminIsSquadsV4Vault) + DebugLogger.keyValue('Delegate is Squads V4 Vault', delegateIsSquadsV4Vault) + dstEids.map((dstEid) => { + DebugLogger.keyHeader(`Nonce Account Checks`) + const nonceAccountCheckInfo = nonceAccountChecksInfo[dstEid] + if (nonceAccountCheckInfo) { + const definedForDstEid = !!nonceAccountCheckInfo.data + DebugLogger.keyValue( + `Defined for ${dstEid} (${getNetworkForChainId(dstEid).chainName})`, + definedForDstEid, + 2 + ) + if (!definedForDstEid) { + console.warn( + `Expected Nonce Account to exist at ${nonceAccountCheckInfo.address.toString()} for destination ${dstEid} (${getNetworkForChainId(dstEid).chainName}).` + ) + } + } + }) + DebugLogger.separator() + } + + let peerConfigsCache: { + peerConfigs: UmiPublicKey[] + peerConfigInfos: Awaited> + endpointV2Sdk: EndpointV2 + } | null = null + const fetchPeerConfigsAndSdk = async () => { + if (peerConfigsCache) { + return peerConfigsCache + } + + const peerConfigs = dstEids.map((dstEid) => { + const peerConfig = oftDeriver.peer(oftStore, dstEid) + return publicKey(peerConfig) + }) + const mockKeypair = new Keypair() + const point: OmniPoint = { + eid, + address: oftStore.toString(), + } + const endpointV2Sdk = new EndpointV2( + await createSolanaConnectionFactory()(eid), + point, + mockKeypair.publicKey // doesn't matter as we are not sending transactions + ) + + const peerConfigInfos = await oft.accounts.safeFetchAllPeerConfig(umi, peerConfigs) + + peerConfigsCache = { peerConfigs, peerConfigInfos, endpointV2Sdk } + return peerConfigsCache + } + + const printPeerConfigs = async () => { + const { peerConfigs, peerConfigInfos, endpointV2Sdk } = await fetchPeerConfigsAndSdk() + + DebugLogger.header('Peer Configurations') + for (let index = 0; index < dstEids.length; index++) { + const dstEid = dstEids[index] + const info = peerConfigInfos[index] + const network = getNetworkForChainId(dstEid) + const oAppReceiveConfig = await getSolanaReceiveConfig(endpointV2Sdk, dstEid, oftStore) + const oAppSendConfig = await getSolanaSendConfig(endpointV2Sdk, dstEid, oftStore) + // Show the chain info + DebugLogger.header(`${dstEid} (${network.chainName})`) + + if (info) { + // nonce account + const nonceAccount = epDeriver.nonce(toWeb3JsPublicKey(oftStore), dstEid, info.peerAddress)[0] + const nonceAccountInfo = await EndpointProgramUmi.accounts.fetchNonce( + umi, + fromWeb3JsPublicKey(nonceAccount) + ) + nonceAccountChecksInfo[dstEid] = { + data: nonceAccountInfo, + address: fromWeb3JsPublicKey(nonceAccount), + } + // Existing PeerConfig info + DebugLogger.keyValue('PeerConfig Account', peerConfigs[index].toString()) + DebugLogger.keyValue('Peer Address', denormalizePeer(info.peerAddress, dstEid)) + DebugLogger.keyValue('Nonce Account', nonceAccount.toString()) + DebugLogger.keyHeader('Enforced Options') + DebugLogger.keyValue( + 'Send', + decodeLzReceiveOptions(uint8ArrayToHex(info.enforcedOptions.send, true)), + 2 + ) + DebugLogger.keyValue( + 'SendAndCall', + decodeLzReceiveOptions(uint8ArrayToHex(info.enforcedOptions.sendAndCall, true)), + 2 + ) + + printOAppReceiveConfigs(oAppReceiveConfig, network.chainName, metadata, sourceChainKey) + printOAppSendConfigs(oAppSendConfig, network.chainName, metadata, sourceChainKey) + } else { + // No PeerConfig account + console.log(`No PeerConfig account found for ${dstEid} (${network.chainName}).`) + } + + DebugLogger.separator() + } + } + + const printRateLimits = async () => { + const { peerConfigInfos } = await fetchPeerConfigsAndSdk() + + DebugLogger.header('Rate Limits') + + const sourceNetwork = getNetworkForChainId(eid) + + for (let index = 0; index < dstEids.length; index++) { + const dstEid = dstEids[index] + const info = peerConfigInfos[index] + const network = getNetworkForChainId(dstEid) + + DebugLogger.header(`${dstEid} (${network.chainName})`) + + if (info) { + const { outboundRateLimiter, inboundRateLimiter } = info + printRateLimitsForPeer( + outboundRateLimiter, + inboundRateLimiter, + sourceNetwork.chainName, + network.chainName + ) + } else { + DebugLogger.keyValue('PeerConfig', 'Not found', 1) + } + + DebugLogger.separator() + } + } + if (action) { + switch (action) { + case DEBUG_ACTIONS.OFT_STORE: + await printOftStore() + break + case DEBUG_ACTIONS.GET_ADMIN: + await printAdmin() + break + case DEBUG_ACTIONS.GET_DELEGATE: + await printDelegate() + break + case DEBUG_ACTIONS.CHECKS: + await printChecks() + break + case DEBUG_ACTIONS.GET_TOKEN: + await printToken() + break + case DEBUG_ACTIONS.GET_PEERS: + await printPeerConfigs() + break + case DEBUG_ACTIONS.RATE_LIMITS: + await printRateLimits() + break + default: + console.error(`Invalid action specified. Use any of ${Object.keys(DEBUG_ACTIONS)}.`) + } + } else { + const tasks = [printOftStore(), printDelegate(), printToken()] + if (dstEids.length > 0) tasks.push(printPeerConfigs()) + await Promise.all(tasks) + // printChecks might depend on other tasks, so we don't add it to the tasks array + await printChecks() + } + }) + +function printOAppReceiveConfigs( + oAppReceiveConfig: Awaited>, + peerChainName: string, + metadata?: IMetadata, + chainKey?: string +) { + const oAppReceiveConfigIndexesToKeys: Record = { + 0: 'receiveLibrary', + 1: 'receiveUlnConfig', + 2: 'receiveLibraryTimeoutConfig', + } + + if (!oAppReceiveConfig) { + console.log('No receive configs found.') + return + } + + DebugLogger.keyValue(`Receive Configs (${peerChainName} to solana)`, '') + for (let i = 0; i < oAppReceiveConfig.length; i++) { + const item = oAppReceiveConfig[i] + if (typeof item === 'object' && item !== null) { + // Print each property in the object + DebugLogger.keyValue(`${oAppReceiveConfigIndexesToKeys[i]}`, '', 2) + for (const [propKey, propVal] of Object.entries(item)) { + const valueDisplay = + (propKey === 'requiredDVNs' || propKey === 'optionalDVNs') && Array.isArray(propVal) + ? formatDvnAddresses(propVal as string[], metadata, chainKey) + : String(propVal) + DebugLogger.keyValue(`${propKey}`, valueDisplay, 3) + } + } else { + // Print a primitive (string, number, etc.) + DebugLogger.keyValue(`${oAppReceiveConfigIndexesToKeys[i]}`, String(item), 2) + } + } +} + +function printOAppSendConfigs( + oAppSendConfig: Awaited>, + peerChainName: string, + metadata?: IMetadata, + chainKey?: string +) { + const sendOappConfigIndexesToKeys: Record = { + 0: 'sendLibrary', + 1: 'sendUlnConfig', + 2: 'sendExecutorConfig', + } + + if (!oAppSendConfig) { + console.log('No send configs found.') + return + } + + DebugLogger.keyValue(`Send Configs (solana to ${peerChainName})`, '') + for (let i = 0; i < oAppSendConfig.length; i++) { + const item = oAppSendConfig[i] + if (typeof item === 'object' && item !== null) { + DebugLogger.keyValue(`${sendOappConfigIndexesToKeys[i]}`, '', 2) + for (const [propKey, propVal] of Object.entries(item)) { + const valueDisplay = + (propKey === 'requiredDVNs' || propKey === 'optionalDVNs') && Array.isArray(propVal) + ? formatDvnAddresses(propVal as string[], metadata, chainKey) + : String(propVal) + DebugLogger.keyValue(`${propKey}`, valueDisplay, 3) + } + } else { + DebugLogger.keyValue(`${sendOappConfigIndexesToKeys[i]}`, String(item), 2) + } + } +} + +type RateLimiter = { + __option: 'Some' | 'None' + value?: { + capacity: bigint + tokens: bigint + refillPerSecond: bigint + lastRefillTime: bigint + } +} + +function formatUnixSecondsToUtc(secs: bigint): string { + const millis = Number(secs) * 1000 + const iso = new Date(millis).toISOString() + return iso.replace('T', ' ').replace('.000Z', ' UTC') +} + +function printSingleRateLimiter(label: string, limiter: RateLimiter | null | undefined) { + DebugLogger.keyValue(label, '', 1) + + if (!limiter || limiter.__option !== 'Some' || !limiter.value) { + DebugLogger.keyValue('status', 'None', 2) + return + } + + const { capacity, tokens, refillPerSecond, lastRefillTime } = limiter.value + + DebugLogger.keyValue('capacity', String(capacity), 2) + DebugLogger.keyValue('tokens (available allowance)', String(tokens), 2) + DebugLogger.keyValue('refillPerSecond', String(refillPerSecond), 2) + DebugLogger.keyValue('lastRefillTime', formatUnixSecondsToUtc(lastRefillTime), 2) +} + +function printRateLimitsForPeer( + outboundRateLimiter: RateLimiter | null | undefined, + inboundRateLimiter: RateLimiter | null | undefined, + sourceChainName: string, + destinationChainName: string +) { + DebugLogger.keyValue('Rate Limits', '') + printSingleRateLimiter(`Outbound (${sourceChainName} to ${destinationChainName})`, outboundRateLimiter) + printSingleRateLimiter(`Inbound (${destinationChainName} to ${sourceChainName})`, inboundRateLimiter) +} diff --git a/tasks/solana/helpers/blacklist.ts b/tasks/solana/helpers/blacklist.ts new file mode 100644 index 0000000..2500f17 --- /dev/null +++ b/tasks/solana/helpers/blacklist.ts @@ -0,0 +1,77 @@ +import { findAssociatedTokenPda } from '@metaplex-foundation/mpl-toolbox' +import { publicKey } from '@metaplex-foundation/umi' +import { TOKEN_PROGRAM_ID, createFreezeAccountInstruction } from '@solana/spl-token' +import { PublicKey } from '@solana/web3.js' +import { task } from 'hardhat/config' + +import { types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat' +import { EndpointId } from '@layerzerolabs/lz-definitions' + +import { deriveConnection } from '..' + +import { printBase58Tx } from './utils' + +interface TxTaskArgs { + eid: EndpointId + tokenAddr: string + userAddr: string + multisigAddr: string + signerAddr: string +} + +task('lz:solana:blacklist', 'Blacklists a user from the token') + .addParam('eid', 'Solana mainnet (30168) or testnet (40168) eid', undefined, devtoolsTypes.eid, false) + .addParam('tokenAddr', 'The mint address of the token to blacklist', undefined, devtoolsTypes.string, false) + .addParam('userAddr', 'The user address to blacklist', undefined, devtoolsTypes.string, false) + .addParam('multisigAddr', 'The native SPL token multisig address that is the freeze authority', undefined, devtoolsTypes.string, false) + .addParam('signerAddr', 'The Squads Vault signer address (must be a signer of the multisig)', undefined, devtoolsTypes.string, false) + .setAction(async ({ eid, tokenAddr, userAddr, multisigAddr, signerAddr }: TxTaskArgs) => { + console.log(`Blacklisting ${userAddr}...`) + + const { connection, umi } = await deriveConnection(eid) + + const tokenAccount = findAssociatedTokenPda(umi, { + mint: publicKey(tokenAddr), + owner: publicKey(userAddr), + tokenProgramId: publicKey(TOKEN_PROGRAM_ID), + }) + + const ata = tokenAccount[0] + console.log("User's ATA: ", ata) + + const balance = await connection.getTokenAccountBalance(new PublicKey(ata)) + console.log('Balance: ', balance.value.uiAmount) + + const multisigAuthorityPubkey = new PublicKey(multisigAddr) // The native SPL token multisig + const squadsVaultSigner = new PublicKey(signerAddr) // The Squads Vault signer + const ataPubkey = new PublicKey(ata) + const mintPubkey = new PublicKey(tokenAddr) + + const ix = createFreezeAccountInstruction( + ataPubkey, + mintPubkey, + multisigAuthorityPubkey, + [squadsVaultSigner], + TOKEN_PROGRAM_ID + ) + + const multisigKeyIndex = ix.keys.findIndex( + (key: any) => key.pubkey.equals(multisigAuthorityPubkey) + ) + + if (multisigKeyIndex !== -1) { + ix.keys[multisigKeyIndex].isSigner = false + ix.keys[multisigKeyIndex].isWritable = false + } + + const signerKeyIndex = ix.keys.findIndex( + (key: any) => key.pubkey.equals(squadsVaultSigner) + ) + + if (signerKeyIndex !== -1) { + ix.keys[signerKeyIndex].isSigner = true + ix.keys[signerKeyIndex].isWritable = false + } + + await printBase58Tx(ix, umi, signerAddr) + }) diff --git a/tasks/solana/helpers/burn.ts b/tasks/solana/helpers/burn.ts new file mode 100644 index 0000000..d0b3eb7 --- /dev/null +++ b/tasks/solana/helpers/burn.ts @@ -0,0 +1,63 @@ +import { findAssociatedTokenPda } from '@metaplex-foundation/mpl-toolbox' +import { publicKey } from '@metaplex-foundation/umi' +import { TOKEN_PROGRAM_ID, createBurnCheckedInstruction } from '@solana/spl-token' +import { PublicKey } from '@solana/web3.js' +import { parseUnits } from 'ethers/lib/utils' +import { task } from 'hardhat/config' + +import { types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat' +import { EndpointId } from '@layerzerolabs/lz-definitions' + +import { deriveConnection } from '..' + +import { printBase58Tx } from './utils' + +interface TxTaskArgs { + eid: EndpointId + tokenAddr: string + userAddr: string + amount: string + squadsAddr: string + signerAddr: string +} + +task('lz:solana:burn', 'Converts base64 Solana transaction to base58') + .addParam('eid', 'Solana mainnet (30168) or testnet (40168) eid', undefined, devtoolsTypes.eid, false) + .addParam('tokenAddr', 'The mint address of the token to burn', undefined, devtoolsTypes.string, false) + .addParam('userAddr', 'The user address of the token to burn', undefined, devtoolsTypes.string, false) + .addParam('amount', 'The amount of tokens to burn', undefined, devtoolsTypes.string, false) + .addParam('signerAddr', 'The signer address to use for the tx', undefined, devtoolsTypes.string, false) + .addParam('squadsAddr', 'The squads address to use for the burn', undefined, devtoolsTypes.string, false) + .setAction(async ({ eid, tokenAddr, userAddr, amount, squadsAddr, signerAddr }: TxTaskArgs) => { + console.log(`Burning ${amount} tokens from ${userAddr}...`) + + const { connection, umi } = await deriveConnection(eid) + + const tokenAccount = findAssociatedTokenPda(umi, { + mint: publicKey(tokenAddr), + owner: publicKey(userAddr), + tokenProgramId: publicKey(TOKEN_PROGRAM_ID), + }) + + const ata = tokenAccount[0] + console.log("User's ATA: ", ata) + + const balance = await connection.getTokenAccountBalance(new PublicKey(ata)) + console.log('Balance: ', balance.value.uiAmount) + + if (!balance.value.uiAmount || balance.value.uiAmount < parseFloat(amount)) { + throw new Error('Insufficient balance') + } + + const ix = createBurnCheckedInstruction( + new PublicKey(ata), // ata + new PublicKey(tokenAddr), // mint + new PublicKey(squadsAddr), // owner // $SQUADS_ADDR + parseUnits(amount, 6).toBigInt(), + 6, + [new PublicKey(squadsAddr)], // $SQUADS_ADDR + TOKEN_PROGRAM_ID + ) + + await printBase58Tx(ix, umi, signerAddr) + }) diff --git a/tasks/solana/helpers/mint.ts b/tasks/solana/helpers/mint.ts new file mode 100644 index 0000000..8cd7542 --- /dev/null +++ b/tasks/solana/helpers/mint.ts @@ -0,0 +1,84 @@ +import { findAssociatedTokenPda } from '@metaplex-foundation/mpl-toolbox' +import { publicKey } from '@metaplex-foundation/umi' +import { toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters' +import { TOKEN_PROGRAM_ID, createAssociatedTokenAccount, createMintToCheckedInstruction } from '@solana/spl-token' +import { PublicKey } from '@solana/web3.js' +import { parseUnits } from 'ethers/lib/utils' +import { task } from 'hardhat/config' + +import { types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat' +import { EndpointId } from '@layerzerolabs/lz-definitions' + +import { deriveConnection } from '..' + +import { printBase58Tx } from './utils' + +interface TxTaskArgs { + eid: EndpointId + tokenAddr: string + userAddr: string + amount: string + multisigAddr: string + squadsAddr: string + signerAddr: string +} + +task('lz:solana:mint', 'Mints tokens to a user') + .addParam('eid', 'Solana mainnet (30168) or testnet (40168) eid', undefined, devtoolsTypes.eid, false) + .addParam('tokenAddr', 'The mint address of the token to mint', undefined, devtoolsTypes.string, false) + .addParam('userAddr', 'The user address to mint tokens to', undefined, devtoolsTypes.string, false) + .addParam('amount', 'The amount of tokens to mint', undefined, devtoolsTypes.string, false) + .addParam('multisigAddr', 'The multisig address to use for the mint', undefined, devtoolsTypes.string, false) + .addParam('squadsAddr', 'The squads address to use for the mint', undefined, devtoolsTypes.string, false) + .addParam('signerAddr', 'The signer address to use for the tx', undefined, devtoolsTypes.string, false) + .setAction(async ({ eid, tokenAddr, userAddr, amount, multisigAddr, squadsAddr, signerAddr }: TxTaskArgs) => { + console.log(`Minting ${amount} tokens to ${userAddr}...`) + const { connection, umi, umiWalletKeyPair } = await deriveConnection(eid) + + const tokenAccount = findAssociatedTokenPda(umi, { + mint: publicKey(tokenAddr), + owner: publicKey(userAddr), + tokenProgramId: publicKey(TOKEN_PROGRAM_ID), + }) + + const ata = tokenAccount[0] + console.log("User's ATA: ", ata) + + const printBalance = async () => { + const balance = await connection.getTokenAccountBalance(new PublicKey(ata)) + console.log('Balance: ', balance.value.uiAmount) + } + + try { + await printBalance() + } catch (error) { + console.error("ATA doesn't exist, creating it...") + const createdAta = await createAssociatedTokenAccount( + connection, + { + publicKey: toWeb3JsPublicKey(umiWalletKeyPair.publicKey), + secretKey: umiWalletKeyPair.secretKey, + }, + new PublicKey(tokenAddr), + new PublicKey(userAddr), + { + commitment: 'finalized', + }, + TOKEN_PROGRAM_ID + ) + console.log('Created ATA: ', createdAta.toBase58()) + await printBalance() + } + + const ix = createMintToCheckedInstruction( + new PublicKey(tokenAddr), // mint + new PublicKey(ata), // ata + new PublicKey(multisigAddr), // mint authority $MULTISIG_ADDR + parseUnits(amount, 6).toBigInt(), + 6, + [new PublicKey(squadsAddr)], // $SQUADS_ADDR + TOKEN_PROGRAM_ID + ) + + await printBase58Tx(ix, umi, signerAddr) + }) diff --git a/tasks/solana/helpers/setFreezeAuthority.ts b/tasks/solana/helpers/setFreezeAuthority.ts new file mode 100644 index 0000000..1006c92 --- /dev/null +++ b/tasks/solana/helpers/setFreezeAuthority.ts @@ -0,0 +1,49 @@ +import { AuthorityType, TOKEN_PROGRAM_ID, createSetAuthorityInstruction } from '@solana/spl-token' +import { PublicKey } from '@solana/web3.js' +import { task } from 'hardhat/config' + +import { types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat' +import { EndpointId } from '@layerzerolabs/lz-definitions' + +import { deriveConnection } from '..' + +import { printBase58Tx } from './utils' + +interface TxTaskArgs { + eid: EndpointId + tokenAddr: string + multisigAddr: string + squadsAddr: string + signerAddr: string + newAuthorityAddr: string | null + tokenProgram?: string +} + +task('lz:solana:set-freeze-authority', 'Changes the freeze authority of a token') + .addParam('eid', 'Solana mainnet (30168) or testnet (40168) eid', undefined, devtoolsTypes.eid, false) + .addParam('tokenAddr', 'The mint address of the token', undefined, devtoolsTypes.string, false) + .addParam('multisigAddr', 'The current freeze authority multisig address', undefined, devtoolsTypes.string, false) + .addParam('squadsAddr', 'The squads vault address that is a signer of the multisig', undefined, devtoolsTypes.string, false) + .addParam('signerAddr', 'The signer address to use for the tx (usually same as squadsAddr)', undefined, devtoolsTypes.string, false) + .addParam('newAuthorityAddr', 'The new freeze authority address (or "null" to remove freeze authority)', undefined, devtoolsTypes.string, false) + .addOptionalParam('tokenProgram', 'Token program ID: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA (standard) or TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb (2022)', TOKEN_PROGRAM_ID.toBase58(), devtoolsTypes.string, false) + .setAction(async ({ eid, tokenAddr, multisigAddr, squadsAddr, signerAddr, newAuthorityAddr, tokenProgram }: TxTaskArgs) => { + console.log(`Changing freeze authority from ${multisigAddr} to ${newAuthorityAddr === 'null' ? 'null (removing)' : newAuthorityAddr}...`) + const { umi } = await deriveConnection(eid) + + const newAuthority = newAuthorityAddr === 'null' || !newAuthorityAddr + ? null + : new PublicKey(newAuthorityAddr) + + const ix = createSetAuthorityInstruction( + new PublicKey(tokenAddr), + new PublicKey(multisigAddr), // current freeze authority (SPL multisig) + AuthorityType.FreezeAccount, + newAuthority, // new freeze authority (null to remove) + [new PublicKey(squadsAddr)], // signer(s) - must be a signer of the multisig + TOKEN_PROGRAM_ID + ) + + await printBase58Tx(ix, umi, signerAddr) + }) + diff --git a/tasks/solana/helpers/setMetadataAuthority.ts b/tasks/solana/helpers/setMetadataAuthority.ts new file mode 100644 index 0000000..42feeba --- /dev/null +++ b/tasks/solana/helpers/setMetadataAuthority.ts @@ -0,0 +1,129 @@ +import { findMetadataPda, updateMetadataAccountV2 } from '@metaplex-foundation/mpl-token-metadata' +import { createNoopSigner, publicKey, transactionBuilder } from '@metaplex-foundation/umi' +import { fromWeb3JsInstruction, fromWeb3JsPublicKey, toWeb3JsInstruction, toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters' +import { TOKEN_PROGRAM_ID, createUpdateAuthorityInstruction } from '@solana/spl-token' +import { PublicKey } from '@solana/web3.js' +import bs58 from 'bs58' +import { task } from 'hardhat/config' + +import { types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat' +import { EndpointId } from '@layerzerolabs/lz-definitions' + +import { deriveConnection, getExplorerTxLink } from '..' +import { SolanaTokenProgramType, getSolanaTokenMetadata, tokenProgramAddressToType } from '../../common/utils' + +import { printBase58Tx } from './utils' + +interface TxTaskArgs { + eid: EndpointId + tokenAddr: string + currentAuthority: string + squadsAddr?: string + signerAddr?: string + newAuthorityAddr: string + execute?: boolean +} + +task('lz:solana:set-metadata-authority', 'Changes the metadata update authority of a token') + .addParam('eid', 'Solana mainnet (30168) or testnet (40168) eid', undefined, devtoolsTypes.eid, false) + .addParam('tokenAddr', 'The mint address of the token', undefined, devtoolsTypes.string, false) + .addParam('currentAuthority', 'The current metadata update authority address (EOA or multisig vault)', undefined, devtoolsTypes.string, false) + .addOptionalParam('squadsAddr', 'The squads vault address that is a signer of the multisig (only needed for multisig)', undefined, devtoolsTypes.string) + .addOptionalParam('signerAddr', 'The signer address to use for the tx (only needed for multisig, usually same as squadsAddr)', undefined, devtoolsTypes.string) + .addParam('newAuthorityAddr', 'The new metadata update authority address', undefined, devtoolsTypes.string, false) + .addFlag('execute', 'Execute the transaction immediately (requires wallet keypair). If not set, outputs base58 transaction for Squads UI.') + .setAction(async ({ eid, tokenAddr, currentAuthority, squadsAddr, signerAddr, newAuthorityAddr, execute }: TxTaskArgs) => { + console.log(`Changing metadata update authority from ${currentAuthority} to ${newAuthorityAddr}...`) + + const { umi, connection, umiWalletSigner } = execute + ? await deriveConnection(eid, false) + : await deriveConnection(eid, true) + + const mintPubkey = new PublicKey(tokenAddr) + const mintAccount = await connection.getAccountInfo(mintPubkey) + + if (!mintAccount) { + throw new Error(`Mint account not found: ${tokenAddr}`) + } + + const tokenProgramType = tokenProgramAddressToType(mintAccount.owner) + + const isMultisig = !!squadsAddr && !!signerAddr + const actualSignerAddr = isMultisig ? signerAddr! : currentAuthority + + const signerPubkey = new PublicKey(actualSignerAddr) + const currentAuthorityPubkey = new PublicKey(currentAuthority) + const newAuthorityPubkey = new PublicKey(newAuthorityAddr) + + let ix: any + + if (tokenProgramType === SolanaTokenProgramType.SPL) { + const mintUmi = publicKey(tokenAddr) + const tokenMetadata = await getSolanaTokenMetadata(umi, mintUmi, tokenProgramType) + + if (!tokenMetadata?.updateAuthority) { + throw new Error('No Metaplex metadata found for this token. Cannot update metadata authority.') + } + + const metadataPda = findMetadataPda(umi, { mint: mintUmi }) + + const updateIx = updateMetadataAccountV2(umi, { + metadata: metadataPda, + updateAuthority: createNoopSigner(publicKey(currentAuthority)), + newUpdateAuthority: publicKey(newAuthorityAddr), + }) + + const umiInstruction = updateIx.getInstructions()[0] + ix = toWeb3JsInstruction(umiInstruction) + + // For multisigs, we need to modify the instruction to use the actual signer + if (isMultisig) { + // Find the updateAuthority key and update it to use the signer + const updateAuthorityKeyIndex = ix.keys.findIndex( + (key: any) => key.pubkey.equals(currentAuthorityPubkey) && key.isSigner + ) + + if (updateAuthorityKeyIndex !== -1) { + // Update the updateAuthority key to use the signer address + ix.keys[updateAuthorityKeyIndex] = { + pubkey: signerPubkey, + isSigner: true, + isWritable: false, + } + } else { + // If not found, add the signer as a new key + ix.keys.push({ + pubkey: signerPubkey, + isSigner: true, + isWritable: false, + }) + } + } + } else { + throw new Error(`Unsupported token program type: ${tokenProgramType}`) + } + + if (execute) { + const umiInstruction = fromWeb3JsInstruction(ix) + const txBuilder = await transactionBuilder() + .add({ instruction: umiInstruction, signers: [], bytesCreatedOnChain: 0 }) + .setLatestBlockhash(umi) + + console.log('Sending transaction...') + const { signature } = await txBuilder.useLegacyVersion().sendAndConfirm(umi, { + send: { + skipPreflight: false, + }, + }) + const txHash = bs58.encode(signature) + const isTestnet = eid === EndpointId.SOLANA_V2_TESTNET + const explorerLink = getExplorerTxLink(txHash, isTestnet) + + console.log(`Transaction sent successfully!`) + console.log(`Transaction signature: ${txHash}`) + console.log(`Explorer: ${explorerLink}`) + } else { + await printBase58Tx(ix, umi, actualSignerAddr) + } + }) + diff --git a/tasks/solana/helpers/unblacklist.ts b/tasks/solana/helpers/unblacklist.ts new file mode 100644 index 0000000..2970877 --- /dev/null +++ b/tasks/solana/helpers/unblacklist.ts @@ -0,0 +1,77 @@ +import { findAssociatedTokenPda } from '@metaplex-foundation/mpl-toolbox' +import { publicKey } from '@metaplex-foundation/umi' +import { TOKEN_PROGRAM_ID, createThawAccountInstruction } from '@solana/spl-token' +import { PublicKey } from '@solana/web3.js' +import { task } from 'hardhat/config' + +import { types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat' +import { EndpointId } from '@layerzerolabs/lz-definitions' + +import { deriveConnection } from '..' + +import { printBase58Tx } from './utils' + +interface TxTaskArgs { + eid: EndpointId + tokenAddr: string + userAddr: string + multisigAddr: string + signerAddr: string +} + +task('lz:solana:unblacklist', 'Unblacklists a user from the token') + .addParam('eid', 'Solana mainnet (30168) or testnet (40168) eid', undefined, devtoolsTypes.eid, false) + .addParam('tokenAddr', 'The mint address of the token to unblacklist', undefined, devtoolsTypes.string, false) + .addParam('userAddr', 'The user address to unblacklist', undefined, devtoolsTypes.string, false) + .addParam('multisigAddr', 'The native SPL token multisig address that is the freeze authority', undefined, devtoolsTypes.string, false) + .addParam('signerAddr', 'The Squads Vault signer address (must be a signer of the multisig)', undefined, devtoolsTypes.string, false) + .setAction(async ({ eid, tokenAddr, userAddr, multisigAddr, signerAddr }: TxTaskArgs) => { + console.log(`Unblacklisting ${userAddr}...`) + + const { connection, umi } = await deriveConnection(eid) + + const tokenAccount = findAssociatedTokenPda(umi, { + mint: publicKey(tokenAddr), + owner: publicKey(userAddr), + tokenProgramId: publicKey(TOKEN_PROGRAM_ID), + }) + + const ata = tokenAccount[0] + console.log("User's ATA: ", ata) + + const balance = await connection.getTokenAccountBalance(new PublicKey(ata)) + console.log('Balance: ', balance.value.uiAmount) + + const multisigAuthorityPubkey = new PublicKey(multisigAddr) // The native SPL token multisig + const squadsVaultSigner = new PublicKey(signerAddr) // The Squads Vault signer + const ataPubkey = new PublicKey(ata) + const mintPubkey = new PublicKey(tokenAddr) + + const ix = createThawAccountInstruction( + ataPubkey, + mintPubkey, + multisigAuthorityPubkey, + [squadsVaultSigner], + TOKEN_PROGRAM_ID + ) + + const multisigKeyIndex = ix.keys.findIndex( + (key: any) => key.pubkey.equals(multisigAuthorityPubkey) + ) + + if (multisigKeyIndex !== -1) { + ix.keys[multisigKeyIndex].isSigner = false + ix.keys[multisigKeyIndex].isWritable = false + } + + const signerKeyIndex = ix.keys.findIndex( + (key: any) => key.pubkey.equals(squadsVaultSigner) + ) + + if (signerKeyIndex !== -1) { + ix.keys[signerKeyIndex].isSigner = true + ix.keys[signerKeyIndex].isWritable = false + } + + await printBase58Tx(ix, umi, signerAddr) + }) diff --git a/tasks/solana/helpers/updateMetadata.ts b/tasks/solana/helpers/updateMetadata.ts new file mode 100644 index 0000000..898c7a7 --- /dev/null +++ b/tasks/solana/helpers/updateMetadata.ts @@ -0,0 +1,104 @@ +import { findMetadataPda, fetchMetadata, updateMetadataAccountV2 } from '@metaplex-foundation/mpl-token-metadata' +import { createNoopSigner, publicKey } from '@metaplex-foundation/umi' +import { toWeb3JsInstruction } from '@metaplex-foundation/umi-web3js-adapters' +import { TOKEN_PROGRAM_ID, createUpdateFieldInstruction } from '@solana/spl-token' +import { PublicKey } from '@solana/web3.js' +import { task } from 'hardhat/config' + +import { types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat' +import { EndpointId } from '@layerzerolabs/lz-definitions' + +import { deriveConnection } from '..' +import { SolanaTokenProgramType, getSolanaTokenMetadata, tokenProgramAddressToType } from '../../common/utils' + +import { printBase58Tx } from './utils' + +interface TxTaskArgs { + eid: EndpointId + tokenAddr: string + squadsAddr: string + field: string + value: string +} + +task('lz:solana:update-metadata', 'Updates the metadata of a token') + .addParam('eid', 'Solana mainnet (30168) or testnet (40168) eid', undefined, devtoolsTypes.eid, false) + .addParam('tokenAddr', 'The mint address of the token to mint', undefined, devtoolsTypes.string, false) + .addParam('squadsAddr', 'The squads address to use for the mint', undefined, devtoolsTypes.string, false) + .addParam('field', 'The field to update - Name, Symbol, Uri', undefined, devtoolsTypes.string, false) + .addParam('value', 'The value to update the field to', undefined, devtoolsTypes.string, false) + .setAction(async ({ eid, tokenAddr, squadsAddr, field, value }: TxTaskArgs) => { + const { umi, connection } = await deriveConnection(eid) + + const mintPubkey = new PublicKey(tokenAddr) + const mintAccount = await connection.getAccountInfo(mintPubkey) + + if (!mintAccount) { + throw new Error(`Mint account not found: ${tokenAddr}`) + } + + const tokenProgramType = tokenProgramAddressToType(mintAccount.owner) + const squadsPubkey = new PublicKey(squadsAddr) + let ix: any + + if (tokenProgramType === SolanaTokenProgramType.SPL) { + const mintUmi = publicKey(tokenAddr) + const tokenMetadata = await getSolanaTokenMetadata(umi, mintUmi, tokenProgramType) + + if (!tokenMetadata?.updateAuthority) { + throw new Error('No Metaplex metadata found for this token. Cannot update metadata.') + } + + const metadataPda = findMetadataPda(umi, { mint: mintUmi }) + + const metadataAccount = await fetchMetadata(umi, metadataPda) + + if (!metadataAccount) { + throw new Error('Failed to fetch metadata account') + } + + const fieldMap: Record = { + Name: 'name', + Symbol: 'symbol', + Uri: 'uri', + } + + const metaplexField = fieldMap[field] + if (!metaplexField) { + throw new Error(`Invalid field: ${field}. Must be one of: Name, Symbol, Uri`) + } + + const updateIx = updateMetadataAccountV2(umi, { + metadata: metadataPda, + updateAuthority: createNoopSigner(publicKey(squadsAddr)), + data: { + name: metaplexField === 'name' ? value : (metadataAccount.name ?? ''), + symbol: metaplexField === 'symbol' ? value : (metadataAccount.symbol ?? ''), + uri: metaplexField === 'uri' ? value : (metadataAccount.uri ?? ''), + sellerFeeBasisPoints: metadataAccount.sellerFeeBasisPoints ?? 0, + creators: metadataAccount.creators ?? null, + collection: metadataAccount.collection ?? null, + uses: metadataAccount.uses ?? null, + }, + }) + + const umiInstruction = updateIx.getInstructions()[0] + ix = toWeb3JsInstruction(umiInstruction) + + const updateAuthorityKeyIndex = ix.keys.findIndex( + (key: any) => key.pubkey.equals(squadsPubkey) && key.isSigner + ) + + if (updateAuthorityKeyIndex !== -1) { + ix.keys[updateAuthorityKeyIndex] = { + pubkey: squadsPubkey, + isSigner: true, + isWritable: false, + } + } + } else { + throw new Error(`Unsupported token program type: ${tokenProgramType}`) + } + + await printBase58Tx(ix, umi, squadsAddr) + }) diff --git a/tasks/solana/helpers/utils.ts b/tasks/solana/helpers/utils.ts new file mode 100644 index 0000000..808bcbd --- /dev/null +++ b/tasks/solana/helpers/utils.ts @@ -0,0 +1,25 @@ +import { Umi, createNoopSigner, publicKey, transactionBuilder } from '@metaplex-foundation/umi' +import { fromWeb3JsInstruction, toWeb3JsTransaction } from '@metaplex-foundation/umi-web3js-adapters' +import { TransactionInstruction } from '@solana/web3.js' +import bs58 from 'bs58' + +export const printBase58Tx = async (instruction: TransactionInstruction, umi: Umi, signerAddr: string) => { + const umiInstruction = fromWeb3JsInstruction(instruction) + + const txBuilder = await transactionBuilder() + .add({ instruction: umiInstruction, signers: [], bytesCreatedOnChain: 0 }) + .setLatestBlockhash(umi) + + const builtTx = txBuilder.useLegacyVersion().build({ + payer: createNoopSigner(publicKey(signerAddr)), + transactions: umi.transactions, + }) + + // Convert to web3.js transaction and serialize + const web3JsTxn = toWeb3JsTransaction(builtTx) + const base58Tx = bs58.encode(new Uint8Array(web3JsTxn.message.serialize())) + + console.log('==== Import the following base58 txn data into the Squads UI ====') + console.log(base58Tx) + console.log('==== End of base58 txn data ====') +} diff --git a/tasks/solana/index.ts b/tasks/solana/index.ts new file mode 100644 index 0000000..996087b --- /dev/null +++ b/tasks/solana/index.ts @@ -0,0 +1,340 @@ +import assert from 'assert' +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs' +import path from 'node:path' + +import { + fetchAddressLookupTable, + mplToolbox, + setComputeUnitLimit, + setComputeUnitPrice, +} from '@metaplex-foundation/mpl-toolbox' +import { + AddressLookupTableInput, + EddsaInterface, + Instruction, + KeypairSigner, + PublicKey, + TransactionBuilder, + Umi, + createNoopSigner, + createSignerFromKeypair, + publicKey, + signerIdentity, + transactionBuilder, +} from '@metaplex-foundation/umi' +import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' +import { createWeb3JsEddsa } from '@metaplex-foundation/umi-eddsa-web3js' +import { toWeb3JsInstruction, toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters' +import { AddressLookupTableAccount, Connection } from '@solana/web3.js' +import { getSimulationComputeUnits } from '@solana-developers/helpers' +import { backOff } from 'exponential-backoff' + +import { formatEid } from '@layerzerolabs/devtools' +import { getPrioritizationFees, getSolanaKeypair } from '@layerzerolabs/devtools-solana' +import { promptToContinue } from '@layerzerolabs/io-devtools' +import { EndpointId, endpointIdToNetwork } from '@layerzerolabs/lz-definitions' +import { OftPDA } from '@layerzerolabs/oft-v2-solana-sdk' + +import { DebugLogger, KnownWarnings, createSolanaConnectionFactory } from '../common/utils' + +export const DEFAULT_LOOKUP_TABLE_ADDRESS: Partial> = { + [EndpointId.SOLANA_V2_MAINNET]: publicKey('AokBxha6VMLLgf97B5VYHEtqztamWmYERBmmFvjuTzJB'), + [EndpointId.SOLANA_V2_TESTNET]: publicKey('9thqPdbR27A1yLWw2spwJLySemiGMXxPnEvfmXVk4KuK'), +} + +type DeriveConnectionParams = + | boolean + | { + readOnly?: boolean + noopSigner?: PublicKey + } +/** + * Derive common connection and UMI objects for a given endpoint ID. + * @param eid {EndpointId} + */ +export const deriveConnection = async (eid: EndpointId, params: DeriveConnectionParams = false) => { + // line below is for backwards compatibility (second param was initially only readOnly, updated to an object) + const { readOnly = false, noopSigner } = typeof params === 'object' ? params : { readOnly: params } + const keypair = await getSolanaKeypair(readOnly) + const connectionFactory = createSolanaConnectionFactory() + const connection = await connectionFactory(eid) + const umi = createUmi(connection.rpcEndpoint).use(mplToolbox()) + const umiWalletKeyPair = umi.eddsa.createKeypairFromSecretKey(keypair.secretKey) + const umiWalletSigner = noopSigner ? createNoopSigner(noopSigner) : createSignerFromKeypair(umi, umiWalletKeyPair) + umi.use(signerIdentity(umiWalletSigner)) + return { + connection, + umi, + umiWalletKeyPair, + umiWalletSigner, + } +} + +export const useWeb3Js = async () => { + // note: if we are okay with exporting getSolanaKeypair, then useWeb3js can be removed + const keypair = await getSolanaKeypair() + return { + web3JsKeypair: keypair, + } +} + +/** + * Derive the keys needed for the OFT program. + * @param programIdStr {string} + */ +export const deriveKeys = (programIdStr: string) => { + const programId = publicKey(programIdStr) + const eddsa: EddsaInterface = createWeb3JsEddsa() + const oftDeriver = new OftPDA(programId) + const lockBox = eddsa.generateKeypair() + const escrowPK = lockBox.publicKey + const [oftStorePda] = oftDeriver.oftStore(escrowPK) + return { + programId, + lockBox, + escrowPK, + oftStorePda, + eddsa, + } +} + +/** + * Outputs the OFT accounts to a JSON file. + * @param eid {EndpointId} + * @param programId {string} + * @param mint {string} + * @param mintAuthority {string} + * @param escrow {string} + * @param oftStore {string} + */ +export const saveSolanaDeployment = ( + eid: EndpointId, + programId: string, + mint: string, + mintAuthority: string, + escrow: string, + oftStore: string +) => { + const outputDir = `./deployments/${endpointIdToNetwork(eid)}` + if (!existsSync(outputDir)) { + mkdirSync(outputDir, { recursive: true }) + } + writeFileSync( + `${outputDir}/OFT.json`, + JSON.stringify( + { + programId, + mint, + mintAuthority, + escrow, + oftStore, + }, + null, + 4 + ) + ) + console.log(`Accounts have been saved to ${outputDir}/OFT.json`) +} + +/** + * Reads the OFT deployment info from disk for the given endpoint ID. + * @param eid {EndpointId} + * @returns The contents of the OFT.json file as a JSON object. + */ +export const getSolanaDeployment = ( + eid: EndpointId +): { + programId: string + mint: string + mintAuthority: string + escrow: string + oftStore: string +} => { + if (!eid) { + throw new Error('eid is required') + } + const outputDir = path.join('deployments', endpointIdToNetwork(eid)) + const filePath = path.join(outputDir, 'OFT.json') // Note: if you have multiple deployments, change this filename to refer to the desired deployment file + + if (!existsSync(filePath)) { + DebugLogger.printWarning(KnownWarnings.SOLANA_DEPLOYMENT_NOT_FOUND) + throw new Error(`Could not find Solana deployment file for eid ${eid} at: ${filePath}`) + } + + const fileContents = readFileSync(filePath, 'utf-8') + return JSON.parse(fileContents) +} + +/** + * Safely load the OFT store PDA for a given Solana endpoint. + * Logs a warning if the deployment file is missing or malformed, + * and returns null so consumers can decide how to proceed. + */ +export const getOftStoreAddress = (eid: EndpointId): string | null => { + try { + const { oftStore } = getSolanaDeployment(eid) + if (!oftStore) { + DebugLogger.printWarning( + KnownWarnings.SOLANA_DEPLOYMENT_MISSING_OFT_STORE, + `deployment file for ${endpointIdToNetwork(eid)} (eid ${eid}) missing 'oftStore' field.` + ) + return null + } + return oftStore + } catch (err: any) { + DebugLogger.printWarning( + KnownWarnings.ERROR_LOADING_SOLANA_DEPLOYMENT, + `Could not load Solana deployment for ${endpointIdToNetwork(eid)} (eid ${eid}): ${err.message}` + ) + return null + } +} + +// TODO: move below outside of solana folder since it's generic +export const getLayerZeroScanLink = (hash: string, isTestnet = false) => + isTestnet ? `https://testnet.layerzeroscan.com/tx/${hash}` : `https://layerzeroscan.com/tx/${hash}` + +export const getExplorerTxLink = (hash: string, isTestnet = false) => + `https://solscan.io/tx/${hash}?cluster=${isTestnet ? 'devnet' : 'mainnet-beta'}` + +const getAddressLookupTable = async (_lookupTableAddress: string | PublicKey, connection: Connection, umi: Umi) => { + const lookupTableAddress = publicKey(_lookupTableAddress) + const addressLookupTableInput: AddressLookupTableInput = await fetchAddressLookupTable(umi, lookupTableAddress) + if (!addressLookupTableInput) { + throw new Error(`No address lookup table found for ${lookupTableAddress}`) + } + const { value: lookupTableAccount } = await connection.getAddressLookupTable(toWeb3JsPublicKey(lookupTableAddress)) + if (!lookupTableAccount) { + throw new Error(`No address lookup table account found for ${lookupTableAddress}`) + } + return { lookupTableAddress, addressLookupTableInput, lookupTableAccount } +} + +export const getDefaultAddressLookupTable = async (connection: Connection, umi: Umi, fromEid: EndpointId) => { + // Lookup Table Address and Priority Fee Calculation + const lookupTableAddress = DEFAULT_LOOKUP_TABLE_ADDRESS[fromEid] + assert(lookupTableAddress != null, `No lookup table found for ${formatEid(fromEid)}`) + return getAddressLookupTable(lookupTableAddress, connection, umi) +} + +export enum TransactionType { + CreateToken = 'CreateToken', + CreateMultisig = 'CreateMultisig', + InitOft = 'InitOft', + SetAuthority = 'SetAuthority', + InitConfig = 'InitConfig', + SendOFT = 'SendOFT', +} + +const TransactionCuEstimates: Record = { + // for the sample values, they are: devnet, mainnet + [TransactionType.CreateToken]: 125_000, // actual sample: (59073, 123539), 55785 (more volatile as it has CPI to Metaplex) + [TransactionType.CreateMultisig]: 5_000, // actual sample: 3,230 + [TransactionType.InitOft]: 70_000, // actual sample: 59207, 65198 (note: this is the only transaction that createOFTAdapter does) + [TransactionType.SetAuthority]: 8_000, // actual sample: 6424, 6472 + [TransactionType.InitConfig]: 42_000, // actual sample: 33157, 40657 + [TransactionType.SendOFT]: 230_000, // actual sample: 217,784 +} + +export const getComputeUnitPriceAndLimit = async ( + connection: Connection, + ixs: Instruction[], + wallet: KeypairSigner, + lookupTableAccounts: AddressLookupTableAccount | AddressLookupTableAccount[], + transactionType: TransactionType +) => { + const { averageFeeExcludingZeros } = await getPrioritizationFees(connection) + const priorityFee = Math.round(averageFeeExcludingZeros) + const computeUnitPrice = BigInt(priorityFee) + + let computeUnits + + try { + computeUnits = await backOff( + () => + getSimulationComputeUnits( + connection, + ixs.map((ix) => toWeb3JsInstruction(ix)), + toWeb3JsPublicKey(wallet.publicKey), + Array.isArray(lookupTableAccounts) ? lookupTableAccounts : [lookupTableAccounts] + ), + { + maxDelay: 10000, + numOfAttempts: 3, + } + ) + } catch (e) { + console.error(`Error retrieving simulations compute units from RPC:`, e) + const continueByUsingHardcodedEstimate = await promptToContinue( + 'Failed to call simulateTransaction on the RPC. This can happen when the network is congested. Would you like to use hardcoded estimates (TransactionCuEstimates) ? This may result in slightly overpaying for the transaction.' + ) + if (!continueByUsingHardcodedEstimate) { + throw new Error( + 'Failed to call simulateTransaction on the RPC and user chose to not continue with hardcoded estimate.' + ) + } + console.log( + `Falling back to hardcoded estimate for ${transactionType}: ${TransactionCuEstimates[transactionType]} CUs` + ) + computeUnits = TransactionCuEstimates[transactionType] + } + + if (!computeUnits) { + throw new Error('Unable to compute units') + } + + return { + computeUnitPrice, + computeUnits, + } +} + +export const addComputeUnitInstructions = async ( + connection: Connection, + umi: Umi, + eid: EndpointId, + txBuilder: TransactionBuilder, + umiWalletSigner: KeypairSigner, + computeUnitPriceScaleFactor: number, + transactionType: TransactionType, + addressLookupTables?: (string | PublicKey)[] +) => { + const computeUnitLimitScaleFactor = 1.1 // hardcoded to 1.1 as the estimations are not perfect and can fall slightly short of the actual CU usage on-chain + + const addressLookupTableInputs: AddressLookupTableInput[] = [] + const lookupTableAccounts: AddressLookupTableAccount[] = [] + + if (addressLookupTables) { + const lookupTableResults = await Promise.all( + addressLookupTables.map((lookupTable) => getAddressLookupTable(lookupTable, connection, umi)) + ) + for (const { addressLookupTableInput, lookupTableAccount } of lookupTableResults) { + addressLookupTableInputs.push(addressLookupTableInput) + lookupTableAccounts.push(lookupTableAccount) + } + } else { + const { addressLookupTableInput, lookupTableAccount } = await getDefaultAddressLookupTable(connection, umi, eid) + addressLookupTableInputs.push(addressLookupTableInput) + lookupTableAccounts.push(lookupTableAccount) + } + + const { computeUnitPrice, computeUnits } = await getComputeUnitPriceAndLimit( + connection, + txBuilder.getInstructions(), + umiWalletSigner, + lookupTableAccounts, + transactionType + ) + // Since transaction builders are immutable, we must be careful to always assign the result of the add and prepend + // methods to a new variable. + const newTxBuilder = transactionBuilder() + .add( + setComputeUnitPrice(umi, { + microLamports: computeUnitPrice * BigInt(Math.floor(computeUnitPriceScaleFactor)), + }) + ) + .add(setComputeUnitLimit(umi, { units: computeUnits * computeUnitLimitScaleFactor })) + .setAddressLookupTables(addressLookupTableInputs) + .add(txBuilder) + return newTxBuilder +} diff --git a/tasks/solana/initConfig.ts b/tasks/solana/initConfig.ts new file mode 100644 index 0000000..202d18a --- /dev/null +++ b/tasks/solana/initConfig.ts @@ -0,0 +1,31 @@ +import { PublicKey } from '@solana/web3.js' +import { ConfigurableTaskDefinition } from 'hardhat/types' + +import { inheritTask } from '@layerzerolabs/devtools-evm-hardhat' +import { type LogLevel } from '@layerzerolabs/io-devtools' +import { type OAppConfigurator } from '@layerzerolabs/ua-devtools' +import { TASK_LZ_OAPP_WIRE } from '@layerzerolabs/ua-devtools-evm-hardhat' +import { initOFTAccounts } from '@layerzerolabs/ua-devtools-solana' + +// We'll create clones of the wire task and only override the configurator argument +const wireLikeTask = inheritTask(TASK_LZ_OAPP_WIRE) + +// TODO: export from wire.ts instead of re-declaring +/** + * Additional CLI arguments for our custom wire task + */ +interface Args { + logLevel: LogLevel + multisigKey?: PublicKey + internalConfigurator?: OAppConfigurator +} + +// This task will use the `initOFTAccounts` configurator that initializes the Solana accounts +const initConfigTask = wireLikeTask('lz:oft:solana:init-config') as ConfigurableTaskDefinition + +// TODO: currently the message for 'already done' state is "OApp is already wired." which is misleading -> should be changed to "Pathway Config already initialized" +initConfigTask + .setDescription('Initialize OFT accounts for Solana') + .setAction(async (args: Args, hre) => + hre.run(TASK_LZ_OAPP_WIRE, { ...args, internalConfigurator: initOFTAccounts, isSolanaInitConfig: true }) + ) diff --git a/tasks/solana/multisig.ts b/tasks/solana/multisig.ts new file mode 100644 index 0000000..24533ab --- /dev/null +++ b/tasks/solana/multisig.ts @@ -0,0 +1,161 @@ +import { createAccount } from '@metaplex-foundation/mpl-toolbox' +import { + KeypairSigner, + Umi, + createSignerFromKeypair, + transactionBuilder, + publicKey as umiPublicKey, +} from '@metaplex-foundation/umi' +import { fromWeb3JsInstruction, toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters' +import { + MULTISIG_SIZE, + TOKEN_2022_PROGRAM_ID, + TOKEN_PROGRAM_ID, + createInitializeMultisigInstruction, +} from '@solana/spl-token' +import { Connection, PublicKey } from '@solana/web3.js' +import bs58 from 'bs58' + +import { assertAccountInitialized } from '@layerzerolabs/devtools-solana' +import { EndpointId } from '@layerzerolabs/lz-definitions' + +import { TransactionType, addComputeUnitInstructions, getExplorerTxLink } from '.' + +export async function createMultisig( + connection: Connection, + umi: Umi, + eid: EndpointId, + umiWalletSigner: KeypairSigner, + signers: PublicKey[], + m: number, + keypair = umi.eddsa.generateKeypair(), + programId = TOKEN_PROGRAM_ID, + computeUnitPriceScaleFactor?: number +): Promise { + const initMultisigIx = createInitializeMultisigInstruction( + toWeb3JsPublicKey(keypair.publicKey), + signers, + m, + programId + ) + + let txBuilder = transactionBuilder() + .add( + createAccount(umi, { + newAccount: createSignerFromKeypair(umi, keypair), + lamports: await umi.rpc.getRent(MULTISIG_SIZE), + space: MULTISIG_SIZE, + programId: umiPublicKey(programId.toBase58()), + }) + ) + .add({ + instruction: fromWeb3JsInstruction(initMultisigIx), + signers: [], + bytesCreatedOnChain: 0, + }) + + if (computeUnitPriceScaleFactor) { + txBuilder = await addComputeUnitInstructions( + connection, + umi, + eid, + txBuilder, + umiWalletSigner, + computeUnitPriceScaleFactor, + TransactionType.CreateMultisig + ) + } + + const multisigPublicKey = toWeb3JsPublicKey(keypair.publicKey) + + const tx = await txBuilder.sendAndConfirm(umi) + await assertAccountInitialized(connection, multisigPublicKey) + const isTestnet = eid == EndpointId.SOLANA_V2_TESTNET + console.log(`createMultisigTx: ${getExplorerTxLink(bs58.encode(tx.signature), isTestnet)}`) + + return multisigPublicKey +} + +/** + * Creates a (1/N) multisig account for use as the mint authority. + * @param connection {Connection} + * @param payer {Signer} + * @param oftStorePda {PublicKey} will be included as a signer + * @param tokenProgramId {PublicKey} defaults to SPL token program ID + * @param additionalSigners {PublicKey[]} the additionalSigners for the multisig account + */ +export const createMintAuthorityMultisig = async ( + connection: Connection, + umi: Umi, + eid: EndpointId, + umiWalletSigner: KeypairSigner, + oftStorePda: PublicKey, + tokenProgramId: PublicKey = TOKEN_PROGRAM_ID, + additionalSigners: PublicKey[], + computeUnitPriceScaleFactor: number +) => { + return createMultisig( + connection, + umi, + eid, + umiWalletSigner, + [oftStorePda, ...additionalSigners], + 1, // quorum 1/N + undefined, + tokenProgramId, + computeUnitPriceScaleFactor + ) +} + +/** + * Decode the signers of a multisig account and check if the expected signers + * are present and the quorum is 1/N. + * @param connection {Connection} + * @param multisigAddress {PublicKey} + * @param expectedSigners {PublicKey[]} the expected signers + */ +export const checkMultisigSigners = async ( + connection: Connection, + multisigAddress: PublicKey, + expectedSigners: PublicKey[] +) => { + const accountInfo = await assertAccountInitialized(connection, multisigAddress) + + if (!accountInfo.owner.equals(TOKEN_PROGRAM_ID) && !accountInfo.owner.equals(TOKEN_2022_PROGRAM_ID)) { + throw new Error('Provided address is not an SPL Token multisig account') + } + + // Multisig accounts have a specific layout based on the Multisig interface: + const data = accountInfo.data + + // Extract the number of required signers (m) and total possible signers (n) + const numRequiredSigners = data[0] + const numTotalSigners = data[1] + + if (numRequiredSigners !== 1) { + throw new Error('Multisig account must have 1 required signer') + } + + // Initialize an array to hold the signers + const signers: PublicKey[] = [] + + // Extract each signer public key based on the Multisig interface + const signerOffset = 3 // Offset to the first signer in the data + const signerSize = 32 // Each signer address is 32 bytes + + for (let i = 0; i < numTotalSigners; i++) { + const start = signerOffset + i * signerSize + const end = start + signerSize + const signerPublicKey = new PublicKey(data.slice(start, end)) + if (!signerPublicKey.equals(PublicKey.default)) { + signers.push(signerPublicKey) + } + } + + for (const signer of expectedSigners) { + if (!signers.find((s) => s.toBase58() == signer.toBase58())) { + throw new Error(`Signer ${signer.toBase58()} not found in multisig account`) + } + } + return signers +} diff --git a/tasks/solana/sendSolana.ts b/tasks/solana/sendSolana.ts new file mode 100644 index 0000000..4f76333 --- /dev/null +++ b/tasks/solana/sendSolana.ts @@ -0,0 +1,196 @@ +import { fetchMint, fetchToken, findAssociatedTokenPda } from '@metaplex-foundation/mpl-toolbox' +import { publicKey, transactionBuilder } from '@metaplex-foundation/umi' +import { fromWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters' +import { TOKEN_PROGRAM_ID } from '@solana/spl-token' +import { PublicKey } from '@solana/web3.js' +import bs58 from 'bs58' + +import { createLogger, promptToContinue } from '@layerzerolabs/io-devtools' +import { EndpointId, endpointIdToNetwork } from '@layerzerolabs/lz-definitions' +import { addressToBytes32 } from '@layerzerolabs/lz-v2-utilities' +import { oft } from '@layerzerolabs/oft-v2-solana-sdk' + +import { SendResult } from '../common/types' +import { DebugLogger, KnownErrors, isEmptyOptionsSolana } from '../common/utils' + +import { parseDecimalToUnits, silenceSolana429 } from './utils' + +import { + TransactionType, + addComputeUnitInstructions, + deriveConnection, + getDefaultAddressLookupTable, + getLayerZeroScanLink, + getSolanaDeployment, +} from './index' + +const logger = createLogger() + +export interface SolanaArgs { + amount: string + to: string + srcEid: EndpointId + dstEid: EndpointId + minAmount?: string + extraOptions?: string + composeMsg?: string + oftAddress?: string + oftProgramId?: string + tokenProgram?: string + computeUnitPriceScaleFactor?: number + addressLookupTables?: string[] +} + +export async function sendSolana({ + amount, + to, + srcEid, + dstEid, + oftAddress, + oftProgramId, + tokenProgram: tokenProgramStr, + computeUnitPriceScaleFactor = 4, + minAmount, + extraOptions, + composeMsg, + addressLookupTables, +}: SolanaArgs): Promise { + // 1️⃣ RPC + UMI + const { connection, umi, umiWalletSigner } = await deriveConnection(srcEid) + silenceSolana429(connection) + // 2️⃣ Pick your OFT program ID (override or from deployment) + const programId = oftProgramId + ? publicKey(oftProgramId) + : publicKey( + (() => { + try { + return getSolanaDeployment(srcEid).programId + } catch (error) { + logger.error(`No Program ID found for ${srcEid}: ${error}`) + throw error + } + })() + ) + + // 3️⃣ Decide your store PDA (override or from your on‐disk deployment) + const storePda = oftAddress ? publicKey(oftAddress) : publicKey(getSolanaDeployment(srcEid).oftStore) + const oftStoreInfo = await oft.accounts.fetchOFTStore(umi, storePda) + const mintPk = new PublicKey(oftStoreInfo.tokenMint) + const escrowPk = new PublicKey(oftStoreInfo.tokenEscrow) + + // 4️⃣ Attach token account & check balance + const tokenProgramId = tokenProgramStr ? publicKey(tokenProgramStr) : fromWeb3JsPublicKey(TOKEN_PROGRAM_ID) + const tokenAccount = findAssociatedTokenPda(umi, { + mint: fromWeb3JsPublicKey(mintPk), + owner: umiWalletSigner.publicKey, + tokenProgramId, + }) + if (!tokenAccount) throw new Error(`No token account for mint ${mintPk}`) + const balance = (await fetchToken(umi, tokenAccount)).amount + + // 5️⃣ Normalize human→base units + const decimals = (await fetchMint(umi, fromWeb3JsPublicKey(mintPk))).decimals + const amountUnits = parseDecimalToUnits(amount, decimals) + if (amountUnits === 0n || amountUnits > balance) { + throw new Error(`Insufficient balance (need ${amountUnits}, have ${balance})`) + } + + // Check whether there are extra options or enforced options. If not, warn the user. + // Read on Message Options: https://docs.layerzero.network/v2/concepts/message-options + if (!extraOptions) { + try { + const enforcedOptionsMap = await oft.getEnforcedOptions(umi.rpc, storePda, dstEid, programId) + const enforcedOptionsBuffer = composeMsg ? enforcedOptionsMap.sendAndCall : enforcedOptionsMap.send + + if (isEmptyOptionsSolana(enforcedOptionsBuffer)) { + const proceed = await promptToContinue( + 'No extra options were included and OFT has no set enforced options. Your quote / send will most likely fail. Continue?' + ) + if (!proceed) { + throw new Error('Aborted due to missing options') + } + } + } catch (error) { + logger.debug(`Failed to check enforced options: ${error}`) + } + } + + // 6️⃣ Lookup table addresses + const lookupTableAddresses = + addressLookupTables && addressLookupTables.length > 0 + ? addressLookupTables.map((addr) => publicKey(addr)) + : [(await getDefaultAddressLookupTable(connection, umi, srcEid)).lookupTableAddress] + + // 7️⃣ Quote (use our overridden `programId`) + logger.info('Quoting the native gas cost for the send transaction...') + const sendParam = { + dstEid, + to: Buffer.from(addressToBytes32(to)), + amountLd: amountUnits, + minAmountLd: minAmount ? parseDecimalToUnits(minAmount, decimals) : amountUnits, + options: extraOptions ? Buffer.from(extraOptions.replace(/^0x/, ''), 'hex') : undefined, + composeMsg: composeMsg ? Buffer.from(composeMsg.replace(/^0x/, ''), 'hex') : undefined, + } + const { nativeFee } = await oft.quote( + umi.rpc, + { + payer: umiWalletSigner.publicKey, + tokenMint: fromWeb3JsPublicKey(mintPk), + tokenEscrow: fromWeb3JsPublicKey(escrowPk), + }, + { + payInLzToken: false, + ...sendParam, + }, + { oft: programId }, // ← use override + [], + lookupTableAddresses + ) + + // 8️⃣ Send (again passing `programId`) + logger.info('Sending the transaction...') + const ix = await oft.send( + umi.rpc, + { + payer: umiWalletSigner, + tokenMint: fromWeb3JsPublicKey(mintPk), + tokenEscrow: fromWeb3JsPublicKey(escrowPk), + tokenSource: tokenAccount[0], + }, + { + nativeFee, + ...sendParam, + }, + { oft: programId, token: tokenProgramId } // ← use override + ) + + // 9️⃣ Compute units & submit + let txB = transactionBuilder().add([ix]) + txB = await addComputeUnitInstructions( + connection, + umi, + srcEid, + txB, + umiWalletSigner, + computeUnitPriceScaleFactor, + TransactionType.SendOFT, + lookupTableAddresses + ) + let txHash: string + try { + const { signature } = await txB.sendAndConfirm(umi) + txHash = bs58.encode(signature) + } catch (error) { + DebugLogger.printErrorAndFixSuggestion( + KnownErrors.ERROR_QUOTING_NATIVE_GAS_COST, + `For network: ${endpointIdToNetwork(srcEid)}, OFT: ${oftAddress}` + ) + throw error + } + + const isTestnet = srcEid === EndpointId.SOLANA_V2_TESTNET + + const scanLink = getLayerZeroScanLink(txHash, isTestnet) + + return { txHash, scanLink } +} diff --git a/tasks/solana/setOFTConfig.ts b/tasks/solana/setOFTConfig.ts new file mode 100644 index 0000000..c0e5e6a --- /dev/null +++ b/tasks/solana/setOFTConfig.ts @@ -0,0 +1,261 @@ +import { createNoopSigner, KeypairSigner, publicKey, transactionBuilder } from '@metaplex-foundation/umi' +import { toWeb3JsTransaction } from '@metaplex-foundation/umi-web3js-adapters' +import bs58 from 'bs58' +import { task } from 'hardhat/config' + +import { types as devtoolsTypes } from '@layerzerolabs/devtools-evm-hardhat' +import { EndpointId } from '@layerzerolabs/lz-definitions' +import { oft } from '@layerzerolabs/oft-v2-solana-sdk' + +import { TransactionType, addComputeUnitInstructions, deriveConnection, getExplorerTxLink } from './index' + +interface SetOFTConfigTaskArgs { + /** + * The endpoint ID for the Solana network. + */ + eid: EndpointId + + /** + * The OFT Store public key. + */ + oftStore: string + + /** + * The program ID for the OFT program. + */ + programId: string + + /** + * The new admin public key. + */ + newAdmin?: string + + /** + * The new delegate public key. + */ + newDelegate?: string + + /** + * The new default fee in basis points. + */ + defaultFee?: number + + /** + * Set paused state. + */ + paused?: boolean + + /** + * The new pauser public key. + */ + pauser?: string + + /** + * The new unpauser public key. + */ + unpauser?: string + + computeUnitPriceScaleFactor: number + + /** + * Output transaction as base58 instead of sending it. + */ + outputBase58?: boolean +} + +task('lz:oft:solana:set-config', 'Sets OFT configuration (admin, delegate, fees, etc.)') + .addParam('eid', 'Solana mainnet (30168) or testnet (40168)', undefined, devtoolsTypes.eid) + .addParam('oftStore', 'The OFT Store public key') + .addParam('programId', 'The OFT Program id') + .addOptionalParam('newAdmin', 'The new admin public key', undefined, devtoolsTypes.string) + .addOptionalParam('newDelegate', 'The new delegate public key', undefined, devtoolsTypes.string) + .addOptionalParam('defaultFee', 'The new default fee in basis points', undefined, devtoolsTypes.int) + .addOptionalParam('paused', 'Set paused state', undefined, devtoolsTypes.boolean) + .addOptionalParam('pauser', 'The new pauser public key', undefined, devtoolsTypes.string) + .addOptionalParam('unpauser', 'The new unpauser public key', undefined, devtoolsTypes.string) + .addParam('computeUnitPriceScaleFactor', 'The compute unit price scale factor', 4, devtoolsTypes.float, true) + .addFlag('outputBase58', 'Output transaction as base58 instead of sending it') + .setAction( + async ({ + eid, + oftStore: oftStoreStr, + programId: programIdStr, + newAdmin: newAdminStr, + newDelegate: newDelegateStr, + defaultFee, + paused, + pauser: pauserStr, + unpauser: unpauserStr, + computeUnitPriceScaleFactor, + outputBase58, + }: SetOFTConfigTaskArgs) => { + const { connection, umi, umiWalletSigner } = await deriveConnection(eid) + const oftStore = publicKey(oftStoreStr) + const programId = publicKey(programIdStr) + + if ( + !newAdminStr && + !newDelegateStr && + defaultFee === undefined && + paused === undefined && + !pauserStr && + !unpauserStr + ) { + throw new Error('At least one configuration parameter must be provided') + } + + const isTestnet = eid === EndpointId.SOLANA_V2_TESTNET + + // If outputting base58, fetch the admin address from OFT store to use in instructions + let adminSigner = umiWalletSigner + if (outputBase58) { + const oftStoreInfo = await oft.accounts.fetchOFTStore(umi, oftStore) + adminSigner = createNoopSigner(publicKey(oftStoreInfo.admin)) + console.log(`Using admin address for transaction: ${oftStoreInfo.admin}`) + } + + let txBuilder = transactionBuilder() + + if (newDelegateStr) { + const newDelegate = publicKey(newDelegateStr) + console.log(`Setting delegate to: ${newDelegate}`) + + txBuilder = txBuilder.add( + oft.setOFTConfig( + { + admin: adminSigner, + oftStore: oftStore, + }, + { __kind: 'Delegate', delegate: newDelegate }, + { + oft: programId, + } + ) + ) + } + + if (defaultFee !== undefined) { + console.log(`Setting default fee to: ${defaultFee} basis points`) + + txBuilder = txBuilder.add( + oft.setOFTConfig( + { + admin: adminSigner, + oftStore: oftStore, + }, + { __kind: 'DefaultFee', defaultFee }, + { + oft: programId, + } + ) + ) + } + + if (paused !== undefined) { + console.log(`Setting paused state to: ${paused}`) + + txBuilder = txBuilder.add( + oft.setOFTConfig( + { + admin: adminSigner, + oftStore: oftStore, + }, + { __kind: 'Paused', paused }, + { + oft: programId, + } + ) + ) + } + + if (pauserStr) { + const pauser = pauserStr === 'null' ? undefined : publicKey(pauserStr) + console.log(`Setting pauser to: ${pauser}`) + + txBuilder = txBuilder.add( + oft.setOFTConfig( + { + admin: adminSigner, + oftStore: oftStore, + }, + { __kind: 'Pauser', pauser }, + { + oft: programId, + } + ) + ) + } + + if (unpauserStr) { + const unpauser = unpauserStr === 'null' ? undefined : publicKey(unpauserStr) + console.log(`Setting unpauser to: ${unpauser}`) + + txBuilder = txBuilder.add( + oft.setOFTConfig( + { + admin: adminSigner, + oftStore: oftStore, + }, + { __kind: 'Unpauser', unpauser }, + { + oft: programId, + } + ) + ) + } + + // Set admin LAST to avoid authorization issues + if (newAdminStr) { + const newAdmin = publicKey(newAdminStr) + console.log(`Setting admin to: ${newAdmin} (setting admin last to avoid authorization issues)`) + + txBuilder = txBuilder.add( + oft.setOFTConfig( + { + admin: adminSigner, + oftStore: oftStore, + }, + { __kind: 'Admin', admin: newAdmin }, + { + oft: programId, + } + ) + ) + } + + txBuilder = await addComputeUnitInstructions( + connection, + umi, + eid, + txBuilder, + umiWalletSigner as KeypairSigner, + computeUnitPriceScaleFactor, + TransactionType.SetAuthority + ) + + if (outputBase58) { + // Build transaction with noop signer for the admin (already set above) + const builtTx = (await txBuilder + .useLegacyVersion() + .setLatestBlockhash(umi)) + .build({ + payer: adminSigner, + transactions: umi.transactions, + }) + + // Convert to web3.js transaction and serialize + const web3JsTxn = toWeb3JsTransaction(builtTx) + const base58Tx = bs58.encode(new Uint8Array(web3JsTxn.message.serialize())) + + console.log('==== Import the following base58 txn data into the Squads UI ====') + console.log(base58Tx) + console.log('==== End of base58 txn data ====') + console.log(`\nAdmin address (signer): ${adminSigner.publicKey}`) + } else { + const { signature } = await txBuilder.sendAndConfirm(umi) + console.log(`setOFTConfigTx: ${getExplorerTxLink(bs58.encode(signature), isTestnet)}`) + + console.log('OFT configuration updated successfully!') + } + } + ) diff --git a/tasks/solana/utils.ts b/tasks/solana/utils.ts new file mode 100644 index 0000000..fd50673 --- /dev/null +++ b/tasks/solana/utils.ts @@ -0,0 +1,85 @@ +import { Connection } from '@solana/web3.js' +import { HardhatRuntimeEnvironment } from 'hardhat/types' + +import { ChainType, EndpointId, endpointIdToChainType } from '@layerzerolabs/lz-definitions' +import { OAppOmniGraph } from '@layerzerolabs/ua-devtools' +import { + OAppOmniGraphHardhatSchema, + SUBTASK_LZ_OAPP_CONFIG_LOAD, + SubtaskLoadConfigTaskArgs, + TASK_LZ_OAPP_CONFIG_GET, +} from '@layerzerolabs/ua-devtools-evm-hardhat' + +export const findSolanaEndpointIdInGraph = async ( + hre: HardhatRuntimeEnvironment, + oappConfig: string +): Promise => { + if (!oappConfig) throw new Error('Missing oappConfig') + + let graph: OAppOmniGraph + try { + graph = await hre.run(SUBTASK_LZ_OAPP_CONFIG_LOAD, { + configPath: oappConfig, + schema: OAppOmniGraphHardhatSchema, + task: TASK_LZ_OAPP_CONFIG_GET, + } satisfies SubtaskLoadConfigTaskArgs) + } catch (error) { + if (error instanceof Error) { + throw new Error(`Failed to load OApp configuration: ${error.message}`) + } else { + throw new Error('Failed to load OApp configuration: Unknown error') + } + } + + let solanaEid: EndpointId | null = null + + const checkSolanaEndpoint = (eid: EndpointId) => { + if (endpointIdToChainType(eid) === ChainType.SOLANA) { + if (solanaEid && solanaEid !== eid) { + throw new Error(`Multiple Solana Endpoint IDs found: ${solanaEid}, ${eid}`) + } + solanaEid = eid + } + } + + for (const { vector } of graph.connections) { + checkSolanaEndpoint(vector.from.eid) + checkSolanaEndpoint(vector.to.eid) + if (solanaEid) return solanaEid + } + + throw new Error('No Solana Endpoint ID found. Ensure your OApp configuration includes a valid Solana endpoint.') +} + +/** + * Turn a human decimal amount (e.g. "1.234") into a BigInt of base‐units given `decimals`. + */ +export function parseDecimalToUnits(amount: string, decimals: number): bigint { + const [whole, fraction = ''] = amount.split('.') + const wholeUnits = BigInt(whole) * 10n ** BigInt(decimals) + // pad or trim the fractional part to exactly `decimals` digits + const fracUnits = BigInt( + fraction + .padEnd(decimals, '0') // "23" → "230000" + .slice(0, decimals) // in case user typed more digits than `decimals` + ) + return wholeUnits + fracUnits +} + +/** + * Suppresses Solana‐web3.js "429 Too Many Requests" retry spam + * by intercepting stderr.write and dropping any chunk + * that mentions the 429 retry. + */ +export function silenceSolana429(connection: Connection): void { + const origWrite = process.stderr.write.bind(process.stderr) + process.stderr.write = ((chunk: any, ...args: any[]) => { + const str = Buffer.isBuffer(chunk) ? chunk.toString('utf8') : chunk + if (typeof str === 'string' && str.includes('429 Too Many Requests')) { + // swallow it + return true + } + // otherwise pass through + return origWrite(chunk, ...args) + }) as typeof process.stderr.write +} diff --git a/tasks/utils/getFee.ts b/tasks/utils/getFee.ts new file mode 100644 index 0000000..ef83ec4 --- /dev/null +++ b/tasks/utils/getFee.ts @@ -0,0 +1,75 @@ +import { Connection, PublicKey } from '@solana/web3.js' + +// Define interfaces for more explicit typing +interface PrioritizationFeeObject { + slot: number + prioritizationFee: number +} + +interface Config { + lockedWritableAccounts: PublicKey[] +} + +const getPrioritizationFees = async ( + connection: Connection, + programId?: string // TODO: change to array of addresses / public keys to match lockedWritableAccounts' type +): Promise<{ + averageFeeIncludingZeros: number + averageFeeExcludingZeros: number + medianFee: number +}> => { + try { + const publicKey = new PublicKey(programId || PublicKey.default) // the account that will be written to + + const config: Config = { + lockedWritableAccounts: [publicKey], + } + + const prioritizationFeeObjects = (await connection.getRecentPrioritizationFees( + config + )) as PrioritizationFeeObject[] + + if (prioritizationFeeObjects.length === 0) { + console.log('No prioritization fee data available.') + return { averageFeeIncludingZeros: 0, averageFeeExcludingZeros: 0, medianFee: 0 } + } + + // Extract slots and sort them + // const slots = prioritizationFeeObjects.map((feeObject) => feeObject.slot).sort((a, b) => a - b) + + // Calculate the average including zero fees + const averageFeeIncludingZeros = + prioritizationFeeObjects.length > 0 + ? Math.floor( + prioritizationFeeObjects.reduce((acc, feeObject) => acc + feeObject.prioritizationFee, 0) / + prioritizationFeeObjects.length + ) + : 0 + + // Filter out prioritization fees that are equal to 0 for other calculations + const nonZeroFees = prioritizationFeeObjects + .map((feeObject) => feeObject.prioritizationFee) + .filter((fee) => fee !== 0) + + // Calculate the average of the non-zero fees + const averageFeeExcludingZeros = + nonZeroFees.length > 0 ? Math.floor(nonZeroFees.reduce((acc, fee) => acc + fee, 0) / nonZeroFees.length) : 0 + + // Calculate the median of the non-zero fees + const sortedFees = nonZeroFees.sort((a, b) => a - b) + let medianFee = 0 + if (sortedFees.length > 0) { + const midIndex = Math.floor(sortedFees.length / 2) + medianFee = + sortedFees.length % 2 !== 0 + ? sortedFees[midIndex] + : Math.floor((sortedFees[midIndex - 1] + sortedFees[midIndex]) / 2) + } + return { averageFeeIncludingZeros, averageFeeExcludingZeros, medianFee } + } catch (error) { + console.error('Error fetching prioritization fees:', error) + return { averageFeeIncludingZeros: 0, averageFeeExcludingZeros: 0, medianFee: 0 } + } +} + +export default getPrioritizationFees diff --git a/tx-data/all-evm-mainnet-txs.log b/tx-data/all-evm-mainnet-txs.log new file mode 100644 index 0000000..41aacbc --- /dev/null +++ b/tx-data/all-evm-mainnet-txs.log @@ -0,0 +1,26 @@ +[ + { + "point": { + "eid": 30101, + "address": "0x01CacCa455d04F0D52231589F0deb543de9213E3" + }, + "data": "0x3400288b00000000000000000000000000000000000000000000000000000000000075d8dde8d977d37ab113e40c953625fe3afe62b74fa20e785a8575688622f6a4da92", + "description": "Setting peer for eid 30168 (SOLANA_V2_MAINNET) to address 0xdde8d977d37ab113e40c953625fe3afe62b74fa20e785a8575688622f6a4da92" + }, + { + "point": { + "eid": 30367, + "address": "0x01CacCa455d04F0D52231589F0deb543de9213E3" + }, + "data": "0x3400288b00000000000000000000000000000000000000000000000000000000000075d8dde8d977d37ab113e40c953625fe3afe62b74fa20e785a8575688622f6a4da92", + "description": "Setting peer for eid 30168 (SOLANA_V2_MAINNET) to address 0xdde8d977d37ab113e40c953625fe3afe62b74fa20e785a8575688622f6a4da92" + }, + { + "point": { + "eid": 30111, + "address": "0x01CacCa455d04F0D52231589F0deb543de9213E3" + }, + "data": "0x3400288b00000000000000000000000000000000000000000000000000000000000075d8dde8d977d37ab113e40c953625fe3afe62b74fa20e785a8575688622f6a4da92", + "description": "Setting peer for eid 30168 (SOLANA_V2_MAINNET) to address 0xdde8d977d37ab113e40c953625fe3afe62b74fa20e785a8575688622f6a4da92" + } +] \ No newline at end of file diff --git a/tx-data/all-evm-testnet-txs.log b/tx-data/all-evm-testnet-txs.log new file mode 100644 index 0000000..c794593 --- /dev/null +++ b/tx-data/all-evm-testnet-txs.log @@ -0,0 +1,18 @@ +[ + { + "point": { + "eid": 40161, + "address": "0xCD16E954FCCb81f8524a6C87Badf34fc88699403" + }, + "data": "0x3400288b0000000000000000000000000000000000000000000000000000000000009ce81b175096fa9ed7cd651560c7ac4c8a5c52b900578938f8f25f9a4d762a29f1c6", + "description": "Setting peer for eid 40168 (SOLANA_V2_TESTNET) to address 0x1b175096fa9ed7cd651560c7ac4c8a5c52b900578938f8f25f9a4d762a29f1c6" + }, + { + "point": { + "eid": 40362, + "address": "0xCD16E954FCCb81f8524a6C87Badf34fc88699403" + }, + "data": "0x3400288b0000000000000000000000000000000000000000000000000000000000009ce81b175096fa9ed7cd651560c7ac4c8a5c52b900578938f8f25f9a4d762a29f1c6", + "description": "Setting peer for eid 40168 (SOLANA_V2_TESTNET) to address 0x1b175096fa9ed7cd651560c7ac4c8a5c52b900578938f8f25f9a4d762a29f1c6" + } +] \ No newline at end of file diff --git a/tx-data/ethereum-mainnet-txs.json b/tx-data/ethereum-mainnet-txs.json new file mode 100644 index 0000000..f8417e2 --- /dev/null +++ b/tx-data/ethereum-mainnet-txs.json @@ -0,0 +1,19 @@ +{ + "version": "1.0", + "chainId": "1", + "createdAt": 1769030917913, + "meta": { + "name": "LayerZero Wire Configuration - ethereum-mainnet", + "description": "Transaction for LayerZero OApp wiring on ethereum-mainnet", + "txBuilderVersion": "1.17.1", + "createdFromSafeAddress": "0xfA633B67b1d9371eBa32cf3476F275D75C75ce77" + }, + "transactions": [ + { + "to": "0x01CacCa455d04F0D52231589F0deb543de9213E3", + "value": "0", + "data": "0x3400288b00000000000000000000000000000000000000000000000000000000000075d8dde8d977d37ab113e40c953625fe3afe62b74fa20e785a8575688622f6a4da92", + "operation": 0 + } + ] +} \ No newline at end of file diff --git a/tx-data/hyperevm-mainnet-txs.json b/tx-data/hyperevm-mainnet-txs.json new file mode 100644 index 0000000..79390e3 --- /dev/null +++ b/tx-data/hyperevm-mainnet-txs.json @@ -0,0 +1,19 @@ +{ + "version": "1.0", + "chainId": "999", + "createdAt": 1769030917914, + "meta": { + "name": "LayerZero Wire Configuration - hyperevm-mainnet", + "description": "Transaction for LayerZero OApp wiring on hyperevm-mainnet", + "txBuilderVersion": "1.17.1", + "createdFromSafeAddress": "0xfA633B67b1d9371eBa32cf3476F275D75C75ce77" + }, + "transactions": [ + { + "to": "0x01CacCa455d04F0D52231589F0deb543de9213E3", + "value": "0", + "data": "0x3400288b00000000000000000000000000000000000000000000000000000000000075d8dde8d977d37ab113e40c953625fe3afe62b74fa20e785a8575688622f6a4da92", + "operation": 0 + } + ] +} \ No newline at end of file diff --git a/tx-data/optimism-mainnet-txs.json b/tx-data/optimism-mainnet-txs.json new file mode 100644 index 0000000..ca5267f --- /dev/null +++ b/tx-data/optimism-mainnet-txs.json @@ -0,0 +1,19 @@ +{ + "version": "1.0", + "chainId": "10", + "createdAt": 1769030917914, + "meta": { + "name": "LayerZero Wire Configuration - optimism-mainnet", + "description": "Transaction for LayerZero OApp wiring on optimism-mainnet", + "txBuilderVersion": "1.17.1", + "createdFromSafeAddress": "0xfA633B67b1d9371eBa32cf3476F275D75C75ce77" + }, + "transactions": [ + { + "to": "0x01CacCa455d04F0D52231589F0deb543de9213E3", + "value": "0", + "data": "0x3400288b00000000000000000000000000000000000000000000000000000000000075d8dde8d977d37ab113e40c953625fe3afe62b74fa20e785a8575688622f6a4da92", + "operation": 0 + } + ] +} \ No newline at end of file diff --git a/tx-data/solana-devnet-dewire-txs.base58.json b/tx-data/solana-devnet-dewire-txs.base58.json new file mode 100644 index 0000000..7a1abdd --- /dev/null +++ b/tx-data/solana-devnet-dewire-txs.base58.json @@ -0,0 +1,20 @@ +[ + { + "point": { + "eid": 40168, + "address": "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6" + }, + "data": "4iY9PieS2uas1FXQnN2CVgZcaQGF8UgxQG1hNn4KmZjA3yZhgF6j7aFUmPiqBHbwYdXECdL7x7WM52tQCYU5QiNDWc8rPCttgXKHxaBmpYnmnMPS7hHnMUKXbUkGe2zja7F11GWTkuhtBBrnYV7sJaYoAAL8wvqw1WdhQnNsjweCRQdE8Kedrb7mEG1dJVQPMs5inZT6Et6ep89wcXq6cM7bvmMKDqGPk7h95vNfn7LWCTvBtoDJpDdzJx1dzmnxb6i4cmQQ7wkKkDXKeP2UsrpUwJt2ik6RLdmYY579ne8sM1KoHFXUNyymDFDz1QapNmJdCUmmCtF8Xqd9deFm5aMA6C9Ej32zvMTMVj1Tq8miPoaW7BLvEkZVFgFZVfTwLRrJ5RLESXUyGTSqApigAN8D3MaagecKz91JczPKN5WawkeHA23XuW3QvE3iWiLr2Yfr1CWmoXHuaWWQXPCoKrcM", + "description": "Setting send library for eid 40161 (SEPOLIA_V2_TESTNET) and OApp 44F6EuNhHYmt7JRXvjzw5vJjGogdeVHRw1BQBEQ9NxBT to 2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB", + "originalDataHex": "02010407f23bf4fe73594d8af557a0f5fdd6956b808756480452785478b954c4861c6b37fc19f37e958f0be82a7f94b3eb813f1df663d729d58ce5d2eead16dfb1f77e9644b9af574fdccec2375db639245776cb2daff308a0b8d7a5e089b647e4c044435028c962eabfc37fc41989847b01895cb34969b6e33ef766cad63d922de5879e5aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18b7c87b0e6b4083fb9dc50b6fa98e3cbc1340cd41d2995c868cb26e6d06ffa8160d1dd86ac361b6252c406c281f3912ab13b924126c011b587278e8af0b08ef09b2a9af36c0dc0a490c2228abd3d2b746a78e6f7ff2d3e246189ca2b7e2c2bdef10104060105020306044cfb764e9e869581052d67bc3658a01f0597729a6ffff5d9580f72c15fd1cd2e538f8de2cdc5ffd982e19c00002515806648630228f165e86b6a6e0469117511850390dcf03f5bb7dd2f9b92f6" + }, + { + "point": { + "eid": 40168, + "address": "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6" + }, + "data": "4iY9PieS2uas1FXQnN2CVgZcaQGF8UgxQG1hNn4KmZjA3yZhgF6j7aFUmPiqBHbwYdXECdL7x7WM52tQCYU5QiNDWc8rYFmvUn4XDhzcLBde5PQ1vKU4DGUD8uG9Va5rYdfEBvAAAjabtpubbxb5ZPRcqugAmmDCUwyutZQZG6dxWd2tdL28LGvZntKpSHJTkcPuHiycU1p95TiJ4ZgcGnne6uWNNmGtRN76TFRRkFF7MhbFku1BjMdQXu7pWHrvFav143E2BGP6xrvGVrDCTsjiXun5usFPQibng7jDHEGH9eJ3EC2tVcNpbt3uCjXNGwag5ktQjdsuS5JJ5TJuokWFnsA2fhuzCiiUdFYRE8oCiitLWWd1K6vfaAcJF233uu5J42dEyibuTBVw2JXdbYXLksnNZiUiBVnbR1T4cX36BLxy8Cg2HNErouSX8VsH3D5Q1TwPdjpzwHsAGSpiaUnZ", + "description": "Setting send library for eid 40362 (HYPERLIQUID_V2_TESTNET) and OApp 44F6EuNhHYmt7JRXvjzw5vJjGogdeVHRw1BQBEQ9NxBT to 2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB", + "originalDataHex": "02010407f23bf4fe73594d8af557a0f5fdd6956b808756480452785478b954c4861c6b37fc19f37e958f0be82a7f94b3eb813f1df663d729d58ce5d2eead16dfb1f77e96e82b8cdb1a53a209c8ef64670c953eb00282be791ce69c584a73f42bd9b21e145028c962eabfc37fc41989847b01895cb34969b6e33ef766cad63d922de5879e5aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18b7c87b0e6b4083fb9dc50b6fa98e3cbc1340cd41d2995c868cb26e6d06ffa8160d1dd86ac361b6252c406c281f3912ab13b924126c011b587278e8af0b08ef09b2a9af36c0dc0a490c2228abd3d2b746a78e6f7ff2d3e246189ca2b7e2c2bdef10104060105020306044cfb764e9e869581052d67bc3658a01f0597729a6ffff5d9580f72c15fd1cd2e538f8de2cdc5ffd982aa9d00002515806648630228f165e86b6a6e0469117511850390dcf03f5bb7dd2f9b92f6" + } +] \ No newline at end of file diff --git a/tx-data/solana-devnet-dewire-txs.log b/tx-data/solana-devnet-dewire-txs.log new file mode 100644 index 0000000..e0ad585 --- /dev/null +++ b/tx-data/solana-devnet-dewire-txs.log @@ -0,0 +1,18 @@ +[ + { + "point": { + "eid": 40168, + "address": "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6" + }, + "data": "02010407f23bf4fe73594d8af557a0f5fdd6956b808756480452785478b954c4861c6b37fc19f37e958f0be82a7f94b3eb813f1df663d729d58ce5d2eead16dfb1f77e9644b9af574fdccec2375db639245776cb2daff308a0b8d7a5e089b647e4c044435028c962eabfc37fc41989847b01895cb34969b6e33ef766cad63d922de5879e5aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18b7c87b0e6b4083fb9dc50b6fa98e3cbc1340cd41d2995c868cb26e6d06ffa8160d1dd86ac361b6252c406c281f3912ab13b924126c011b587278e8af0b08ef09b2a9af36c0dc0a490c2228abd3d2b746a78e6f7ff2d3e246189ca2b7e2c2bdef10104060105020306044cfb764e9e869581052d67bc3658a01f0597729a6ffff5d9580f72c15fd1cd2e538f8de2cdc5ffd982e19c00002515806648630228f165e86b6a6e0469117511850390dcf03f5bb7dd2f9b92f6", + "description": "Setting send library for eid 40161 (SEPOLIA_V2_TESTNET) and OApp 44F6EuNhHYmt7JRXvjzw5vJjGogdeVHRw1BQBEQ9NxBT to 2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB" + }, + { + "point": { + "eid": 40168, + "address": "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6" + }, + "data": "02010407f23bf4fe73594d8af557a0f5fdd6956b808756480452785478b954c4861c6b37fc19f37e958f0be82a7f94b3eb813f1df663d729d58ce5d2eead16dfb1f77e96e82b8cdb1a53a209c8ef64670c953eb00282be791ce69c584a73f42bd9b21e145028c962eabfc37fc41989847b01895cb34969b6e33ef766cad63d922de5879e5aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18b7c87b0e6b4083fb9dc50b6fa98e3cbc1340cd41d2995c868cb26e6d06ffa8160d1dd86ac361b6252c406c281f3912ab13b924126c011b587278e8af0b08ef09b2a9af36c0dc0a490c2228abd3d2b746a78e6f7ff2d3e246189ca2b7e2c2bdef10104060105020306044cfb764e9e869581052d67bc3658a01f0597729a6ffff5d9580f72c15fd1cd2e538f8de2cdc5ffd982aa9d00002515806648630228f165e86b6a6e0469117511850390dcf03f5bb7dd2f9b92f6", + "description": "Setting send library for eid 40362 (HYPERLIQUID_V2_TESTNET) and OApp 44F6EuNhHYmt7JRXvjzw5vJjGogdeVHRw1BQBEQ9NxBT to 2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB" + } +] \ No newline at end of file diff --git a/tx-data/solana-mainnet-dewire-txs.base58.json b/tx-data/solana-mainnet-dewire-txs.base58.json new file mode 100644 index 0000000..21d3a70 --- /dev/null +++ b/tx-data/solana-mainnet-dewire-txs.base58.json @@ -0,0 +1,29 @@ +[ + { + "point": { + "eid": 30168, + "address": "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6" + }, + "data": "4iY9PcUZrmJd7uvzQJDFA6L1HjkqEMTXPZnus7xfeyNTxazKpnV9gDLH3ofaijV2vvuUDojd7AbyVckDG8aHtqkcTAdPGkvc8WZh1L1nvQd3QaF6PqSQnBWPuQqqPRxPRNLNsBCLbbFF6NwXBUhByr8WLP5ceGjS2caW5f5MSm8YXLTbpaLsEv6TsCXtmoRBR52zovDqmmstAgPJwX3jBSzcZbrikjvX42DVVAEf1Ro29aXqroeS4o4gbtePHvaS6FkiHZTM3tBcfwyzd7H4nV3hF5C2L7jVAHiBGL6rVkduouN6aUq8UFH1euoWNECGTdhuejHgfVsF6SZzKbr1RvKhZJsPYVfx7YatCaQyRegpMomyTPQp1nsskRj5rG7p2hrG7Tfe3YHQXBuZBLASa44gDVj3zcHwBiBhvEpfNQoEpwqnb9SAV6NLJKyrd52rPJ4xGeC3jECWmwEF5TbYXkM3", + "description": "Setting send library for eid 30101 (ETHEREUM_V2_MAINNET) and OApp GKzT5jtvcysvWoRN7Kgro1nqriS6QhHjyqrtL6UNK89t to 2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB", + "originalDataHex": "02010407dc7632e1bb58b2687df7047262cb0f08f7aa27264ce1acdd0d902d6e5869cacbd5d284a0c602de8a0e767cff40debc9419a2a335928a53cc606ac916c46221fd94d99e2a34a1d85d756cd749905d5996c02fd7a439ddf525cd78a9f18fe584615028c962eabfc37fc41989847b01895cb34969b6e33ef766cad63d922de5879e5aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18bba53f930024a21e928a4d50a5e2db4c08547e9632fe33eae8533abf150426e2ad1dd86ac361b6252c406c281f3912ab13b924126c011b587278e8af0b08ef09b20076b0dd38cec194c9c1bb50129c1f66ce11ec8ef08f1808af8471435d9c0ee0104060105020306044cfb764e9e86958105e3bcb78ee78ca0a9ae2d7a92e4af89cf09361b43617ffbfd8ca585624e2042bf957500002515806648630228f165e86b6a6e0469117511850390dcf03f5bb7dd2f9b92f6" + }, + { + "point": { + "eid": 30168, + "address": "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6" + }, + "data": "4iY9PcUZrmJd7uvzQJDFA6L1HjkqEMTXPZnus7xfeyNTxazKpnV9gDLH3ofaijV2vvuUDojd7AbyVckDG8aHtqkcTAdPMKG3PywHTbkc8WSbv1RDq769TsoihxHcERWUgnnz8B5syZg5g6WPv72DCi5RFwtVoQNaK5FUFu1uG3qsmWHJcHqxYte7HLEcE2GFc1RTEaxVaG1ntmNg6avbt6E8Ci8CEdoTvVo8h4NkGktHpSvZHhNk43xCrfp7xsydnKgztzrZ2qGTteE6hRQ6gHtHqK16MAGxcWVWPCsWfB1QxiuQUoxkRW3qrtMrgp57RyXneLKrZpq5CmBorGiuvKjDvhKGgg59qgdh3xLayoWFK5pyFJWLpGWvyNHVvyF29dB16iP2WHAhbRE3xYDURLBk1MPdGoyjQvdQ1n2vhyCQXtbVc2YBH928SD6t7HcGc2x1vmpEN9MvMR1fjynmfQkm", + "description": "Setting send library for eid 30367 (HYPERLIQUID_V2_MAINNET) and OApp GKzT5jtvcysvWoRN7Kgro1nqriS6QhHjyqrtL6UNK89t to 2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB", + "originalDataHex": "02010407dc7632e1bb58b2687df7047262cb0f08f7aa27264ce1acdd0d902d6e5869cacbd5d284a0c602de8a0e767cff40debc9419a2a335928a53cc606ac916c46221fde729a0d1594db54bb44b3913de2c4417bc90fa8629d95f6822ae18797fef45b95028c962eabfc37fc41989847b01895cb34969b6e33ef766cad63d922de5879e5aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18bba53f930024a21e928a4d50a5e2db4c08547e9632fe33eae8533abf150426e2ad1dd86ac361b6252c406c281f3912ab13b924126c011b587278e8af0b08ef09b20076b0dd38cec194c9c1bb50129c1f66ce11ec8ef08f1808af8471435d9c0ee0104060105020306044cfb764e9e86958105e3bcb78ee78ca0a9ae2d7a92e4af89cf09361b43617ffbfd8ca585624e2042bf9f7600002515806648630228f165e86b6a6e0469117511850390dcf03f5bb7dd2f9b92f6" + }, + { + "point": { + "eid": 30168, + "address": "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6" + }, + "data": "4iY9PcUZrmJd7uvzQJDFA6L1HjkqEMTXPZnus7xfeyNTxazKpnV9gDLH3ofaijV2vvuUDojd7AbyVckDG8aHtqkcTAdPLYvJempKsyCpvMVgdkQiCFGUxKhGktMZqKARB2LkZbqmimmkihivth56AC8uT3YxLqgpXBpeivYR8sjinzjJFMU4mb3N4efFfXY7kcBf2auTHkziBgweNe1Q9X7pbtgd3MBpcJH9ycxJutMgLBtKSoQEjL9eFnVih1yk8181JQZbLp9dCqQx2Yd8G5d3ki5urdmzxCwd3fTbwWn4JeXgi7EUmAeDgmsQBA8rjt3rLZnyoSgVPbbWDJ7hHsGAJzyE7vqU6i32hzDNFmnqCZRsr9PsuFkKgjzvVgioNRkwK8w1eZa3DAhcBsDT3sKaeYdAbjRapK4wJzU6wLG7jJkQP9jKTgprUK9b6EjMVa1eWV7Q4NJBVb1KjMRLPbRX", + "description": "Setting send library for eid 30111 (OPTIMISM_V2_MAINNET) and OApp GKzT5jtvcysvWoRN7Kgro1nqriS6QhHjyqrtL6UNK89t to 2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB", + "originalDataHex": "02010407dc7632e1bb58b2687df7047262cb0f08f7aa27264ce1acdd0d902d6e5869cacbd5d284a0c602de8a0e767cff40debc9419a2a335928a53cc606ac916c46221fdd95af394ff73799fcdc61255ccbd2cd4cffba394b14b4c4ddb5f1545b19996d85028c962eabfc37fc41989847b01895cb34969b6e33ef766cad63d922de5879e5aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18bba53f930024a21e928a4d50a5e2db4c08547e9632fe33eae8533abf150426e2ad1dd86ac361b6252c406c281f3912ab13b924126c011b587278e8af0b08ef09b20076b0dd38cec194c9c1bb50129c1f66ce11ec8ef08f1808af8471435d9c0ee0104060105020306044cfb764e9e86958105e3bcb78ee78ca0a9ae2d7a92e4af89cf09361b43617ffbfd8ca585624e2042bf9f7500002515806648630228f165e86b6a6e0469117511850390dcf03f5bb7dd2f9b92f6" + } +] \ No newline at end of file diff --git a/tx-data/solana-mainnet-dewire-txs.log b/tx-data/solana-mainnet-dewire-txs.log new file mode 100644 index 0000000..ef6b7d5 --- /dev/null +++ b/tx-data/solana-mainnet-dewire-txs.log @@ -0,0 +1,26 @@ +[ + { + "point": { + "eid": 30168, + "address": "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6" + }, + "data": "02010407dc7632e1bb58b2687df7047262cb0f08f7aa27264ce1acdd0d902d6e5869cacbd5d284a0c602de8a0e767cff40debc9419a2a335928a53cc606ac916c46221fd94d99e2a34a1d85d756cd749905d5996c02fd7a439ddf525cd78a9f18fe584615028c962eabfc37fc41989847b01895cb34969b6e33ef766cad63d922de5879e5aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18bba53f930024a21e928a4d50a5e2db4c08547e9632fe33eae8533abf150426e2ad1dd86ac361b6252c406c281f3912ab13b924126c011b587278e8af0b08ef09b20076b0dd38cec194c9c1bb50129c1f66ce11ec8ef08f1808af8471435d9c0ee0104060105020306044cfb764e9e86958105e3bcb78ee78ca0a9ae2d7a92e4af89cf09361b43617ffbfd8ca585624e2042bf957500002515806648630228f165e86b6a6e0469117511850390dcf03f5bb7dd2f9b92f6", + "description": "Setting send library for eid 30101 (ETHEREUM_V2_MAINNET) and OApp GKzT5jtvcysvWoRN7Kgro1nqriS6QhHjyqrtL6UNK89t to 2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB" + }, + { + "point": { + "eid": 30168, + "address": "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6" + }, + "data": "02010407dc7632e1bb58b2687df7047262cb0f08f7aa27264ce1acdd0d902d6e5869cacbd5d284a0c602de8a0e767cff40debc9419a2a335928a53cc606ac916c46221fde729a0d1594db54bb44b3913de2c4417bc90fa8629d95f6822ae18797fef45b95028c962eabfc37fc41989847b01895cb34969b6e33ef766cad63d922de5879e5aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18bba53f930024a21e928a4d50a5e2db4c08547e9632fe33eae8533abf150426e2ad1dd86ac361b6252c406c281f3912ab13b924126c011b587278e8af0b08ef09b20076b0dd38cec194c9c1bb50129c1f66ce11ec8ef08f1808af8471435d9c0ee0104060105020306044cfb764e9e86958105e3bcb78ee78ca0a9ae2d7a92e4af89cf09361b43617ffbfd8ca585624e2042bf9f7600002515806648630228f165e86b6a6e0469117511850390dcf03f5bb7dd2f9b92f6", + "description": "Setting send library for eid 30367 (HYPERLIQUID_V2_MAINNET) and OApp GKzT5jtvcysvWoRN7Kgro1nqriS6QhHjyqrtL6UNK89t to 2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB" + }, + { + "point": { + "eid": 30168, + "address": "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6" + }, + "data": "02010407dc7632e1bb58b2687df7047262cb0f08f7aa27264ce1acdd0d902d6e5869cacbd5d284a0c602de8a0e767cff40debc9419a2a335928a53cc606ac916c46221fdd95af394ff73799fcdc61255ccbd2cd4cffba394b14b4c4ddb5f1545b19996d85028c962eabfc37fc41989847b01895cb34969b6e33ef766cad63d922de5879e5aad76da514b6e1dcf11037e904dac3d375f525c9fbafcb19507b78907d8c18bba53f930024a21e928a4d50a5e2db4c08547e9632fe33eae8533abf150426e2ad1dd86ac361b6252c406c281f3912ab13b924126c011b587278e8af0b08ef09b20076b0dd38cec194c9c1bb50129c1f66ce11ec8ef08f1808af8471435d9c0ee0104060105020306044cfb764e9e86958105e3bcb78ee78ca0a9ae2d7a92e4af89cf09361b43617ffbfd8ca585624e2042bf9f7500002515806648630228f165e86b6a6e0469117511850390dcf03f5bb7dd2f9b92f6", + "description": "Setting send library for eid 30111 (OPTIMISM_V2_MAINNET) and OApp GKzT5jtvcysvWoRN7Kgro1nqriS6QhHjyqrtL6UNK89t to 2XrYqmhBMPJgDsb4SVbjV1PnJBprurd5bzRCkHwiFCJB" + } +] \ No newline at end of file diff --git a/utils/convertToBase58.ts b/utils/convertToBase58.ts new file mode 100644 index 0000000..fc72f6d --- /dev/null +++ b/utils/convertToBase58.ts @@ -0,0 +1,87 @@ +import * as fs from 'fs' +import * as path from 'path' + +import bs58 from 'bs58' + +interface Transaction { + point: { + eid: number + address: string + } + data: string + description: string +} + +/** + * Converts hex-encoded transaction data to base58 format + * @param inputFile - Path to the input JSON file + * @param outputFile - Optional path to the output JSON file (defaults to input file with .base58.json suffix) + */ +function convertToBase58(inputFile: string, outputFile?: string): void { + // Read the input file + const inputPath = path.resolve(inputFile) + if (!fs.existsSync(inputPath)) { + throw new Error(`Input file not found: ${inputPath}`) + } + + const fileContent = fs.readFileSync(inputPath, 'utf-8') + const transactions: Transaction[] = JSON.parse(fileContent) + + // Convert each transaction's data field from hex to base58 + const convertedTransactions = transactions.map((tx) => { + // Remove '0x' prefix if present + const hexData = tx.data.startsWith('0x') ? tx.data.slice(2) : tx.data + + // Convert hex string to Buffer, then to Uint8Array + const buffer = Buffer.from(hexData, 'hex') + const uint8Array = new Uint8Array(buffer) + + // Convert Uint8Array to base58 + const base58Data = bs58.encode(uint8Array) + + return { + ...tx, + data: base58Data, + originalDataHex: tx.data, // Keep original for reference + } + }) + + // Determine output file path + const outputPath = outputFile ? path.resolve(outputFile) : inputPath.replace(/\.(json|log)$/, '.base58.json') + + // Write the converted data + fs.writeFileSync(outputPath, JSON.stringify(convertedTransactions, null, 2), 'utf-8') + + console.log(`✓ Converted ${convertedTransactions.length} transactions`) + console.log(`✓ Output written to: ${outputPath}`) + + // Print first transaction as example + if (convertedTransactions.length > 0) { + console.log('\nExample conversion:') + console.log(` Original (hex): ${convertedTransactions[0].originalDataHex.substring(0, 50)}...`) + console.log(` Converted (base58): ${convertedTransactions[0].data}`) + } +} + +// Main execution +if (require.main === module) { + const args = process.argv.slice(2) + + if (args.length === 0) { + console.error('Usage: ts-node convertToBase58.ts [output-file]') + console.error('Example: ts-node convertToBase58.ts mainnet-dewire-txs.log') + process.exit(1) + } + + const inputFile = args[0] + const outputFile = args[1] + + try { + convertToBase58(inputFile, outputFile) + } catch (error) { + console.error('Error:', error instanceof Error ? error.message : error) + process.exit(1) + } +} + +export { convertToBase58 } diff --git a/utils/generateSafeTxs.ts b/utils/generateSafeTxs.ts new file mode 100644 index 0000000..d81bffb --- /dev/null +++ b/utils/generateSafeTxs.ts @@ -0,0 +1,143 @@ +import * as fs from 'fs' +import * as path from 'path' + +import { getOwnerAddress } from '../consts/mainnet' + +interface Transaction { + point: { + eid: number + address: string + } + data: string + description: string +} + +interface SafeTransaction { + to: string + value: string + data: string + operation: number +} + +interface SafeTransactionBuilder { + version: string + chainId: string + createdAt: number + meta: { + name: string + description: string + txBuilderVersion: string + createdFromSafeAddress: string + } + transactions: SafeTransaction[] +} + +// Mapping from EID to chainId and network name +const EID_TO_CHAIN_CONFIG: Record = { + 30101: { chainId: '1', networkName: 'ethereum-mainnet' }, + 30367: { chainId: '999', networkName: 'hyperevm-mainnet' }, + 30111: { chainId: '10', networkName: 'optimism-mainnet' }, +} + +const TX_BUILDER_VERSION = '1.17.1' + +/** + * Generates Safe transaction builder compatible JSON files for each EID + * @param inputFile - Path to the input JSON log file + * @param outputDir - Directory to write output files (defaults to tx-data directory) + */ +function generateSafeTxs(inputFile: string, outputDir?: string): void { + // Read the input file + const inputPath = path.resolve(inputFile) + if (!fs.existsSync(inputPath)) { + throw new Error(`Input file not found: ${inputPath}`) + } + + const fileContent = fs.readFileSync(inputPath, 'utf-8') + const transactions: Transaction[] = JSON.parse(fileContent) + + // Determine output directory + const defaultOutputDir = path.resolve(path.dirname(inputPath)) + const outputDirectory = outputDir ? path.resolve(outputDir) : defaultOutputDir + + // Group transactions by EID + const transactionsByEid: Record = {} + for (const tx of transactions) { + const eid = tx.point.eid + if (!transactionsByEid[eid]) { + transactionsByEid[eid] = [] + } + transactionsByEid[eid].push(tx) + } + + // Generate a Safe transaction builder file for each EID + for (const [eidStr, txs] of Object.entries(transactionsByEid)) { + const eid = parseInt(eidStr, 10) + const config = EID_TO_CHAIN_CONFIG[eid] + + if (!config) { + console.warn(`⚠️ No chain configuration found for EID ${eid}, skipping...`) + continue + } + + // Convert transactions to Safe transaction format + const safeTransactions: SafeTransaction[] = txs.map((tx) => ({ + to: tx.point.address, + value: '0', + data: tx.data, + operation: 0, + })) + + // Get the owner address for this EID + const safeAddress = getOwnerAddress(eid) + + // Create Safe transaction builder JSON + const safeTxBuilder: SafeTransactionBuilder = { + version: '1.0', + chainId: config.chainId, + createdAt: Date.now(), + meta: { + name: `LayerZero Wire Configuration - ${config.networkName}`, + description: `Transaction for LayerZero OApp wiring on ${config.networkName}`, + txBuilderVersion: TX_BUILDER_VERSION, + createdFromSafeAddress: safeAddress, + }, + transactions: safeTransactions, + } + + // Write output file + const outputFileName = `${config.networkName}-txs.json` + const outputPath = path.join(outputDirectory, outputFileName) + fs.writeFileSync(outputPath, JSON.stringify(safeTxBuilder, null, 2), 'utf-8') + + console.log(`✓ Generated ${outputFileName} for EID ${eid} (${config.networkName})`) + console.log(` - Chain ID: ${config.chainId}`) + console.log(` - Transactions: ${safeTransactions.length}`) + } + + console.log(`\n✓ Generated ${Object.keys(transactionsByEid).length} Safe transaction builder file(s)`) + console.log(`✓ Output directory: ${outputDirectory}`) +} + +// Main execution +if (require.main === module) { + const args = process.argv.slice(2) + + if (args.length === 0) { + console.error('Usage: ts-node generateSafeTxs.ts [output-dir]') + console.error('Example: ts-node generateSafeTxs.ts tx-data/all-evm-mainnet-txs.log') + process.exit(1) + } + + const inputFile = args[0] + const outputDir = args[1] + + try { + generateSafeTxs(inputFile, outputDir) + } catch (error) { + console.error('Error:', error instanceof Error ? error.message : error) + process.exit(1) + } +} + +export { generateSafeTxs }