From dda597e2f4f40191e9ba509fbd2832e24fd685d8 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Wed, 17 Jan 2024 18:50:14 +0530 Subject: [PATCH 01/19] IBridge: Setup Initial Locking and Claiming Functionality --- package.json | 1 + src/config/chainSpecs.ts | 28 +- .../components/handleValidatorAddition.ts | 3 +- .../utils/getEvmLockListenerHandler.ts | 10 +- .../utils/getHederaLockListenerHandler.ts | 8 +- src/types/index.ts | 22 +- src/utils/functions/getEvmBridgeContract.ts | 18 +- .../functions/getHederaBridgeContract.ts | 18 +- .../functions/getMultiversXBridgeContract.ts | 342 +++++++++++++++++- .../functions/getSecretBridgeContract.ts | 12 +- src/utils/functions/getTezosBridgeContract.ts | 32 +- src/utils/functions/getTonBridgeContract.ts | 12 +- 12 files changed, 468 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 6699b353..00d02f5d 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@types/mocha": "^10.0.3", "@types/web3": "^1.2.2", "axios": "^1.6.0", + "bignumber.js": "^9.1.2", "bip39": "^3.1.0", "borsh": "^1.0.0", "bullmq": "^4.12.5", diff --git a/src/config/chainSpecs.ts b/src/config/chainSpecs.ts index 0c8aed60..9f3dfea2 100644 --- a/src/config/chainSpecs.ts +++ b/src/config/chainSpecs.ts @@ -18,7 +18,7 @@ const storageTestnetConfig: IEvmChainConfig = { lastBlock: 17608314, }; -const bridgeTestChains: TChain[] = [ +const bridgeTestChains = [ { chain: 'BSC', rpcURL: 'https://bsc-testnet.publicnode.com', @@ -76,16 +76,16 @@ const bridgeTestChains: TChain[] = [ // chainId: 'pulsar-3', // lastBlock: 50883 // }, - // { - // chain: "TEZOS", - // rpcURL: "https://ghostnet.ecadinfra.com", - // restApiURL: "https://api.ghostnet.tzkt.io", - // contractAddress: "KT1NHxTSXAFKH2y94PpfqDsg4bZ5SiF2V8a4", - // intialFund: "50000", - // lastBlock: 5058309, - // nativeCoinSymbol: "XTZ", - // chainType: "tezos" - // }, + { + chain: 'TEZOS', + rpcURL: 'https://ghostnet.ecadinfra.com', + restApiURL: 'https://api.ghostnet.tzkt.io', + contractAddress: 'KT1NHxTSXAFKH2y94PpfqDsg4bZ5SiF2V8a4', + intialFund: '50000', + lastBlock: 5058309, + nativeCoinSymbol: 'XTZ', + chainType: 'tezos', + }, { chain: 'HEDERA', rpcURL: 'https://testnet.hashio.io/api', @@ -96,7 +96,7 @@ const bridgeTestChains: TChain[] = [ lastBlock: 7095475, royaltyInfoProxyAddress: '0x870f7b68c0a64733dcF4D95E5C06aa34387B98BF', }, -]; +] as const satisfies readonly TChain[]; const stakingTestChain: IStakingConfig = { chain: 'BSC', @@ -111,7 +111,7 @@ const stakingTestChain: IStakingConfig = { }; const testnetBridgeConfig: IBridgeConfig = { - bridgeChains: bridgeTestChains, + bridgeChains: bridgeTestChains as unknown as TChain[], storageConfig: storageTestnetConfig, stakingConfig: stakingTestChain, }; @@ -169,4 +169,6 @@ const prodBridgeConfig: IBridgeConfig = { const BLOCK_CHUNKS = 1000; +export type SupportedChains = (typeof bridgeTestChains)[number]['chain']; + export { BLOCK_CHUNKS, testnetBridgeConfig, prodBridgeConfig }; diff --git a/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts b/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts index c6d55056..77363015 100644 --- a/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts +++ b/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts @@ -35,7 +35,8 @@ const handleValidatorAddition = async ({ let failiure = true; - let bridgeContract: IBridge; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let bridgeContract: IBridge; let publicWalletAddress: string; let isChainFunded: () => Promise; diff --git a/src/modules/validator/components/nftLockListener/components/evmLockListener/utils/getEvmLockListenerHandler.ts b/src/modules/validator/components/nftLockListener/components/evmLockListener/utils/getEvmLockListenerHandler.ts index a739e2d6..b333f656 100644 --- a/src/modules/validator/components/nftLockListener/components/evmLockListener/utils/getEvmLockListenerHandler.ts +++ b/src/modules/validator/components/nftLockListener/components/evmLockListener/utils/getEvmLockListenerHandler.ts @@ -1,25 +1,23 @@ import { LogEntry } from '@src/modules/validator/utils/evmContractListener/types'; -import { getEvmBridgeContract, getStorageContract } from '@src/utils'; +import { getStorageContract } from '@src/utils'; import { getLockEventDecodedLog } from '.'; import { IEvmLockListener } from '../../../types'; import { getNftDetails } from '../../../utils'; import { approveLock } from '../..'; import { INftTransferDetailsObject } from '../../types'; +import { Bridge__factory } from '@src/contractsTypes'; const getEvmLockListenerHandler = ({ config, evmChainConfig, wallets, }: IEvmLockListener) => { - const bridgeContract = getEvmBridgeContract({ - evmChainConfig, - evmWallet: wallets.evmWallet, - }); const storageContract = getStorageContract({ evmChainConfig: config.storageConfig, evmWallet: wallets.evmWallet, }); - const { topicHash } = bridgeContract.interface.getEvent('Locked'); + const BI = Bridge__factory.createInterface(); + const { topicHash } = BI.getEvent('Locked'); const handleLog = async ({ log }: { log: LogEntry }) => { // if its not the lock nft event we early return diff --git a/src/modules/validator/components/nftLockListener/components/hederaLockListener/utils/getHederaLockListenerHandler.ts b/src/modules/validator/components/nftLockListener/components/hederaLockListener/utils/getHederaLockListenerHandler.ts index 33d716c9..99c101b7 100644 --- a/src/modules/validator/components/nftLockListener/components/hederaLockListener/utils/getHederaLockListenerHandler.ts +++ b/src/modules/validator/components/nftLockListener/components/hederaLockListener/utils/getHederaLockListenerHandler.ts @@ -4,23 +4,19 @@ import { IHederaLockListener } from '../../../types'; import { getNftDetails } from '../../../utils'; import { approveLock } from '../..'; import { INftTransferDetailsObject } from '../../types'; -import { getHederaBridgeContract } from '@src/utils'; import { getLockEventDecodedLog } from '../../evmLockListener/utils'; +import { Bridge__factory } from '@src/contractsTypes'; const getHederaLockListenerHandler = ({ config, hederaChainConfig, wallets, }: IHederaLockListener) => { - const bridgeContract = getHederaBridgeContract({ - hederaChainConfig, - evmWallet: wallets.evmWallet, - }); const storageContract = getStorageContract({ evmChainConfig: config.storageConfig, evmWallet: wallets.evmWallet, }); - const { topicHash } = bridgeContract.interface.getEvent('Locked'); + const { topicHash } = Bridge__factory.createInterface().getEvent('Locked'); const handleLog = async ({ log }: { log: LogEntry }) => { // if its not the lock nft event we early return diff --git a/src/types/index.ts b/src/types/index.ts index 08e29200..911be41f 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,5 @@ +import { SupportedChains } from '@src/config/chainSpecs'; + type ISecretKeyCrypto = { ciphertext: string; cipherparams: { @@ -209,7 +211,7 @@ type IBridgeConfig = { stakingConfig: IStakingConfig; }; -type IBridge = { +type IBridge = { validators: (address: string) => Promise<{ added: boolean }>; validatorsCount: () => Promise; addValidator: ( @@ -219,6 +221,24 @@ type IBridge = { signature: string; }[], ) => Promise<{ hash: string; wait: () => Promise }>; + lock721: ( + ...lockArgs: TLockArgs + ) => Promise<{ hash: string; wait: () => Promise }>; + lock1155?: ( + sourceNftContractAddress: string, + tokenId: string, + destinationChain: SupportedChains, + address: string, + amt: bigint, + ) => Promise<{ hash: string; wait: () => Promise }>; + claimNFT721: ( + nftTransferData: TClaimData, + sigs: TSig[], + ) => Promise<{ hash: string; wait: () => Promise }>; + claimNFT1155?: ( + nftTransferData: TClaimData, + sigs: TSig[], + ) => Promise<{ hash: string; wait: () => Promise }>; }; type INftContract = { diff --git a/src/utils/functions/getEvmBridgeContract.ts b/src/utils/functions/getEvmBridgeContract.ts index c1be1c9e..78d48064 100644 --- a/src/utils/functions/getEvmBridgeContract.ts +++ b/src/utils/functions/getEvmBridgeContract.ts @@ -1,11 +1,23 @@ -import { ethers } from 'ethers'; +import { BytesLike, ethers } from 'ethers'; import { Bridge, Bridge__factory } from '../../contractsTypes'; -import { IEvmChainConfigAndEvmWallet } from '@src/types'; +import { IBridge, IEvmChainConfigAndEvmWallet } from '@src/types'; +import { SupportedChains } from '@src/config/chainSpecs'; + +export type EvmLockArgs = [ + sourceNftContractAddress: string, + tokenId: string, + destinationChain: SupportedChains, + address: string, +]; const getEvmBridgeContract = ({ evmChainConfig, evmWallet, -}: IEvmChainConfigAndEvmWallet): Bridge => { +}: IEvmChainConfigAndEvmWallet): IBridge< + EvmLockArgs, + Bridge.ClaimDataStruct, + BytesLike +> => { const provider = new ethers.JsonRpcProvider(evmChainConfig.rpcURL); const wallet = new ethers.Wallet(evmWallet.privateKey, provider); return Bridge__factory.connect(evmChainConfig.contractAddress, wallet); diff --git a/src/utils/functions/getHederaBridgeContract.ts b/src/utils/functions/getHederaBridgeContract.ts index c6e01064..fa07388e 100644 --- a/src/utils/functions/getHederaBridgeContract.ts +++ b/src/utils/functions/getHederaBridgeContract.ts @@ -1,11 +1,23 @@ -import { ethers } from 'ethers'; +import { BytesLike, ethers } from 'ethers'; import { Bridge, Bridge__factory } from '../../contractsTypes'; -import { IHederaChainConfigAndEvmWallet } from '@src/types'; +import { IBridge, IHederaChainConfigAndEvmWallet } from '@src/types'; +import { SupportedChains } from '@src/config/chainSpecs'; + +export type HederaLockArgs = [ + sourceNftContractAddress: string, + tokenId: string, + destinationChain: SupportedChains, + address: string, +]; const getHederaBridgeContract = ({ hederaChainConfig, evmWallet, -}: IHederaChainConfigAndEvmWallet): Bridge => { +}: IHederaChainConfigAndEvmWallet): IBridge< + HederaLockArgs, + Bridge.ClaimDataStruct, + BytesLike +> => { const provider = new ethers.JsonRpcProvider(hederaChainConfig.rpcURL); const wallet = new ethers.Wallet(evmWallet.privateKey, provider); return Bridge__factory.connect(hederaChainConfig.contractAddress, wallet); diff --git a/src/utils/functions/getMultiversXBridgeContract.ts b/src/utils/functions/getMultiversXBridgeContract.ts index f5481d76..74d7f9ca 100644 --- a/src/utils/functions/getMultiversXBridgeContract.ts +++ b/src/utils/functions/getMultiversXBridgeContract.ts @@ -2,10 +2,21 @@ import { AbiRegistry, Account, Address, + AddressType, AddressValue, + BigUIntType, + BigUIntValue, + BytesType, BytesValue, + Field, + FieldDefinition, ResultsParser, SmartContract, + Struct, + StructType, + Transaction, + TransactionPayload, + VariadicValue, } from '@multiversx/sdk-core'; import { multiversXBridgeABI } from '@src/abi'; import { IBridge, IMultiversXChainConfigAndMultiversXWallet } from '@src/types'; @@ -13,11 +24,46 @@ import { ProxyNetworkProvider } from '@multiversx/sdk-network-providers'; import { UserSigner } from '@multiversx/sdk-wallet/out'; import { ProcessDelayMilliseconds } from '../constants/processDelayMilliseconds'; import waitForMSWithMsg from './waitForMSWithMsg'; +import { SupportedChains } from '@src/config/chainSpecs'; +import { Nonce } from '@multiversx/sdk-network-providers/out/primitives'; +import BigNumber from 'bignumber.js'; + +export type MultiversXLockArgs = [ + sourceNftContractAddress: string, + nonce: string, + destinationChain: SupportedChains, + address: string, + tokenId: string, +]; +export type ClaimStruct = { + tokenId: string; + sourceChain: string; + destinationChain: string; + destinationUserAddress: string; + sourceNftContractAddress: string; + name: string; + symbol: string; + royalty: string; + royaltyReceiver: string; + attrs: string; + transactionHash: string; + tokenAmount: string; + nftType: string; + fee: string; + metadata: string; +}; const getMultiversXBridgeContract = ({ multiversXChainConfig, multiversXWallet, -}: IMultiversXChainConfigAndMultiversXWallet): IBridge => { +}: IMultiversXChainConfigAndMultiversXWallet): IBridge< + MultiversXLockArgs, + ClaimStruct, + { + signerAddress: string; + signature: string; + } +> => { const abiRegistry = AbiRegistry.create(multiversXBridgeABI); const proxyNetworkProvider = new ProxyNetworkProvider( @@ -33,6 +79,300 @@ const getMultiversXBridgeContract = ({ }); return { + lock721: async (srcNftAddr, nonce, destChain, destAddress, tokenId) => { + const ba = new Address(multiversXChainConfig.contractAddress); + try { + const signer = UserSigner.fromWallet( + multiversXWallet.userWallet, + multiversXWallet.password, + ); + + const userAddress = new Address( + multiversXWallet.userWallet.bech32, + ); + const userAccount = new Account(userAddress); + const userOnNetwork = + await proxyNetworkProvider.getAccount(userAddress); + userAccount.update(userOnNetwork); + + const collectionIdentifiers = + '@' + Buffer.from(srcNftAddr).toString('hex'); + const noncec = '@' + nonce; + const quantity = '@' + '01'; + const destination_address = '@' + ba.hex(); + const method = '@' + Buffer.from('lock721').toString('hex'); + const token_id = '@' + Buffer.from(tokenId).toString('hex'); + const destination_chain = + '@' + Buffer.from(destChain).toString('hex'); + const destination_user_address = + '@' + Buffer.from(destAddress).toString('hex'); + const source_nft_contract_address = collectionIdentifiers; + + const tx3 = new Transaction({ + data: new TransactionPayload( + 'ESDTNFTTransfer' + + collectionIdentifiers + + noncec + + quantity + + destination_address + + method + + token_id + + destination_chain + + destination_user_address + + source_nft_contract_address + + noncec, + ), + gasLimit: 600000000, + sender: signer.getAddress(), + receiver: signer.getAddress(), + chainID: 'D', + }); + + tx3.setNonce(userAccount.getNonceThenIncrement()); + + const serializedTransaction = tx3.serializeForSigning(); + const transactionSignature = await signer.sign( + serializedTransaction, + ); + tx3.applySignature(transactionSignature); + + const txHash = await proxyNetworkProvider.sendTransaction(tx3); + return { + hash: txHash, + wait: () => Promise.resolve(txHash), + }; + } catch (e) { + console.log(e); + throw new Error('Error locking in multiversX bridge'); + } + }, + claimNFT721: async (nftTransferDetailsObject, sigs) => { + const signer = UserSigner.fromWallet( + multiversXWallet.userWallet, + multiversXWallet.password, + ); + + const userAddress = new Address(multiversXWallet.userWallet.bech32); + const userAccount = new Account(userAddress); + const userOnNetwork = + await proxyNetworkProvider.getAccount(userAddress); + userAccount.update(userOnNetwork); + + const structClaimData = new StructType('ClaimData', [ + new FieldDefinition( + 'token_id', + 'name of the nft', + new BytesType(), + ), + new FieldDefinition( + 'source_chain', + 'attributes of the nft', + new BytesType(), + ), + new FieldDefinition( + 'destination_chain', + 'attributes of the nft', + new BytesType(), + ), + new FieldDefinition( + 'destination_user_address', + 'attributes of the nft', + new AddressType(), + ), + new FieldDefinition( + 'source_nft_contract_address', + 'attributes of the nft', + new BytesType(), + ), + new FieldDefinition( + 'name', + 'attributes of the nft', + new BytesType(), + ), + new FieldDefinition( + 'symbol', + 'attributes of the nft', + new BytesType(), + ), + new FieldDefinition( + 'royalty', + 'attributes of the nft', + new BigUIntType(), + ), + new FieldDefinition( + 'royalty_receiver', + 'attributes of the nft', + new AddressType(), + ), + new FieldDefinition( + 'attrs', + 'attributes of the nft', + new BytesType(), + ), + new FieldDefinition( + 'transaction_hash', + 'attributes of the nft', + new BytesType(), + ), + new FieldDefinition( + 'token_amount', + 'attributes of the nft', + new BigUIntType(), + ), + new FieldDefinition( + 'nft_type', + 'attributes of the nft', + new BytesType(), + ), + new FieldDefinition( + 'fee', + 'attributes of the nft', + new BigUIntType(), + ), + ]); + + // const structSigInfo = new StructType('SignatureInfo', [ + // new FieldDefinition( + // 'public_key', + // 'attributes of the nft', + // new AddressType(), + // ), + // new FieldDefinition( + // 'sig', + // 'attributes of the nft', + // new BytesType(), + // ), + // ]); + const claimDataArgs = new Struct(structClaimData, [ + new Field( + new BytesValue( + Buffer.from( + new Nonce( + Number(nftTransferDetailsObject.tokenId), + ).hex(), + 'hex', + ), + ), + 'token_id', + ), + new Field( + new BytesValue( + Buffer.from(nftTransferDetailsObject.sourceChain), + ), + 'source_chain', + ), + new Field( + new BytesValue( + Buffer.from(nftTransferDetailsObject.destinationChain), + ), + 'destination_chain', + ), + new Field( + new AddressValue( + new Address( + nftTransferDetailsObject.destinationUserAddress, + ), + ), + 'destination_user_address', + ), + new Field( + new BytesValue( + Buffer.from( + nftTransferDetailsObject.sourceNftContractAddress, + ), + ), + 'source_nft_contract_address', + ), + new Field( + new BytesValue(Buffer.from(nftTransferDetailsObject.name)), + 'name', + ), + new Field( + new BytesValue( + Buffer.from( + 'N' + + nftTransferDetailsObject.sourceChain.toUpperCase(), + ), + ), + 'symbol', + ), + new Field( + new BigUIntValue(Number(nftTransferDetailsObject.royalty)), + 'royalty', + ), + new Field( + new AddressValue( + new Address(nftTransferDetailsObject.royaltyReceiver), + ), + 'royalty_receiver', + ), + new Field( + new BytesValue( + Buffer.from(nftTransferDetailsObject.metadata), + ), + 'attrs', + ), + new Field( + new BytesValue( + Buffer.from(nftTransferDetailsObject.transactionHash), + ), + 'transaction_hash', + ), + new Field( + new BigUIntValue(nftTransferDetailsObject.tokenAmount), + 'token_amount', + ), + new Field( + new BytesValue( + Buffer.from(nftTransferDetailsObject.nftType), + ), + 'nft_type', + ), + new Field( + new BigUIntValue(nftTransferDetailsObject.fee), + 'fee', + ), + ]); + const data = [ + claimDataArgs, + [ + sigs.map((item) => { + return { + public_key: new AddressValue( + new Address( + Buffer.from(item.signerAddress, 'hex'), + ), + ), + sig: new BytesValue( + Buffer.from(item.signature, 'hex'), + ), + }; + }), + ], + VariadicValue.fromItems( + new BytesValue( + Buffer.from(nftTransferDetailsObject.metadata, 'utf-8'), + ), + ), + ]; + const transaction = multiversXBridgeContract.methods + .claimNft721(data) + .withSender(signer.getAddress()) + .withChainID('D') + .withGasLimit(6_000_000_00) + .withValue(new BigUIntValue(new BigNumber('50000000000000000'))) + .buildTransaction(); + transaction.setNonce(userAccount.getNonceThenIncrement()); + transaction.applySignature( + await signer.sign(transaction.serializeForSigning()), + ); + const hash = + await proxyNetworkProvider.sendTransaction(transaction); + return { + hash: hash, + wait: () => Promise.resolve(hash as unknown), + }; + }, validators: async (validatorAddress: string) => { const query = multiversXBridgeContract.createQuery({ func: 'validators', diff --git a/src/utils/functions/getSecretBridgeContract.ts b/src/utils/functions/getSecretBridgeContract.ts index 83a762fd..08ea64ad 100644 --- a/src/utils/functions/getSecretBridgeContract.ts +++ b/src/utils/functions/getSecretBridgeContract.ts @@ -6,7 +6,11 @@ import { encodeSecp256k1Pubkey } from 'secretjs/dist/wallet_amino'; const getSecretBridgeContract = ({ secretChainConfig, secretWallet, -}: ISecretChainConfigAndSecretWallet): IBridge => { +}: ISecretChainConfigAndSecretWallet): IBridge< + unknown[], + Record, + { signer: string; signature: string } +> => { const bridgeContractCodeHash = 'dbccb5a7abf668d050d720cd01ea39d556492456ceb870dcae80dc4ff8572575'; const secretjs = new SecretNetworkClient({ @@ -15,6 +19,12 @@ const getSecretBridgeContract = ({ }); return { + lock721: async () => { + throw new Error('Not implemented'); + }, + claimNFT721: async () => { + throw new Error('Not implemented'); + }, validators: async (address: string) => { const res = (await secretjs.query.compute.queryContract({ contract_address: secretChainConfig.contractAddress, diff --git a/src/utils/functions/getTezosBridgeContract.ts b/src/utils/functions/getTezosBridgeContract.ts index 14393d27..fed304a1 100644 --- a/src/utils/functions/getTezosBridgeContract.ts +++ b/src/utils/functions/getTezosBridgeContract.ts @@ -2,14 +2,36 @@ import { IBridge, ITezosChainConfigAndTezosWallet } from '@src/types'; import { TezosToolkit } from '@taquito/taquito'; import { InMemorySigner } from '@taquito/signer'; import { BridgeContractType } from '@src/contractsTypes/tezosContractTypes/Bridge.types'; -import { tas } from '@src/contractsTypes/tezosContractTypes/type-aliases'; +import { + address, + key, + signature, + tas, +} from '@src/contractsTypes/tezosContractTypes/type-aliases'; import { b58cencode, prefix, b58cdecode } from '@taquito/utils'; import { hash } from '@stablelib/blake2b'; +import { SupportedChains } from '@src/config/chainSpecs'; + +export type TezosLockArgs = [ + sourceNftContractAddress: string, + + destinationChain: SupportedChains, + address: string, + tokenId: string, +]; const getTezosBridgeContract = ({ tezosChainConfig, tezosWallet, -}: ITezosChainConfigAndTezosWallet): IBridge => { +}: ITezosChainConfigAndTezosWallet): IBridge< + TezosLockArgs, + Record, + { + signer: key; + sig: signature; + addr: address; + } +> => { const getBridgeInstance = async () => { const Tezos = new TezosToolkit(tezosChainConfig.rpcURL); const tezosSigner = await InMemorySigner.fromSecretKey( @@ -23,6 +45,12 @@ const getTezosBridgeContract = ({ }; return { + lock721: async () => { + throw new Error('Not implemented'); + }, + claimNFT721: async () => { + throw new Error('Not implemented'); + }, validators: async (address: string) => { const bridge = await getBridgeInstance(); const storage = await bridge.storage(); diff --git a/src/utils/functions/getTonBridgeContract.ts b/src/utils/functions/getTonBridgeContract.ts index 4bff8e1a..622a3048 100644 --- a/src/utils/functions/getTonBridgeContract.ts +++ b/src/utils/functions/getTonBridgeContract.ts @@ -13,7 +13,11 @@ import TonWeb from 'tonweb'; const getTonBridgeContract = ({ tonChainConfig, tonWallet, -}: ITonChainConfigAndTonWallet): IBridge => { +}: ITonChainConfigAndTonWallet): IBridge< + unknown[], + Record, + unknown +> => { const client = new TonClient({ endpoint: tonChainConfig.rpcURL, apiKey: 'f3f6ef64352ac53cdfca18a3ba5372983e4037182c2b510fc52de5a259ecf292', @@ -36,6 +40,12 @@ const getTonBridgeContract = ({ const tonweb = new TonWeb(new TonWeb.HttpProvider(tonChainConfig.rpcURL)); return { + lock721: async () => { + throw new Error('Not implemented'); + }, + claimNFT721: async () => { + throw new Error('Not implemented'); + }, validators: async (address: string) => { const newValidatorPublicKey = Buffer.from(address, 'hex'); const newValidatorPublicKeyBigInt = beginCell() From 024abba49c7b1b0005d3edc484d3eb3aa22856d3 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Wed, 17 Jan 2024 19:14:27 +0530 Subject: [PATCH 02/19] INFTContract: Implement Approval for NFT Contracts on All Chains --- .gitignore | 3 +- src/types/index.ts | 1 + src/utils/functions/getEvmMultiNftContract.ts | 9 +++++- .../functions/getEvmSingleNftContract.ts | 9 +++++- src/utils/functions/getHederaNftContract.ts | 9 +++++- .../functions/getMultiversXNftContract.ts | 3 ++ .../functions/getSecretMultiNftContract.ts | 32 ++++++++++++++++--- .../functions/getSecretSingleNftContract.ts | 29 ++++++++++++++--- src/utils/functions/getTezosNftContract.ts | 29 +++++++++++++---- src/utils/functions/getTonNftContract.ts | 3 ++ 10 files changed, 107 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index c3b10faa..d2541e97 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ secrets.json database.sqlite test.ts test.bash -test2.ts \ No newline at end of file +test2.ts +dist/ \ No newline at end of file diff --git a/src/types/index.ts b/src/types/index.ts index 911be41f..a9b724e3 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -246,6 +246,7 @@ type INftContract = { symbol: (tokenId?: bigint) => Promise; royaltyInfo: (tokenId?: bigint) => Promise; tokenURI: (tokenId: bigint) => Promise; + approve: (tokenId: bigint, to: string) => Promise; }; export { diff --git a/src/utils/functions/getEvmMultiNftContract.ts b/src/utils/functions/getEvmMultiNftContract.ts index 91474700..4d8e5b27 100644 --- a/src/utils/functions/getEvmMultiNftContract.ts +++ b/src/utils/functions/getEvmMultiNftContract.ts @@ -1,7 +1,7 @@ import { ERC1155Royalty, ERC1155Royalty__factory } from '../../contractsTypes'; import { IEvmContractConfig, INftContract } from '@src/types'; import { SalePriceToGetTotalRoyalityPercentage } from '../constants/salePriceToGetTotalRoyalityPercentage'; -import { JsonRpcProvider } from 'ethers'; +import { JsonRpcProvider, Signer } from 'ethers'; type IExtendedERC1155Royalty = { name?: () => Promise; @@ -10,6 +10,7 @@ type IExtendedERC1155Royalty = { const getEvmMultiNftContract = ( contractConfig: IEvmContractConfig, + wallet?: Signer, ): INftContract => { const provider = new JsonRpcProvider(contractConfig.rpcURL); @@ -49,6 +50,12 @@ const getEvmMultiNftContract = ( return '0'; } }, + approve: async (_tokenId, to) => { + if (!wallet) throw new Error('Wallet is not connected'); + const contractWithSigner = erc1155Contract.connect(wallet); + const tx = await contractWithSigner.setApprovalForAll(to, true); + return tx.hash; + }, tokenURI: async (tokenId: bigint) => { return await erc1155Contract.uri(tokenId); }, diff --git a/src/utils/functions/getEvmSingleNftContract.ts b/src/utils/functions/getEvmSingleNftContract.ts index 788e10f0..3bf7f215 100644 --- a/src/utils/functions/getEvmSingleNftContract.ts +++ b/src/utils/functions/getEvmSingleNftContract.ts @@ -1,10 +1,11 @@ import { ERC721Royalty__factory } from '../../contractsTypes'; import { IEvmContractConfig, INftContract } from '@src/types'; import { SalePriceToGetTotalRoyalityPercentage } from '../constants/salePriceToGetTotalRoyalityPercentage'; -import { JsonRpcProvider } from 'ethers'; +import { JsonRpcProvider, Signer } from 'ethers'; const getEvmSingleNftContract = ( contractConfig: IEvmContractConfig, + wallet?: Signer, ): INftContract => { const provider = new JsonRpcProvider(contractConfig.rpcURL); const erc721Contract = ERC721Royalty__factory.connect( @@ -29,6 +30,12 @@ const getEvmSingleNftContract = ( return '0'; } }, + async approve(tokenId, to) { + if (!wallet) throw new Error('Wallet is not connected'); + const contractWithSigner = erc721Contract.connect(wallet); + const tx = await contractWithSigner.approve(to, tokenId); + return tx.hash; + }, tokenURI: async (tokenId) => { return await erc721Contract.tokenURI(tokenId); }, diff --git a/src/utils/functions/getHederaNftContract.ts b/src/utils/functions/getHederaNftContract.ts index 6e1fcc12..d03eea46 100644 --- a/src/utils/functions/getHederaNftContract.ts +++ b/src/utils/functions/getHederaNftContract.ts @@ -1,10 +1,11 @@ import { ERC721Royalty__factory } from '../../contractsTypes'; import { IHederaContractConfig, INftContract } from '@src/types'; -import { JsonRpcProvider } from 'ethers'; +import { JsonRpcProvider, Signer } from 'ethers'; import { RoyaltyInfoProxy__factory } from '@src/contractsTypes/Hedera/RoyaltyInfoProxy__factory'; const getHederaSingleNftContract = ( contractConfig: IHederaContractConfig, + wallet?: Signer, ): INftContract => { const provider = new JsonRpcProvider(contractConfig.rpcURL); const erc721Contract = ERC721Royalty__factory.connect( @@ -39,6 +40,12 @@ const getHederaSingleNftContract = ( return '0'; } }, + async approve(tokenId, to) { + if (!wallet) throw new Error('Wallet is not connected'); + const contractWithSigner = erc721Contract.connect(wallet); + const tx = await contractWithSigner.approve(to, tokenId); + return tx.hash; + }, tokenURI: async (tokenId: bigint) => { return await erc721Contract.tokenURI(tokenId); }, diff --git a/src/utils/functions/getMultiversXNftContract.ts b/src/utils/functions/getMultiversXNftContract.ts index ddb17478..724e19c5 100644 --- a/src/utils/functions/getMultiversXNftContract.ts +++ b/src/utils/functions/getMultiversXNftContract.ts @@ -39,6 +39,9 @@ const getMultiversXNftContract = ({ ); return nftDetails.ticker; }, + approve: async () => { + throw new Error('Not implemented'); + }, royaltyInfo: async (tokenId) => { try { const nftDetails = await getNonFungibleToken( diff --git a/src/utils/functions/getSecretMultiNftContract.ts b/src/utils/functions/getSecretMultiNftContract.ts index e436f083..86996b84 100644 --- a/src/utils/functions/getSecretMultiNftContract.ts +++ b/src/utils/functions/getSecretMultiNftContract.ts @@ -1,11 +1,10 @@ import { INftContract, ISecretContractConfig } from '@src/types'; import { SecretNetworkClient } from 'secretjs'; -const getSecretMultiNftContract = ({ - rpcURL, - chainId, - contractAddress, -}: ISecretContractConfig): INftContract => { +const getSecretMultiNftContract = ( + { rpcURL, chainId, contractAddress }: ISecretContractConfig, + wallet?: SecretNetworkClient, +): INftContract => { const secretjs = new SecretNetworkClient({ url: rpcURL, chainId: chainId, @@ -37,6 +36,29 @@ const getSecretMultiNftContract = ({ ).token_id_public_info.token_id_info.name; return name; }, + async approve(tokenId, to) { + if (!wallet) throw new Error('Wallet is not connected'); + + const res = await wallet.tx.compute.executeContract( + { + sender: wallet.address, + contract_address: contractAddress, + msg: { + give_permission: { + allowed_address: to, + token_id: tokenId, + view_balance: true, + transfer: 1, + }, + }, + }, + { + waitForCommit: true, + gasLimit: 250_000, + }, + ); + return res.transactionHash; + }, symbol: async (tokenId) => { const symbol = ( (await secretjs.query.compute.queryContract({ diff --git a/src/utils/functions/getSecretSingleNftContract.ts b/src/utils/functions/getSecretSingleNftContract.ts index 7608b231..e10466ea 100644 --- a/src/utils/functions/getSecretSingleNftContract.ts +++ b/src/utils/functions/getSecretSingleNftContract.ts @@ -1,11 +1,10 @@ import { INftContract, ISecretContractConfig } from '@src/types'; import { SecretNetworkClient } from 'secretjs'; -const getSecretSingleNftContract = ({ - rpcURL, - chainId, - contractAddress, -}: ISecretContractConfig): INftContract => { +const getSecretSingleNftContract = ( + { rpcURL, chainId, contractAddress }: ISecretContractConfig, + wallet?: SecretNetworkClient, +): INftContract => { const secretjs = new SecretNetworkClient({ url: rpcURL, chainId: chainId, @@ -23,6 +22,26 @@ const getSecretSingleNftContract = ({ ).contract_info.name; return name; }, + approve: async (tokenId, to) => { + if (!wallet) throw new Error('Wallet is not connected'); + const res = await wallet.tx.compute.executeContract( + { + sender: wallet.address, + contract_address: contractAddress, + msg: { + approve: { + spender: to, + token_id: tokenId, + }, + }, + }, + { + waitForCommit: true, + gasLimit: 250_000, + }, + ); + return res.transactionHash; + }, symbol: async () => { const symbol = ( (await secretjs.query.compute.queryContract({ diff --git a/src/utils/functions/getTezosNftContract.ts b/src/utils/functions/getTezosNftContract.ts index 5c492d74..b0432352 100644 --- a/src/utils/functions/getTezosNftContract.ts +++ b/src/utils/functions/getTezosNftContract.ts @@ -1,7 +1,10 @@ import { NFTContractType } from '@src/contractsTypes/tezosContractTypes/NFT.types'; -import { tas } from '@src/contractsTypes/tezosContractTypes/type-aliases'; +import { + address, + tas, +} from '@src/contractsTypes/tezosContractTypes/type-aliases'; import { INftContract, ITezosContractConfig } from '@src/types'; -import { TezosToolkit } from '@taquito/taquito'; +import { Signer, TezosToolkit } from '@taquito/taquito'; import { Tzip16Module, bytes2Char, tzip16 } from '@taquito/tzip16'; const URLCanParse = (url: string): boolean => { @@ -13,10 +16,10 @@ const URLCanParse = (url: string): boolean => { } }; -const getTezosNftContract = ({ - rpcURL, - contractAddress, -}: ITezosContractConfig): INftContract => { +const getTezosNftContract = ( + { rpcURL, contractAddress }: ITezosContractConfig, + signer?: Signer, +): INftContract => { const getNftTokenMetaData = async (tokenId: bigint) => { const Tezos = new TezosToolkit(rpcURL); const nftContract = @@ -30,6 +33,20 @@ const getTezosNftContract = ({ }; return { + async approve(tokenId, to) { + if (!signer) throw new Error('Wallet is not connected'); + const Tezos = new TezosToolkit(rpcURL); + const nftContract = + await Tezos.contract.at(contractAddress); + const tx = await nftContract.methods + .add_operator( + (await signer.publicKeyHash()) as address, + to as address, + tas.nat(tokenId.toString()), + ) + .send(); + return tx.hash; + }, name: async () => { try { const Tezos = new TezosToolkit(rpcURL); diff --git a/src/utils/functions/getTonNftContract.ts b/src/utils/functions/getTonNftContract.ts index ef41b5e6..8a5ba72f 100644 --- a/src/utils/functions/getTonNftContract.ts +++ b/src/utils/functions/getTonNftContract.ts @@ -48,6 +48,9 @@ const getTonNftContract = ({ return ''; } }, + async approve() { + return ''; + }, symbol: async () => { return ''; }, From 4e439c6c82fa4eeef2207dcd3180707cd4898456 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Thu, 18 Jan 2024 14:55:13 +0530 Subject: [PATCH 03/19] IBridge: Implement Locking and Claiming for Secret and TON --- src/types/index.ts | 7 +- .../functions/getMultiversXNftContract.ts | 2 +- .../functions/getSecretBridgeContract.ts | 146 +++++++++++++++++- src/utils/functions/getTonBridgeContract.ts | 71 ++++++++- 4 files changed, 205 insertions(+), 21 deletions(-) diff --git a/src/types/index.ts b/src/types/index.ts index a9b724e3..2f95c62d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,5 +1,3 @@ -import { SupportedChains } from '@src/config/chainSpecs'; - type ISecretKeyCrypto = { ciphertext: string; cipherparams: { @@ -225,11 +223,8 @@ type IBridge = { ...lockArgs: TLockArgs ) => Promise<{ hash: string; wait: () => Promise }>; lock1155?: ( - sourceNftContractAddress: string, - tokenId: string, - destinationChain: SupportedChains, - address: string, amt: bigint, + ...lockArgs: TLockArgs ) => Promise<{ hash: string; wait: () => Promise }>; claimNFT721: ( nftTransferData: TClaimData, diff --git a/src/utils/functions/getMultiversXNftContract.ts b/src/utils/functions/getMultiversXNftContract.ts index 724e19c5..bcc76e03 100644 --- a/src/utils/functions/getMultiversXNftContract.ts +++ b/src/utils/functions/getMultiversXNftContract.ts @@ -40,7 +40,7 @@ const getMultiversXNftContract = ({ return nftDetails.ticker; }, approve: async () => { - throw new Error('Not implemented'); + return Promise.resolve('No Need to Approve in MultiversX'); }, royaltyInfo: async (tokenId) => { try { diff --git a/src/utils/functions/getSecretBridgeContract.ts b/src/utils/functions/getSecretBridgeContract.ts index 08ea64ad..55cc3c82 100644 --- a/src/utils/functions/getSecretBridgeContract.ts +++ b/src/utils/functions/getSecretBridgeContract.ts @@ -1,14 +1,45 @@ import { AddValidatorType } from '@src/contractsTypes/contracts/secretBridge'; import { IBridge, ISecretChainConfigAndSecretWallet } from '@src/types'; +import BigNumber from 'bignumber.js'; import { SecretNetworkClient, pubkeyToAddress } from 'secretjs'; import { encodeSecp256k1Pubkey } from 'secretjs/dist/wallet_amino'; +export type CodeInfo = { + code_id: number; + code_hash: string; +}; + +export type SecretLockType = [ + destinationChain: string, + destinationUserAddress: string, + sourceNftContractAddress: string, + collectionCodeInfo: CodeInfo, + tokenId: string, +]; + +export type ClaimData = { + token_id: string; + source_chain: string; + destination_chain: string; + destination_user_address: string; + source_nft_contract_address: string; + name: string; + symbol: string; + royalty: number; + royalty_receiver: string; + metadata: string; + transaction_hash: string; + token_amount: BigNumber; + nft_type: string; + fee: BigNumber; +}; + const getSecretBridgeContract = ({ secretChainConfig, secretWallet, }: ISecretChainConfigAndSecretWallet): IBridge< - unknown[], - Record, + SecretLockType, + ClaimData, { signer: string; signature: string } > => { const bridgeContractCodeHash = @@ -19,11 +50,114 @@ const getSecretBridgeContract = ({ }); return { - lock721: async () => { - throw new Error('Not implemented'); + lock721: async ( + destinationChain, + destinationUserAddress, + sourceNftContractAddress, + collectionCodeInfo, + tokenId, + ) => { + const tx = await secretjs.tx.compute.executeContract( + { + contract_address: secretChainConfig.contractAddress, + msg: { + lock721: { + data: { + destination_chain: destinationChain, + destination_user_address: + destinationUserAddress, + source_nft_contract_address: + sourceNftContractAddress, + collection_code_info: collectionCodeInfo, + token_id: tokenId, + }, + }, + }, + code_hash: bridgeContractCodeHash, + sender: secretjs.address, + }, + { + gasLimit: 200_000, + }, + ); + return { hash: tx.transactionHash, wait: async () => {} }; }, - claimNFT721: async () => { - throw new Error('Not implemented'); + claimNFT721: async (data, sigs) => { + const claim721 = { + claim721: { + data: { + data, + signatures: sigs, + }, + }, + }; + const tx = await secretjs.tx.compute.executeContract( + { + contract_address: secretChainConfig.contractAddress, + msg: claim721, + code_hash: bridgeContractCodeHash, + sender: secretjs.address, + sent_funds: [ + { amount: data.fee.toString(), denom: 'uscrt' }, + ], + }, + { + gasLimit: 300_000, + }, + ); + return { hash: tx.transactionHash, wait: async () => {} }; + }, + async lock1155( + amt, + destinationChain, + destinationUserAddress, + sourceNftContractAddress, + collectionCodeInfo, + tokenId, + ) { + const tx = await secretjs.tx.compute.executeContract( + { + contract_address: secretChainConfig.contractAddress, + msg: { + destination_chain: destinationChain, + destination_user_address: destinationUserAddress, + source_nft_contract_address: sourceNftContractAddress, + collection_code_info: collectionCodeInfo, + token_id: tokenId, + token_amount: new BigNumber(amt.toString()), + }, + code_hash: bridgeContractCodeHash, + sender: secretjs.address, + }, + { + gasLimit: 200_000, + }, + ); + + return { hash: tx.transactionHash, wait: async () => {} }; + }, + async claimNFT1155(nftTransferData, sigs) { + const claim721 = { + claim1155: { + data: { + data: nftTransferData, + signatures: sigs, + }, + }, + }; + const tx = await secretjs.tx.compute.executeContract( + { + contract_address: secretChainConfig.contractAddress, + msg: claim721, + code_hash: bridgeContractCodeHash, + sender: secretjs.address, + sent_funds: [{ amount: '1', denom: 'uscrt' }], + }, + { + gasLimit: 300_000, + }, + ); + return { hash: tx.transactionHash, wait: async () => {} }; }, validators: async (address: string) => { const res = (await secretjs.query.compute.queryContract({ diff --git a/src/utils/functions/getTonBridgeContract.ts b/src/utils/functions/getTonBridgeContract.ts index 622a3048..fdecbd49 100644 --- a/src/utils/functions/getTonBridgeContract.ts +++ b/src/utils/functions/getTonBridgeContract.ts @@ -1,5 +1,6 @@ import { Bridge, + ClaimData, NewValidator, SignerAndSignature, } from '@src/contractsTypes/contracts/tonBridge'; @@ -10,13 +11,23 @@ import { ProcessDelayMilliseconds } from '../constants/processDelayMilliseconds' import waitForMSWithMsg from './waitForMSWithMsg'; import TonWeb from 'tonweb'; +export type TonLockArgs = [ + destinationChain: string, + destinationUserAddress: string, + sourceNftContractAddress: string, + tokenId: bigint, +]; + const getTonBridgeContract = ({ tonChainConfig, tonWallet, }: ITonChainConfigAndTonWallet): IBridge< - unknown[], - Record, - unknown + TonLockArgs, + ClaimData, + { + publicKey: bigint; + sig: string; + } > => { const client = new TonClient({ endpoint: tonChainConfig.rpcURL, @@ -36,15 +47,59 @@ const getTonBridgeContract = ({ Address.parseFriendly(tonChainConfig.contractAddress).address, ), ); + const provider = new TonWeb.HttpProvider(tonChainConfig.rpcURL); - const tonweb = new TonWeb(new TonWeb.HttpProvider(tonChainConfig.rpcURL)); + const tonweb = new TonWeb(provider); return { - lock721: async () => { - throw new Error('Not implemented'); + lock721: async ( + destinationChain, + destinationUserAddress, + sourceNftContractAddress, + tokenId, + ) => { + await bridge.send( + walletSender, + { + value: toNano('2'), + }, + { + $$type: 'Lock721', + destinationChain, + destinationUserAddress, + sourceNftContractAddress: Address.parseFriendly( + sourceNftContractAddress, + ).address, + tokenId: tokenId, + }, + ); + return { hash: 'No Tx Hash', wait: async () => {} }; }, - claimNFT721: async () => { - throw new Error('Not implemented'); + claimNFT721: async (claimData, sigsA) => { + const sigs: SignerAndSignature[] = sigsA.map((e) => { + return { + $$type: 'SignerAndSignature', + key: e.publicKey, + signature: beginCell() + .storeBuffer(Buffer.from(e.sig, 'hex')) + .endCell(), + }; + }); + const dictA = Dictionary.empty(); + sigs.forEach((item, index) => dictA.set(BigInt(index), item)); + await bridge.send( + walletSender, + { + value: toNano('0.8'), + }, + { + $$type: 'ClaimNFT721', + data: claimData, + len: 1n, + signatures: dictA, + }, + ); + return { hash: 'No Tx Hash', wait: async () => {} }; }, validators: async (address: string) => { const newValidatorPublicKey = Buffer.from(address, 'hex'); From c1111782ef0c57898688969d99798400ab48bc8e Mon Sep 17 00:00:00 2001 From: imsk17 Date: Thu, 18 Jan 2024 15:25:38 +0530 Subject: [PATCH 04/19] IBridge: Implement Locking and Claiming Tezos w/ Newly Generated Contract Types --- .../tezosContractTypes/Bridge.code.ts | 2 +- .../tezosContractTypes/Bridge.types.ts | 38 +++++---- .../CollectionFactory.code.ts | 2 +- .../CollectionFactory.types.ts | 10 +-- .../tezosContractTypes/NFT.code.ts | 2 +- .../tezosContractTypes/NFT.types.ts | 32 +++---- .../tezosContractTypes/NFTStorage.code.ts | 4 +- .../tezosContractTypes/NFTStorage.types.ts | 5 +- .../tezosContractTypes/StorageFactory.code.ts | 2 +- .../tezosContractTypes/type-aliases.ts | 7 +- .../tezosContractTypes/type-utils.ts | 1 + src/utils/functions/getTezosBridgeContract.ts | 83 +++++++++++++++++-- 12 files changed, 131 insertions(+), 57 deletions(-) diff --git a/src/contractsTypes/tezosContractTypes/Bridge.code.ts b/src/contractsTypes/tezosContractTypes/Bridge.code.ts index 6d824518..6962e1d1 100644 --- a/src/contractsTypes/tezosContractTypes/Bridge.code.ts +++ b/src/contractsTypes/tezosContractTypes/Bridge.code.ts @@ -6,6 +6,6 @@ export const BridgeCode: { __type: 'BridgeCode', protocol: 'PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA', code: JSON.parse( - `[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"pair","annots":["%claim_nft"],"args":[{"prim":"pair","annots":["%data"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%source_chain"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"address","annots":["%dest_address"]},{"prim":"bytes","annots":["%source_nft_contract_address"]},{"prim":"string","annots":["%name"]},{"prim":"string","annots":["%symbol"]},{"prim":"nat","annots":["%royalty"]},{"prim":"address","annots":["%royalty_receiver"]},{"prim":"string","annots":["%metadata"]},{"prim":"string","annots":["%transaction_hash"]},{"prim":"nat","annots":["%token_amount"]},{"prim":"string","annots":["%nft_type"]},{"prim":"mutez","annots":["%fee"]}]},{"prim":"list","annots":["%sigs"],"args":[{"prim":"pair","args":[{"prim":"key","annots":["%signer"]},{"prim":"signature","annots":["%sig"]},{"prim":"address","annots":["%addr"]}]}]}]},{"prim":"or","args":[{"prim":"pair","annots":["%internal_ns_nd_part"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"address","annots":["%dest_address"]},{"prim":"address","annots":["%collection"]},{"prim":"nat","annots":["%token_amount"]},{"prim":"string","annots":["%source_chain"]},{"prim":"string","annots":["%md"]},{"prim":"string","annots":["%transaction_hash"]}]},{"prim":"or","args":[{"prim":"pair","annots":["%lock_sft"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"string","annots":["%dest_address"]},{"prim":"address","annots":["%source_nft_address"]},{"prim":"nat","annots":["%token_amount"]}]},{"prim":"or","args":[{"prim":"pair","annots":["%lock_internal"],"args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%collection"]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]}]},{"prim":"or","args":[{"prim":"pair","annots":["%lock_nft"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"string","annots":["%dest_address"]},{"prim":"address","annots":["%source_nft_address"]}]},{"prim":"or","args":[{"prim":"pair","annots":["%claim_validator_rewards"],"args":[{"prim":"address","annots":["%validator"]},{"prim":"list","annots":["%sigs"],"args":[{"prim":"pair","args":[{"prim":"key","annots":["%signer"]},{"prim":"signature","annots":["%sig"]},{"prim":"address","annots":["%addr"]}]}]}]},{"prim":"pair","annots":["%add_validator"],"args":[{"prim":"address","annots":["%validator"]},{"prim":"list","annots":["%sigs"],"args":[{"prim":"pair","args":[{"prim":"key","annots":["%signer"]},{"prim":"signature","annots":["%sig"]},{"prim":"address","annots":["%addr"]}]}]}]}]}]}]}]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"big_map","annots":["%validators"],"args":[{"prim":"address"},{"prim":"mutez"}]},{"prim":"big_map","annots":["%unique_identifiers"],"args":[{"prim":"bytes"},{"prim":"bool"}]},{"prim":"address","annots":["%collection_deployer"]},{"prim":"address","annots":["%storage_deployer"]},{"prim":"big_map","annots":["%original_to_duplicate_mapping"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"string"}]},{"prim":"pair","args":[{"prim":"string","annots":["%chain"]},{"prim":"bytes","annots":["%contract"]}]}]},{"prim":"big_map","annots":["%duplicate_to_original_mapping"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"string"}]},{"prim":"pair","args":[{"prim":"string","annots":["%chain"]},{"prim":"bytes","annots":["%contract"]}]}]},{"prim":"big_map","annots":["%original_storage_mapping_nft"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"string"}]},{"prim":"address"}]},{"prim":"big_map","annots":["%original_storage_mapping_sft"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"string"}]},{"prim":"address"}]},{"prim":"big_map","annots":["%duplicate_storage_mapping_nft"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"string"}]},{"prim":"address"}]},{"prim":"big_map","annots":["%duplicate_storage_mapping_sft"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"string"}]},{"prim":"address"}]},{"prim":"nat","annots":["%validators_count"]}]}]},{"prim":"code","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"TEZOS"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"NFT"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"SFT"}]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"string"},{"prim":"string"}]},{"prim":"operation"},[{"prim":"EMIT","annots":["%claimed"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%source_chain"]},{"prim":"string","annots":["%tx_hash"]}]}]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"address"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"VIEW","args":[{"string":"owner_of"},{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"bytes"},{"prim":"list","args":[{"prim":"pair","args":[{"prim":"key"},{"prim":"signature"},{"prim":"address"}]}]}]},{"prim":"int"},[{"prim":"UNPAIR"},{"prim":"PUSH","args":[{"prim":"int"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CHECK_SIGNATURE"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"int"},{"int":"1"}]},{"prim":"ADD"}],[]]}]]},{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"address"}]},{"prim":"operation"},[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONTRACT","annots":["%unlock_token"],"args":[{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%to"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"TRANSFER_TOKENS"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"string"},{"prim":"nat"}]},{"prim":"operation"},[{"prim":"UNPAIR","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"CONTRACT","annots":["%mint"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%token_uri"]},{"prim":"address","annots":["%to"]},{"prim":"nat","annots":["%amt"]}]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"nat"},{"prim":"string"},{"prim":"address"},{"prim":"nat"}]}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"CONS"},{"prim":"TRANSFER_TOKENS"}]]},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"26"}]},{"prim":"AMOUNT"},{"prim":"COMPARE"},{"prim":"LT"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Insufficient fees"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Cannot transfer to the same chain"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"10"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"25"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[],[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Invalid NFT Type"}]},{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"PACK"},{"prim":"KECCAK"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Data already processed"}]},{"prim":"FAILWITH"}]]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"address"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CDR"},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"CHECK_SIGNATURE"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"int"},{"int":"1"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ADD"},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"CONS"}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"}]]},{"prim":"PAIR"}]]},{"prim":"SWAP"},{"prim":"DROP"},{"prim":"UNPAIR"},{"prim":"PUSH","args":[{"prim":"int"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"2"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"GET","args":[{"int":"20"}]},{"prim":"MUL"},{"prim":"EDIV"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"DIV by 0"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CAR"},{"prim":"ADD"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"LT"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Insufficient signatures"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"26"}]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"GT"},{"prim":"IF","args":[[],[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Fee must be greater than 0"}]},{"prim":"FAILWITH"}]]},{"prim":"BALANCE"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Insufficient rewards to distribute"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"COMPARE"},{"prim":"GT"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SIZE"},{"prim":"SWAP"},{"prim":"EDIV"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"DIV by 0"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"DUP"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"MAP FIND"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"ADD"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"UPDATE"}]]},{"prim":"SWAP"},{"prim":"DROP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"SWAP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Invalid contract address"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"9"}]},{"prim":"UNPACK","args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"DUP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}]]},{"prim":"DUP"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"10"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CDR"},{"prim":"UNPACK","args":[{"prim":"address"}]},{"prim":"DUP","args":[{"int":"12"}]},{"prim":"DIG","args":[{"int":"12"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"17"}]}],[{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"19"}]}]]},{"prim":"DIG","args":[{"int":"12"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Invalid contract address"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"PAIR"},{"prim":"GET"}],[{"prim":"DIG","args":[{"int":"12"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"9"}]},{"prim":"UNPACK","args":[{"prim":"address"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Invalid contract address"}]},{"prim":"SWAP"},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"11"}]},{"prim":"DIG","args":[{"int":"12"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"13"}]}],[{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"15"}]}]]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"PAIR"},{"prim":"GET"}]]},{"prim":"DUP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}]]},{"prim":"DUP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"AND"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DROP","args":[{"int":"3"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SWAP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Invalid Contract Address"}]},{"prim":"SWAP"},{"prim":"CDR"},{"prim":"UNPACK","args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"}],[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"19"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"CONS"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"21"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"SWAP"}],[{"prim":"DUP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"AND"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"DIG","args":[{"int":"10"}]},{"prim":"DROP","args":[{"int":"6"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Invalid Contract Address"}]},{"prim":"SWAP"},{"prim":"CDR"},{"prim":"UNPACK","args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"19"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"CONS"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"21"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"SWAP"}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"},{"prim":"DUP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"NOT"},{"prim":"AND"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Invalid Contract Address"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"9"}]},{"prim":"UNPACK","args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"SWAP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"}],[{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"19"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"CONS"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"21"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"SWAP"}],[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"DROP","args":[{"int":"4"}]},{"prim":"NOT"},{"prim":"SWAP"},{"prim":"NOT"},{"prim":"AND"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Invalid Contract Address"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"9"}]},{"prim":"UNPACK","args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"CONTRACT","annots":["%deploy_nft"],"args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%internal_ns_nd_part"],"args":[{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"address","annots":["%dest_address"]},{"prim":"address","annots":["%collection"]},{"prim":"nat","annots":["%token_amount"]},{"prim":"string","annots":["%source_chain"]},{"prim":"string","annots":["%md"]},{"prim":"string","annots":["%transaction_hash"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"21"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"19"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"10"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"23"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"11"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"12"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"12"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"8"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"DUG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"SWAP"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"21"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"SWAP"}]]}]]}]]}]]},{"prim":"SWAP"}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DROP","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Only Callable by Self"}]},{"prim":"SELF_ADDRESS"},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"VIEW","args":[{"string":"get_store"},{"prim":"address"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Collection not deployed"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"DROP","args":[{"int":"2"}]}]]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"PACK"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PACK"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"13"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"14"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"UPDATE","args":[{"int":"11"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"UPDATE","args":[{"int":"9"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"2"}]}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"15"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%deploy_sft_storage"],"args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%collection"]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"6"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%collection"]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"6"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]}]]}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"19"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%deploy_sft_storage"],"args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%collection"]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"6"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%collection"]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"6"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]},{"prim":"DIG","args":[{"int":"2"}]}],[{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Only Callable by Self"}]},{"prim":"SELF_ADDRESS"},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"VIEW","args":[{"string":"get_store"},{"prim":"address"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Storage contract not deployed"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"DROP","args":[{"int":"2"}]}]]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"10"}]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"13"}]}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"15"}]}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"13"}]},{"prim":"SWAP"}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"}]]}],[{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"10"}]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"17"}]}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"19"}]}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"17"}]},{"prim":"SWAP"}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"}]]}]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SOURCE"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CONTRACT","annots":["%transfer"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]}]}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"CONS"},{"prim":"TRANSFER_TOKENS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DROP"}],[{"prim":"DIG","args":[{"int":"8"}]},{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"EMIT","annots":["%locked"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%dest_address"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"string","annots":["%nft_type"]},{"prim":"string","annots":["%source_chain"]},{"prim":"address","annots":["%source_nft_address"]},{"prim":"nat","annots":["%token_amount"]},{"prim":"nat","annots":["%token_id"]}]}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"2"}]}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"13"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"CONTRACT","annots":["%deploy_nft_storage"],"args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%collection"]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"6"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%collection"]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"6"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]}]]}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"17"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"CONTRACT","annots":["%deploy_nft_storage"],"args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%collection"]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"6"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%collection"]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"6"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]},{"prim":"DIG","args":[{"int":"2"}]}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"},{"prim":"IF_LEFT","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"SIZE"},{"prim":"COMPARE"},{"prim":"GT"},{"prim":"IF","args":[[],[{"prim":"PUSH","args":[{"prim":"string"},{"string":"No signatures provided"}]},{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET"},{"prim":"DUP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Validator does not exist"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"PACK"},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Insufficient signatures"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"2"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"20"}]},{"prim":"MUL"},{"prim":"EDIV"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"DIV by 0"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CAR"},{"prim":"ADD"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"GE"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"EMIT","annots":["%rewarded_validator"],"args":[{"prim":"address"}]},{"prim":"SWAP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CONTRACT","args":[{"prim":"unit"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_contract"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SWAP"},{"prim":"UNIT"},{"prim":"TRANSFER_TOKENS"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"2"}]}],[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"SIZE"},{"prim":"COMPARE"},{"prim":"GT"},{"prim":"IF","args":[[],[{"prim":"PUSH","args":[{"prim":"string"},{"string":"No signatures provided"}]},{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Validator already exists"}]},{"prim":"FAILWITH"}]]},{"prim":"DUP"},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"PACK"},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Insufficient signatures"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"2"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"20"}]},{"prim":"MUL"},{"prim":"EDIV"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"DIV by 0"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CAR"},{"prim":"ADD"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"GE"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"20"}]},{"prim":"ADD"},{"prim":"UPDATE","args":[{"int":"20"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"EMIT","annots":["%added_new_validator"],"args":[{"prim":"address"}]}]]}]]}]]}]]}]]}]]},{"prim":"CONS"},{"prim":"PAIR"}]]}]`, + `[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"pair","annots":["%claim_nft"],"args":[{"prim":"pair","annots":["%data"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%source_chain"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"address","annots":["%dest_address"]},{"prim":"or","annots":["%source_nft_contract_address"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"string","annots":["%name"]},{"prim":"string","annots":["%symbol"]},{"prim":"nat","annots":["%royalty"]},{"prim":"address","annots":["%royalty_receiver"]},{"prim":"string","annots":["%metadata"]},{"prim":"string","annots":["%transaction_hash"]},{"prim":"nat","annots":["%token_amount"]},{"prim":"string","annots":["%nft_type"]},{"prim":"mutez","annots":["%fee"]}]},{"prim":"list","annots":["%sigs"],"args":[{"prim":"pair","args":[{"prim":"key","annots":["%signer"]},{"prim":"signature","annots":["%sig"]},{"prim":"address","annots":["%addr"]}]}]}]},{"prim":"or","args":[{"prim":"pair","annots":["%internal_ns_nd_part"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"address","annots":["%dest_address"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"nat","annots":["%token_amount"]},{"prim":"string","annots":["%source_chain"]},{"prim":"string","annots":["%md"]},{"prim":"string","annots":["%transaction_hash"]}]},{"prim":"or","args":[{"prim":"pair","annots":["%lock_sft"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"string","annots":["%dest_address"]},{"prim":"or","annots":["%source_nft_address"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"nat","annots":["%token_amount"]}]},{"prim":"or","args":[{"prim":"pair","annots":["%lock_internal"],"args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]},{"prim":"string","annots":["%dest_chain"]}]},{"prim":"or","args":[{"prim":"pair","annots":["%lock_nft"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"string","annots":["%dest_address"]},{"prim":"or","annots":["%source_nft_address"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]}]},{"prim":"or","args":[{"prim":"pair","annots":["%claim_validator_rewards"],"args":[{"prim":"address","annots":["%validator"]},{"prim":"list","annots":["%sigs"],"args":[{"prim":"pair","args":[{"prim":"key","annots":["%signer"]},{"prim":"signature","annots":["%sig"]},{"prim":"address","annots":["%addr"]}]}]}]},{"prim":"pair","annots":["%add_validator"],"args":[{"prim":"address","annots":["%validator"]},{"prim":"list","annots":["%sigs"],"args":[{"prim":"pair","args":[{"prim":"key","annots":["%signer"]},{"prim":"signature","annots":["%sig"]},{"prim":"address","annots":["%addr"]}]}]}]}]}]}]}]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"big_map","annots":["%validators"],"args":[{"prim":"address"},{"prim":"mutez"}]},{"prim":"big_map","annots":["%unique_identifiers"],"args":[{"prim":"bytes"},{"prim":"bool"}]},{"prim":"address","annots":["%collection_deployer"]},{"prim":"address","annots":["%storage_deployer"]},{"prim":"big_map","annots":["%original_to_duplicate_mapping"],"args":[{"prim":"pair","args":[{"prim":"or","args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"string"}]},{"prim":"pair","args":[{"prim":"string","annots":["%chain"]},{"prim":"or","annots":["%contract"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]}]}]},{"prim":"big_map","annots":["%duplicate_to_original_mapping"],"args":[{"prim":"pair","args":[{"prim":"or","args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"string"}]},{"prim":"pair","args":[{"prim":"string","annots":["%chain"]},{"prim":"or","annots":["%contract"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]}]}]},{"prim":"big_map","annots":["%original_storage_mapping_nft"],"args":[{"prim":"pair","args":[{"prim":"or","args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"string"}]},{"prim":"address"}]},{"prim":"big_map","annots":["%original_storage_mapping_sft"],"args":[{"prim":"pair","args":[{"prim":"or","args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"string"}]},{"prim":"address"}]},{"prim":"big_map","annots":["%duplicate_storage_mapping_nft"],"args":[{"prim":"pair","args":[{"prim":"or","args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"string"}]},{"prim":"address"}]},{"prim":"big_map","annots":["%duplicate_storage_mapping_sft"],"args":[{"prim":"pair","args":[{"prim":"or","args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"string"}]},{"prim":"address"}]},{"prim":"nat","annots":["%validators_count"]}]}]},{"prim":"code","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"TEZOS"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"singular"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"multiple"}]},{"prim":"LAMBDA","args":[{"prim":"or","args":[{"prim":"address"},{"prim":"string"}]},{"prim":"address"},[{"prim":"IF_LEFT","args":[[],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Tried to extract address from AddrOrStr which didnt have an address"}]},{"prim":"FAILWITH"}]]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"operation"},[{"prim":"UNPAIR"},{"prim":"CONTRACT","annots":["%add_deposited_token"],"args":[{"prim":"nat"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"TRANSFER_TOKENS"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"string"},{"prim":"string"}]},{"prim":"operation"},[{"prim":"EMIT","annots":["%claimed"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%source_chain"]},{"prim":"string","annots":["%tx_hash"]}]}]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"bool"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"VIEW","args":[{"string":"has_locked_token"},{"prim":"bool"}]},{"prim":"DUP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Failed to check if token is deposited"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"bytes"},{"prim":"list","args":[{"prim":"pair","args":[{"prim":"key"},{"prim":"signature"},{"prim":"address"}]}]}]},{"prim":"int"},[{"prim":"UNPAIR"},{"prim":"PUSH","args":[{"prim":"int"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CHECK_SIGNATURE"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"int"},{"int":"1"}]},{"prim":"ADD"}],[]]}]]},{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"},{"prim":"address"},{"prim":"nat"}]},{"prim":"operation"},[{"prim":"UNPAIR","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CONTRACT","annots":["%transfer"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]}]}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"CONS"},{"prim":"TRANSFER_TOKENS"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"address"}]},{"prim":"operation"},[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONTRACT","annots":["%unlock_token"],"args":[{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%to"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"TRANSFER_TOKENS"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"string"},{"prim":"nat"}]},{"prim":"operation"},[{"prim":"UNPAIR","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"CONTRACT","annots":["%mint"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%token_uri"]},{"prim":"address","annots":["%to"]},{"prim":"nat","annots":["%amt"]}]}]}]},{"prim":"DUP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Contract does not have mint entrypoint"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"nat"},{"prim":"string"},{"prim":"address"},{"prim":"nat"}]}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"CONS"},{"prim":"TRANSFER_TOKENS"}]]},{"prim":"DIG","args":[{"int":"11"}]},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"DIG","args":[{"int":"10"}]},{"prim":"DROP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"26"}]},{"prim":"AMOUNT"},{"prim":"COMPARE"},{"prim":"LT"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Insufficient fees"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Cannot transfer to the same chain"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"10"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"25"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[],[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Invalid NFT Type"}]},{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"PACK"},{"prim":"KECCAK"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Data already processed"}]},{"prim":"FAILWITH"}]]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"address"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CDR"},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"CHECK_SIGNATURE"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"int"},{"int":"1"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ADD"},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"CONS"}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"}]]},{"prim":"PAIR"}]]},{"prim":"SWAP"},{"prim":"DROP"},{"prim":"UNPAIR"},{"prim":"PUSH","args":[{"prim":"int"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"2"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"GET","args":[{"int":"20"}]},{"prim":"MUL"},{"prim":"EDIV"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"DIV by 0"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CAR"},{"prim":"ADD"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"LT"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Insufficient signatures"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"26"}]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"GT"},{"prim":"IF","args":[[],[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Fee must be greater than 0"}]},{"prim":"FAILWITH"}]]},{"prim":"BALANCE"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Insufficient rewards to distribute"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"COMPARE"},{"prim":"GE"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SIZE"},{"prim":"SWAP"},{"prim":"EDIV"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"DIV by 0"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"DUP"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Validator does not exist"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"ADD"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"UPDATE"}]]},{"prim":"SWAP"},{"prim":"DROP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"9"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"DUP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}]]},{"prim":"DUP"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"13"}]},{"prim":"DIG","args":[{"int":"13"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"17"}]}],[{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"19"}]}]]},{"prim":"DIG","args":[{"int":"13"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"PAIR"},{"prim":"GET"}],[{"prim":"DIG","args":[{"int":"12"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"12"}]},{"prim":"DIG","args":[{"int":"12"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"13"}]}],[{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"15"}]}]]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"9"}]},{"prim":"PAIR"},{"prim":"GET"}]]},{"prim":"DUP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}]]},{"prim":"DUP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"AND"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DROP","args":[{"int":"3"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SWAP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"}],[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"19"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"CONS"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"21"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"SWAP"}],[{"prim":"DUP"},{"prim":"NOT"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"AND"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"DIG","args":[{"int":"10"}]},{"prim":"DROP","args":[{"int":"6"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"19"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"CONS"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"21"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"SWAP"}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"},{"prim":"DUP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"NOT"},{"prim":"AND"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Storage not deployed for this collection"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"SWAP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"}],[{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"19"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"CONS"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"21"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"SWAP"}],[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"DIG","args":[{"int":"11"}]},{"prim":"DROP","args":[{"int":"5"}]},{"prim":"NOT"},{"prim":"SWAP"},{"prim":"NOT"},{"prim":"AND"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"CONTRACT","annots":["%deploy_nft"],"args":[{"prim":"or","args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"9"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%internal_ns_nd_part"],"args":[{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"address","annots":["%dest_address"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"nat","annots":["%token_amount"]},{"prim":"string","annots":["%source_chain"]},{"prim":"string","annots":["%md"]},{"prim":"string","annots":["%transaction_hash"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"21"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"19"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"23"}]},{"prim":"DUP","args":[{"int":"10"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"11"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"12"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"12"}]},{"prim":"CAR"},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"8"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"CONS"}],[{"prim":"SWAP"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"21"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"SWAP"}]]}]]}]]}]]},{"prim":"SWAP"}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"DROP","args":[{"int":"6"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Only Callable by Self"}]},{"prim":"SELF_ADDRESS"},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"VIEW","args":[{"string":"get_store"},{"prim":"address"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Collection not deployed"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"DROP","args":[{"int":"2"}]}]]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"LEFT","args":[{"prim":"string"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"LEFT","args":[{"prim":"string"}]},{"prim":"PAIR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"13"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"14"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"UPDATE","args":[{"int":"11"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"UPDATE","args":[{"int":"9"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"2"}]}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DROP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"15"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%deploy_sft_storage"],"args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"TRANSFER_TOKENS"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]},{"prim":"string","annots":["%dest_chain"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]},{"prim":"string","annots":["%dest_chain"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]}]]}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"19"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%deploy_sft_storage"],"args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"TRANSFER_TOKENS"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]},{"prim":"string","annots":["%dest_chain"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]},{"prim":"string","annots":["%dest_chain"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]},{"prim":"DIG","args":[{"int":"2"}]}],[{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Only Callable by Self"}]},{"prim":"SELF_ADDRESS"},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"VIEW","args":[{"string":"get_store"},{"prim":"address"}]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Storage contract not deployed"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"IF_NONE","args":[[{"prim":"FAILWITH"}],[{"prim":"DROP","args":[{"int":"2"}]}]]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"13"}]}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"15"}]}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"13"}]},{"prim":"SWAP"}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"}]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"SOURCE"},{"prim":"PAIR","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"8"}]},{"prim":"DROP"}],[{"prim":"DIG","args":[{"int":"9"}]},{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"GET","args":[{"int":"12"}]},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"EMIT","annots":["%locked"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%dest_address"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"string","annots":["%nft_type"]},{"prim":"string","annots":["%source_chain"]},{"prim":"or","annots":["%source_nft_address"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"nat","annots":["%token_amount"]},{"prim":"nat","annots":["%token_id"]}]}]}],[{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"17"}]}],[{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"19"}]}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"12"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"17"}]},{"prim":"SWAP"}],[]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"MAP FIND"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"SOURCE"},{"prim":"PAIR","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DROP"}],[{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"9"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"GET","args":[{"int":"12"}]},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"EMIT","annots":["%locked"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%dest_address"]},{"prim":"string","annots":["%dest_chain"]},{"prim":"string","annots":["%nft_type"]},{"prim":"string","annots":["%source_chain"]},{"prim":"or","annots":["%source_nft_address"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"nat","annots":["%token_amount"]},{"prim":"nat","annots":["%token_id"]}]}]}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"2"}]}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DROP","args":[{"int":"4"}]},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"11"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"13"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"CONTRACT","annots":["%deploy_nft_storage"],"args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"TRANSFER_TOKENS"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]},{"prim":"string","annots":["%dest_chain"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]},{"prim":"string","annots":["%dest_chain"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]}]]}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"17"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"7"}]},{"prim":"CONTRACT","annots":["%deploy_nft_storage"],"args":[{"prim":"address"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"TRANSFER_TOKENS"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]},{"prim":"string","annots":["%dest_chain"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"9"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"SELF_ADDRESS"},{"prim":"CONTRACT","annots":["%lock_internal"],"args":[{"prim":"pair","args":[{"prim":"string","annots":["%to"]},{"prim":"nat","annots":["%token_id"]},{"prim":"or","annots":["%collection"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"bool","annots":["%original"]},{"prim":"nat","annots":["%amt"]},{"prim":"bool","annots":["%new_deploy"]},{"prim":"string","annots":["%dest_chain"]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR","args":[{"int":"7"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]},{"prim":"DIG","args":[{"int":"2"}]}],[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"IF_LEFT","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"SIZE"},{"prim":"COMPARE"},{"prim":"GT"},{"prim":"IF","args":[[],[{"prim":"PUSH","args":[{"prim":"string"},{"string":"No signatures provided"}]},{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET"},{"prim":"DUP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Validator does not exist"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"PACK"},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Insufficient signatures"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"2"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"GET","args":[{"int":"20"}]},{"prim":"MUL"},{"prim":"EDIV"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"DIV by 0"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CAR"},{"prim":"ADD"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"GE"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"EMIT","annots":["%rewarded_validator"],"args":[{"prim":"address"}]},{"prim":"SWAP"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"CONTRACT","args":[{"prim":"unit"}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_contract"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SWAP"},{"prim":"UNIT"},{"prim":"TRANSFER_TOKENS"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"2"}]}],[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"SIZE"},{"prim":"COMPARE"},{"prim":"GT"},{"prim":"IF","args":[[],[{"prim":"PUSH","args":[{"prim":"string"},{"string":"No signatures provided"}]},{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Validator already exists"}]},{"prim":"FAILWITH"}]]},{"prim":"DUP"},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"PACK"},{"prim":"PAIR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Insufficient signatures"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"2"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"20"}]},{"prim":"MUL"},{"prim":"EDIV"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"DIV by 0"}]},{"prim":"FAILWITH"}],[]]},{"prim":"CAR"},{"prim":"ADD"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"GE"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"20"}]},{"prim":"ADD"},{"prim":"UPDATE","args":[{"int":"20"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"EMIT","annots":["%added_new_validator"],"args":[{"prim":"address"}]}]]}]]}]]}]]}]]}]]},{"prim":"CONS"},{"prim":"PAIR"}]]}]`, ), }; diff --git a/src/contractsTypes/tezosContractTypes/Bridge.types.ts b/src/contractsTypes/tezosContractTypes/Bridge.types.ts index 38cb1a9e..13ccaee2 100644 --- a/src/contractsTypes/tezosContractTypes/Bridge.types.ts +++ b/src/contractsTypes/tezosContractTypes/Bridge.types.ts @@ -19,48 +19,48 @@ export type Storage = { storage_deployer: address; original_to_duplicate_mapping: BigMap< { - 0: address; + 0: { addr: address } | { str: string }; 1: string; }, { chain: string; - contract: bytes; + contract: { addr: address } | { str: string }; } >; duplicate_to_original_mapping: BigMap< { - 0: address; + 0: { addr: address } | { str: string }; 1: string; }, { chain: string; - contract: bytes; + contract: { addr: address } | { str: string }; } >; original_storage_mapping_nft: BigMap< { - 0: address; + 0: { addr: address } | { str: string }; 1: string; }, address >; original_storage_mapping_sft: BigMap< { - 0: address; + 0: { addr: address } | { str: string }; 1: string; }, address >; duplicate_storage_mapping_nft: BigMap< { - 0: address; + 0: { addr: address } | { str: string }; 1: string; }, address >; duplicate_storage_mapping_sft: BigMap< { - 0: address; + 0: { addr: address } | { str: string }; 1: string; }, address @@ -74,7 +74,7 @@ type Methods = { source_chain: string, dest_chain: string, dest_address: address, - source_nft_contract_address: bytes, + source_nft_contract_address: { addr: address } | { str: string }, name: string, symbol: string, royalty: nat, @@ -94,7 +94,7 @@ type Methods = { token_id: nat, dest_chain: string, dest_address: address, - collection: address, + collection: { addr: address } | { str: string }, token_amount: nat, source_chain: string, md: string, @@ -104,22 +104,23 @@ type Methods = { token_id: nat, dest_chain: string, dest_address: string, - source_nft_address: address, + source_nft_address: { addr: address } | { str: string }, token_amount: nat, ) => Promise; lock_internal: ( to: string, token_id: nat, - collection: address, + collection: { addr: address } | { str: string }, original: boolean, amt: nat, new_deploy: boolean, + dest_chain: string, ) => Promise; lock_nft: ( token_id: nat, dest_chain: string, dest_address: string, - source_nft_address: address, + source_nft_address: { addr: address } | { str: string }, ) => Promise; claim_validator_rewards: ( validator: address, @@ -145,7 +146,7 @@ type MethodsObject = { source_chain: string; dest_chain: string; dest_address: address; - source_nft_contract_address: bytes; + source_nft_contract_address: { addr: address } | { str: string }; name: string; symbol: string; royalty: nat; @@ -165,7 +166,7 @@ type MethodsObject = { token_id: nat; dest_chain: string; dest_address: address; - collection: address; + collection: { addr: address } | { str: string }; token_amount: nat; source_chain: string; md: string; @@ -175,22 +176,23 @@ type MethodsObject = { token_id: nat; dest_chain: string; dest_address: string; - source_nft_address: address; + source_nft_address: { addr: address } | { str: string }; token_amount: nat; }) => Promise; lock_internal: (params: { to: string; token_id: nat; - collection: address; + collection: { addr: address } | { str: string }; original: boolean; amt: nat; new_deploy: boolean; + dest_chain: string; }) => Promise; lock_nft: (params: { token_id: nat; dest_chain: string; dest_address: string; - source_nft_address: address; + source_nft_address: { addr: address } | { str: string }; }) => Promise; claim_validator_rewards: (params: { validator: address; diff --git a/src/contractsTypes/tezosContractTypes/CollectionFactory.code.ts b/src/contractsTypes/tezosContractTypes/CollectionFactory.code.ts index e6562e52..957505c1 100644 --- a/src/contractsTypes/tezosContractTypes/CollectionFactory.code.ts +++ b/src/contractsTypes/tezosContractTypes/CollectionFactory.code.ts @@ -6,6 +6,6 @@ export const CollectionFactoryCode: { __type: 'CollectionFactoryCode', protocol: 'PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA', code: JSON.parse( - `[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"address","annots":["%deploy_sft"]},{"prim":"or","args":[{"prim":"address","annots":["%deploy_nft"]},{"prim":"address","annots":["%set_owner"]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"option","annots":["%owner"],"args":[{"prim":"address"}]},{"prim":"map","annots":["%collection_to_store"],"args":[{"prim":"address"},{"prim":"address"}]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"option","args":[{"prim":"address"}]},{"prim":"map","args":[{"prim":"address"},{"prim":"address"}]}]},{"prim":"unit"},[{"prim":"DUP"},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Contract is not initialized"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SENDER"},{"prim":"SWAP"},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Only owner can call this function"}]},{"prim":"FAILWITH"}],[]]},{"prim":"UNIT"}]]},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat"},{"prim":"map","args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"}]},{"prim":"PAIR","args":[{"int":"5"}]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NONE","args":[{"prim":"key_hash"}]},{"prim":"CREATE_CONTRACT","args":[[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"list","annots":["%update_operators"],"args":[{"prim":"or","args":[{"prim":"pair","annots":["%add_operator"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"pair","annots":["%remove_operator"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]}]}]},{"prim":"or","args":[{"prim":"pair","annots":["%balance_of"],"args":[{"prim":"list","annots":["%requests"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"nat","annots":["%token_id"]}]}]},{"prim":"contract","annots":["%callback"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"pair","annots":["%request"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"nat","annots":["%balance"]}]}]}]}]},{"prim":"list","annots":["%transfer"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"big_map","annots":["%ledger"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"}]},{"prim":"big_map","annots":["%operators"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"big_map","annots":["%token_metadata"],"args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"map","annots":["%token_info"],"args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"big_map","annots":["%metadata"],"args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"address","annots":["%admin"]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"address"},{"prim":"unit"},[{"prim":"PUSH","args":[{"prim":"string"},{"string":"The sender can only manage operators for his own token"}]},{"prim":"SENDER"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"UNIT"}],[{"prim":"FAILWITH"}]]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat"},{"prim":"map","args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"nat"}]},{"prim":"unit"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"UNIT"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"}]},{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"},[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"DUG","args":[{"int":"2"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]}],[]]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"}]},{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]},{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"}]},[{"prim":"UNPAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"lambda","args":[{"prim":"address"},{"prim":"unit"}]},{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"or","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"}]},{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"}]}]}]}]},{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"IF_LEFT","args":[[{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"4"}]}],[{"prim":"DUP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]}],[{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"4"}]}],[{"prim":"DUP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"},{"prim":"NONE","args":[{"prim":"set","args":[{"prim":"nat"}]}]}],[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SIZE"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"NONE","args":[{"prim":"set","args":[{"prim":"nat"}]}]}],[{"prim":"SOME"}]]}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]}]]}]]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"APPLY"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"SWAP"},{"prim":"DROP"},{"prim":"UPDATE","args":[{"int":"3"}]},{"prim":"NIL","args":[{"prim":"operation"}]}],[{"prim":"DIG","args":[{"int":"5"}]},{"prim":"DROP"},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"UNPAIR"},{"prim":"MAP","args":[[{"prim":"DUP"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"SWAP"},{"prim":"PAIR"}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"ITER","args":[[{"prim":"UNPAIR"},{"prim":"DUG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"10"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"SENDER"},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"7"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"MEM"},{"prim":"NOT"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_NOT_OPERATOR"}]},{"prim":"FAILWITH"}],[]]}],[{"prim":"DROP"}]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_INSUFFICIENT_BALANCE"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"COMPARE"},{"prim":"GE"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"SUB"},{"prim":"ABS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"6"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"9"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"ADD"},{"prim":"DUG","args":[{"int":"3"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"3"}]},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_balance"},{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"},[{"prim":"UNPAIR"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUG","args":[{"int":"2"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]}],[]]}]]},{"prim":"view","args":[{"string":"total_supply"},{"prim":"nat"},{"prim":"nat"},[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Feature not available. Maybe use an indexer instead"}]},{"prim":"FAILWITH"}]]},{"prim":"view","args":[{"string":"all_tokens"},{"prim":"unit"},{"prim":"set","args":[{"prim":"nat"}]},[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Feature not available. Maybe use an indexer instead"}]},{"prim":"FAILWITH"}]]},{"prim":"view","args":[{"string":"is_operator"},{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"bool"},[{"prim":"UNPAIR"},{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"SIZE"},{"prim":"COMPARE"},{"prim":"GT"},{"prim":"OR"}]]},{"prim":"view","args":[{"string":"token_metadata"},{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"map","annots":["%token_info"],"args":[{"prim":"string"},{"prim":"bytes"}]}]},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[]]}]]}]]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"CONS"}],[{"prim":"IF_LEFT","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat"},{"prim":"map","args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"nat"},{"prim":"address"}]},{"prim":"PAIR","args":[{"int":"5"}]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NONE","args":[{"prim":"key_hash"}]},{"prim":"CREATE_CONTRACT","args":[[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"list","annots":["%update_operators"],"args":[{"prim":"or","args":[{"prim":"pair","annots":["%add_operator"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"pair","annots":["%remove_operator"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]}]}]},{"prim":"or","args":[{"prim":"pair","annots":["%balance_of"],"args":[{"prim":"list","annots":["%requests"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"nat","annots":["%token_id"]}]}]},{"prim":"contract","annots":["%callback"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"pair","annots":["%request"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"nat","annots":["%balance"]}]}]}]}]},{"prim":"list","annots":["%transfer"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"big_map","annots":["%ledger"],"args":[{"prim":"nat"},{"prim":"address"}]},{"prim":"big_map","annots":["%operators"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"big_map","annots":["%token_metadata"],"args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"map","annots":["%token_info"],"args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"big_map","annots":["%metadata"],"args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"address","annots":["%admin"]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"address"},{"prim":"unit"},[{"prim":"PUSH","args":[{"prim":"string"},{"string":"The sender can only manage operators for his own token"}]},{"prim":"SENDER"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"UNIT"}],[{"prim":"FAILWITH"}]]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat"},{"prim":"map","args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"nat"}]},{"prim":"unit"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"UNIT"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"nat"},{"prim":"address"}]},{"prim":"nat"},{"prim":"address"}]},{"prim":"bool"},[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"EQ"}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"lambda","args":[{"prim":"address"},{"prim":"unit"}]},{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"or","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"}]},{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"}]}]}]}]},{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"IF_LEFT","args":[[{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"4"}]}],[{"prim":"DUP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]}],[{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"4"}]}],[{"prim":"DUP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"},{"prim":"NONE","args":[{"prim":"set","args":[{"prim":"nat"}]}]}],[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SIZE"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"NONE","args":[{"prim":"set","args":[{"prim":"nat"}]}]}],[{"prim":"SOME"}]]}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]}]]}]]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"APPLY"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"SWAP"},{"prim":"DROP"},{"prim":"UPDATE","args":[{"int":"3"}]},{"prim":"NIL","args":[{"prim":"operation"}]}],[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"IF_LEFT","args":[[{"prim":"UNPAIR"},{"prim":"MAP","args":[[{"prim":"DUP"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}],[]]},{"prim":"SWAP"},{"prim":"PAIR"}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"ITER","args":[[{"prim":"UNPAIR"},{"prim":"DUG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"SENDER"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"MEM"},{"prim":"NOT"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_NOT_OPERATOR"}]},{"prim":"FAILWITH"}],[]]}],[{"prim":"DROP"}]]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_INSUFFICIENT_BALANCE"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"UPDATE"}]]},{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_balance"},{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"},[{"prim":"UNPAIR"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}],[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]}]]}]]},{"prim":"view","args":[{"string":"total_supply"},{"prim":"nat"},{"prim":"nat"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}]]},{"prim":"view","args":[{"string":"all_tokens"},{"prim":"unit"},{"prim":"set","args":[{"prim":"nat"}]},[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Feature not available. Maybe use an indexer instead"}]},{"prim":"FAILWITH"}]]},{"prim":"view","args":[{"string":"is_operator"},{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"bool"},[{"prim":"UNPAIR"},{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"MEM"},{"prim":"OR"}]]},{"prim":"view","args":[{"string":"token_metadata"},{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"map","annots":["%token_info"],"args":[{"prim":"string"},{"prim":"bytes"}]}]},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[]]}]]}]]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"CONS"}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}]]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Owner already set"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SOME"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_store"},{"prim":"address"},{"prim":"address"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"CDR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"MAP FIND"}]},{"prim":"FAILWITH"}],[]]}]]},{"prim":"view","args":[{"string":"get_owner"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]}]]}]`, + `[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"or","annots":["%deploy_nft"],"args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"address","annots":["%set_owner"]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"option","annots":["%owner"],"args":[{"prim":"address"}]},{"prim":"map","annots":["%collection_to_store"],"args":[{"prim":"or","args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"address"}]}]}]},{"prim":"code","args":[[{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Contract is not initialized"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SENDER"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Only owner can call this function"}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat"},{"prim":"map","args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"EMPTY_BIG_MAP","args":[{"prim":"nat"},{"prim":"address"}]},{"prim":"PAIR","args":[{"int":"5"}]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NONE","args":[{"prim":"key_hash"}]},{"prim":"CREATE_CONTRACT","args":[[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"list","annots":["%update_operators"],"args":[{"prim":"or","args":[{"prim":"pair","annots":["%add_operator"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"pair","annots":["%remove_operator"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]}]}]},{"prim":"or","args":[{"prim":"list","annots":["%mint"],"args":[{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%token_uri"]},{"prim":"address","annots":["%to"]},{"prim":"nat","annots":["%amt"]}]}]},{"prim":"or","args":[{"prim":"pair","annots":["%balance_of"],"args":[{"prim":"list","annots":["%requests"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"nat","annots":["%token_id"]}]}]},{"prim":"contract","annots":["%callback"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"pair","annots":["%request"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"nat","annots":["%balance"]}]}]}]}]},{"prim":"list","annots":["%transfer"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"big_map","annots":["%ledger"],"args":[{"prim":"nat"},{"prim":"address"}]},{"prim":"big_map","annots":["%operators"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"big_map","annots":["%token_metadata"],"args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"map","annots":["%token_info"],"args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"big_map","annots":["%metadata"],"args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"address","annots":["%admin"]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"address"},{"prim":"unit"},[{"prim":"PUSH","args":[{"prim":"string"},{"string":"The sender can only manage operators for his own token"}]},{"prim":"SENDER"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"UNIT"}],[{"prim":"FAILWITH"}]]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat"},{"prim":"map","args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"nat"}]},{"prim":"unit"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"UNIT"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"nat"},{"prim":"address"}]},{"prim":"nat"},{"prim":"address"}]},{"prim":"bool"},[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"EQ"}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"lambda","args":[{"prim":"address"},{"prim":"unit"}]},{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"or","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"}]},{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"}]}]}]}]},{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"IF_LEFT","args":[[{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"4"}]}],[{"prim":"DUP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]}],[{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"4"}]}],[{"prim":"DUP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"},{"prim":"NONE","args":[{"prim":"set","args":[{"prim":"nat"}]}]}],[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SIZE"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"NONE","args":[{"prim":"set","args":[{"prim":"nat"}]}]}],[{"prim":"SOME"}]]}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]}]]}]]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"APPLY"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"SWAP"},{"prim":"DROP"},{"prim":"UPDATE","args":[{"int":"3"}]},{"prim":"NIL","args":[{"prim":"operation"}]}],[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Mint Can Only Be Called By Owner"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"8"}]},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Token ID Already Exists"}]},{"prim":"FAILWITH"}]]},{"prim":"EMPTY_MAP","args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PACK"},{"prim":"PUSH","args":[{"prim":"string"},{"string":""}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR"},{"prim":"SOME"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"EMPTY_SET","args":[{"prim":"nat"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"SOME"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"3"}]}]]},{"prim":"NIL","args":[{"prim":"operation"}]}],[{"prim":"IF_LEFT","args":[[{"prim":"UNPAIR"},{"prim":"MAP","args":[[{"prim":"DUP"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}],[]]},{"prim":"SWAP"},{"prim":"PAIR"}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"ITER","args":[[{"prim":"UNPAIR"},{"prim":"DUG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"SENDER"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"MEM"},{"prim":"NOT"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_NOT_OPERATOR"}]},{"prim":"FAILWITH"}],[]]}],[{"prim":"DROP"}]]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_INSUFFICIENT_BALANCE"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"UPDATE"}]]},{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_balance"},{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"},[{"prim":"UNPAIR"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}],[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]}]]}]]},{"prim":"view","args":[{"string":"owner_of"},{"prim":"nat"},{"prim":"address"},[{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"SWAP"},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"MAP FIND"}]},{"prim":"FAILWITH"}],[]]}]]},{"prim":"view","args":[{"string":"total_supply"},{"prim":"nat"},{"prim":"nat"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}]]},{"prim":"view","args":[{"string":"all_tokens"},{"prim":"unit"},{"prim":"set","args":[{"prim":"nat"}]},[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Feature not available. Maybe use an indexer instead"}]},{"prim":"FAILWITH"}]]},{"prim":"view","args":[{"string":"is_operator"},{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"bool"},[{"prim":"UNPAIR"},{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"MEM"},{"prim":"OR"}]]},{"prim":"view","args":[{"string":"token_metadata"},{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"map","annots":["%token_info"],"args":[{"prim":"string"},{"prim":"bytes"}]}]},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[]]}]]}]]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"CONS"}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}]]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Owner already set"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SOME"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_store"},{"prim":"or","args":[{"prim":"address","annots":["%addr"]},{"prim":"string","annots":["%str"]}]},{"prim":"address"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"CDR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"MAP FIND"}]},{"prim":"FAILWITH"}],[]]}]]},{"prim":"view","args":[{"string":"get_owner"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]}]]}]`, ), }; diff --git a/src/contractsTypes/tezosContractTypes/CollectionFactory.types.ts b/src/contractsTypes/tezosContractTypes/CollectionFactory.types.ts index 7892b322..d6359b77 100644 --- a/src/contractsTypes/tezosContractTypes/CollectionFactory.types.ts +++ b/src/contractsTypes/tezosContractTypes/CollectionFactory.types.ts @@ -6,18 +6,18 @@ import { address, MMap } from './type-aliases'; export type Storage = { owner: { Some: address } | null; - collection_to_store: MMap; + collection_to_store: MMap<{ addr: address } | { str: string }, address>; }; type Methods = { - deploy_sft: (param: address) => Promise; - deploy_nft: (param: address) => Promise; + addr: (param: address) => Promise; + str: (param: string) => Promise; set_owner: (param: address) => Promise; }; type MethodsObject = { - deploy_sft: (param: address) => Promise; - deploy_nft: (param: address) => Promise; + addr: (param: address) => Promise; + str: (param: string) => Promise; set_owner: (param: address) => Promise; }; diff --git a/src/contractsTypes/tezosContractTypes/NFT.code.ts b/src/contractsTypes/tezosContractTypes/NFT.code.ts index 61c57b78..07d3f0ae 100644 --- a/src/contractsTypes/tezosContractTypes/NFT.code.ts +++ b/src/contractsTypes/tezosContractTypes/NFT.code.ts @@ -3,6 +3,6 @@ export const NFTCode: { __type: 'NFTCode'; protocol: string; code: object[] } = __type: 'NFTCode', protocol: 'PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA', code: JSON.parse( - `[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"list","annots":["%mint"],"args":[{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%token_uri"]},{"prim":"address","annots":["%to"]},{"prim":"nat","annots":["%amt"]}]}]},{"prim":"or","args":[{"prim":"list","annots":["%update_operators"],"args":[{"prim":"or","args":[{"prim":"pair","annots":["%add_operator"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"pair","annots":["%remove_operator"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]}]}]},{"prim":"or","args":[{"prim":"pair","annots":["%balance_of"],"args":[{"prim":"list","annots":["%requests"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"nat","annots":["%token_id"]}]}]},{"prim":"contract","annots":["%callback"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"pair","annots":["%request"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"nat","annots":["%balance"]}]}]}]}]},{"prim":"list","annots":["%transfer"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"big_map","annots":["%ledger"],"args":[{"prim":"nat"},{"prim":"address"}]},{"prim":"big_map","annots":["%operators"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"big_map","annots":["%token_metadata"],"args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"map","annots":["%token_info"],"args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"big_map","annots":["%metadata"],"args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"address","annots":["%admin"]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"address"},{"prim":"unit"},[{"prim":"PUSH","args":[{"prim":"string"},{"string":"The sender can only manage operators for his own token"}]},{"prim":"SENDER"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"UNIT"}],[{"prim":"FAILWITH"}]]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat"},{"prim":"map","args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"nat"}]},{"prim":"unit"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"UNIT"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"nat"},{"prim":"address"}]},{"prim":"nat"},{"prim":"address"}]},{"prim":"bool"},[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"EQ"}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"3"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Mint Can Only Be Called By Owner"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"8"}]},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Token ID Already Exists"}]},{"prim":"FAILWITH"}]]},{"prim":"EMPTY_MAP","args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PACK"},{"prim":"PUSH","args":[{"prim":"string"},{"string":""}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR"},{"prim":"SOME"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"EMPTY_SET","args":[{"prim":"nat"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"SOME"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"3"}]}]]},{"prim":"NIL","args":[{"prim":"operation"}]}],[{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"lambda","args":[{"prim":"address"},{"prim":"unit"}]},{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"or","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"}]},{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"}]}]}]}]},{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"IF_LEFT","args":[[{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"4"}]}],[{"prim":"DUP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]}],[{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"4"}]}],[{"prim":"DUP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"},{"prim":"NONE","args":[{"prim":"set","args":[{"prim":"nat"}]}]}],[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SIZE"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"NONE","args":[{"prim":"set","args":[{"prim":"nat"}]}]}],[{"prim":"SOME"}]]}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]}]]}]]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"APPLY"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"SWAP"},{"prim":"DROP"},{"prim":"UPDATE","args":[{"int":"3"}]},{"prim":"NIL","args":[{"prim":"operation"}]}],[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"IF_LEFT","args":[[{"prim":"UNPAIR"},{"prim":"MAP","args":[[{"prim":"DUP"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}],[]]},{"prim":"SWAP"},{"prim":"PAIR"}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"ITER","args":[[{"prim":"UNPAIR"},{"prim":"DUG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"SENDER"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"MEM"},{"prim":"NOT"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_NOT_OPERATOR"}]},{"prim":"FAILWITH"}],[]]}],[{"prim":"DROP"}]]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_INSUFFICIENT_BALANCE"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"UPDATE"}]]},{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_balance"},{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"},[{"prim":"UNPAIR"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}],[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]}]]}]]},{"prim":"view","args":[{"string":"total_supply"},{"prim":"nat"},{"prim":"nat"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}]]},{"prim":"view","args":[{"string":"all_tokens"},{"prim":"unit"},{"prim":"set","args":[{"prim":"nat"}]},[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Feature not available. Maybe use an indexer instead"}]},{"prim":"FAILWITH"}]]},{"prim":"view","args":[{"string":"is_operator"},{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"bool"},[{"prim":"UNPAIR"},{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"MEM"},{"prim":"OR"}]]},{"prim":"view","args":[{"string":"token_metadata"},{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"map","annots":["%token_info"],"args":[{"prim":"string"},{"prim":"bytes"}]}]},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[]]}]]}]`, + `[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"list","annots":["%update_operators"],"args":[{"prim":"or","args":[{"prim":"pair","annots":["%add_operator"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"pair","annots":["%remove_operator"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]}]}]},{"prim":"or","args":[{"prim":"list","annots":["%mint"],"args":[{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"string","annots":["%token_uri"]},{"prim":"address","annots":["%to"]},{"prim":"nat","annots":["%amt"]}]}]},{"prim":"or","args":[{"prim":"pair","annots":["%balance_of"],"args":[{"prim":"list","annots":["%requests"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"nat","annots":["%token_id"]}]}]},{"prim":"contract","annots":["%callback"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"pair","annots":["%request"],"args":[{"prim":"address","annots":["%owner"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"nat","annots":["%balance"]}]}]}]}]},{"prim":"list","annots":["%transfer"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"big_map","annots":["%ledger"],"args":[{"prim":"nat"},{"prim":"address"}]},{"prim":"big_map","annots":["%operators"],"args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"big_map","annots":["%token_metadata"],"args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"map","annots":["%token_info"],"args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"big_map","annots":["%metadata"],"args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"address","annots":["%admin"]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"address"},{"prim":"unit"},[{"prim":"PUSH","args":[{"prim":"string"},{"string":"The sender can only manage operators for his own token"}]},{"prim":"SENDER"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"UNIT"}],[{"prim":"FAILWITH"}]]}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat"},{"prim":"map","args":[{"prim":"string"},{"prim":"bytes"}]}]}]},{"prim":"nat"}]},{"prim":"unit"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"UNIT"}]]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"nat"},{"prim":"address"}]},{"prim":"nat"},{"prim":"address"}]},{"prim":"bool"},[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"EQ"}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"lambda","args":[{"prim":"address"},{"prim":"unit"}]},{"prim":"pair","args":[{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"or","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"}]},{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"}]}]}]}]},{"prim":"big_map","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"}]},{"prim":"set","args":[{"prim":"nat"}]}]},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"IF_LEFT","args":[[{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"4"}]}],[{"prim":"DUP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]}],[{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"4"}]}],[{"prim":"DUP"},{"prim":"DIG","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP"},{"prim":"NONE","args":[{"prim":"set","args":[{"prim":"nat"}]}]}],[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SIZE"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"NONE","args":[{"prim":"set","args":[{"prim":"nat"}]}]}],[{"prim":"SOME"}]]}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR"},{"prim":"UPDATE"}]]}]]}]]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"APPLY"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"SWAP"},{"prim":"DROP"},{"prim":"UPDATE","args":[{"int":"3"}]},{"prim":"NIL","args":[{"prim":"operation"}]}],[{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP"},{"prim":"IF_LEFT","args":[[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"SWAP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Mint Can Only Be Called By Owner"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"8"}]},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DUP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Token ID Already Exists"}]},{"prim":"FAILWITH"}]]},{"prim":"EMPTY_MAP","args":[{"prim":"string"},{"prim":"bytes"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"PACK"},{"prim":"PUSH","args":[{"prim":"string"},{"string":""}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR"},{"prim":"SOME"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"EMPTY_SET","args":[{"prim":"nat"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"SOME"},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"3"}]}]]},{"prim":"NIL","args":[{"prim":"operation"}]}],[{"prim":"IF_LEFT","args":[[{"prim":"UNPAIR"},{"prim":"MAP","args":[[{"prim":"DUP"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]},{"prim":"SWAP"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"CAR"},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"IF","args":[[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}],[]]},{"prim":"SWAP"},{"prim":"PAIR"}]]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"TRANSFER_TOKENS"},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"ITER","args":[[{"prim":"UNPAIR"},{"prim":"DUG","args":[{"int":"2"}]},{"prim":"ITER","args":[[{"prim":"UNPAIR","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"SENDER"},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"DUP","args":[{"int":"6"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"MEM"},{"prim":"NOT"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_NOT_OPERATOR"}]},{"prim":"FAILWITH"}],[]]}],[{"prim":"DROP"}]]},{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_INSUFFICIENT_BALANCE"}]},{"prim":"DUP","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"6"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"IF","args":[[{"prim":"DROP"}],[{"prim":"FAILWITH"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"UPDATE"}]]},{"prim":"SWAP"},{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"DROP","args":[{"int":"2"}]},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_balance"},{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"}]},{"prim":"nat"},[{"prim":"UNPAIR"},{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}],[{"prim":"PUSH","args":[{"prim":"nat"},{"int":"0"}]}]]}]]},{"prim":"view","args":[{"string":"owner_of"},{"prim":"nat"},{"prim":"address"},[{"prim":"UNPAIR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"5"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"SWAP"},{"prim":"CAR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"MAP FIND"}]},{"prim":"FAILWITH"}],[]]}]]},{"prim":"view","args":[{"string":"total_supply"},{"prim":"nat"},{"prim":"nat"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[{"prim":"DROP"}]]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]}]]},{"prim":"view","args":[{"string":"all_tokens"},{"prim":"unit"},{"prim":"set","args":[{"prim":"nat"}]},[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"string"},{"string":"Feature not available. Maybe use an indexer instead"}]},{"prim":"FAILWITH"}]]},{"prim":"view","args":[{"string":"is_operator"},{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%operator"]},{"prim":"nat","annots":["%token_id"]}]},{"prim":"bool"},[{"prim":"UNPAIR"},{"prim":"DUP"},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"COMPARE"},{"prim":"EQ"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"PAIR"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"EMPTY_SET","args":[{"prim":"nat"}]}],[]]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"MEM"},{"prim":"OR"}]]},{"prim":"view","args":[{"string":"token_metadata"},{"prim":"nat"},{"prim":"pair","args":[{"prim":"nat","annots":["%token_id"]},{"prim":"map","annots":["%token_info"],"args":[{"prim":"string"},{"prim":"bytes"}]}]},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"5"}]},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"FA2_TOKEN_UNDEFINED"}]},{"prim":"FAILWITH"}],[]]}]]}]`, ), }; diff --git a/src/contractsTypes/tezosContractTypes/NFT.types.ts b/src/contractsTypes/tezosContractTypes/NFT.types.ts index e8ce27b4..606dc6cd 100644 --- a/src/contractsTypes/tezosContractTypes/NFT.types.ts +++ b/src/contractsTypes/tezosContractTypes/NFT.types.ts @@ -25,14 +25,6 @@ export type Storage = { }; type Methods = { - mint: ( - param: Array<{ - token_id: nat; - token_uri: string; - to: address; - amt: nat; - }>, - ) => Promise; add_operator: ( owner: address, operator: address, @@ -43,6 +35,14 @@ type Methods = { operator: address, token_id: nat, ) => Promise; + mint: ( + param: Array<{ + token_id: nat; + token_uri: string; + to: address; + amt: nat; + }>, + ) => Promise; balance_of: ( requests: Array<{ owner: address; @@ -63,14 +63,6 @@ type Methods = { }; type MethodsObject = { - mint: ( - param: Array<{ - token_id: nat; - token_uri: string; - to: address; - amt: nat; - }>, - ) => Promise; add_operator: (params: { owner: address; operator: address; @@ -81,6 +73,14 @@ type MethodsObject = { operator: address; token_id: nat; }) => Promise; + mint: ( + param: Array<{ + token_id: nat; + token_uri: string; + to: address; + amt: nat; + }>, + ) => Promise; balance_of: (params: { requests: Array<{ owner: address; diff --git a/src/contractsTypes/tezosContractTypes/NFTStorage.code.ts b/src/contractsTypes/tezosContractTypes/NFTStorage.code.ts index 78c7a912..89c751ca 100644 --- a/src/contractsTypes/tezosContractTypes/NFTStorage.code.ts +++ b/src/contractsTypes/tezosContractTypes/NFTStorage.code.ts @@ -4,8 +4,8 @@ export const NFTStorageCode: { code: object[]; } = { __type: 'NFTStorageCode', - protocol: 'PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA', + protocol: 'PsDELPH1Kxsxt8f9eWbxQeRxkjfbxoqM52jvs5Y5fBxWWh4ifpo', code: JSON.parse( - `[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"pair","annots":["%unlock_token"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%to"]}]},{"prim":"nat","annots":["%deposit_token"]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%collection"]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"},{"prim":"address"},{"prim":"address"}]},{"prim":"operation"},[{"prim":"UNPAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"CONTRACT","annots":["%transfer"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]}]}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"CONS"},{"prim":"TRANSFER_TOKENS"}]]},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"SELF_ADDRESS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Cannot perform this function since you are not the owner."}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}],[{"prim":"SELF_ADDRESS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUG","args":[{"int":"2"}]},{"prim":"SOURCE"},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_collection_address"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CDR"}]]},{"prim":"view","args":[{"string":"get_owner"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CDR"}]]}]`, + `[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"pair","annots":["%unlock_token"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%to"]}]},{"prim":"nat","annots":["%add_deposited_token"]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%collection"]},{"prim":"set","annots":["%locked"],"args":[{"prim":"nat"}]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"unit"},[{"prim":"CAR"},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Cannot perform this function since you are not the owner."}]},{"prim":"FAILWITH"}],[]]},{"prim":"UNIT"}]]},{"prim":"SWAP"},[[{"prim":"DUP"},{"prim":"CAR"},{"prim":"DIP","args":[[{"prim":"CDR"}]]}]],{"prim":"IF_LEFT","args":[[{"prim":"SELF_ADDRESS"},[{"prim":"DIP","args":[{"int":"2"},[{"prim":"DUP"}]]},{"prim":"DIG","args":[{"int":"3"}]}],{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},[{"prim":"DIP","args":[{"int":"2"},[{"prim":"DUP"}]]},{"prim":"DIG","args":[{"int":"3"}]}],{"prim":"GET","args":[{"int":"3"}]},{"prim":"CONTRACT","annots":["%transfer"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]}]}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},[{"prim":"DIP","args":[{"int":"6"},[{"prim":"DUP"}]]},{"prim":"DIG","args":[{"int":"7"}]}],{"prim":"CAR"},[{"prim":"DIP","args":[{"int":"7"},[{"prim":"DUP"}]]},{"prim":"DIG","args":[{"int":"8"}]}],{"prim":"CDR"},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"CONS"},{"prim":"TRANSFER_TOKENS"},[{"prim":"DIP","args":[{"int":"2"},[{"prim":"DUP"}]]},{"prim":"DIG","args":[{"int":"3"}]}],{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"4"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[[{"prim":"DIP","args":[[{"prim":"DUP"}]]},{"prim":"SWAP"}],{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},[{"prim":"DIP","args":[[{"prim":"DUP"}]]},{"prim":"SWAP"}],{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"4"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_collection_address"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"GET","args":[{"int":"3"}]}]]},{"prim":"view","args":[{"string":"has_locked_token"},{"prim":"nat"},{"prim":"bool"},[[[{"prim":"DUP"},{"prim":"CAR"},{"prim":"DIP","args":[[{"prim":"CDR"}]]}]],{"prim":"SWAP"},{"prim":"GET","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"MEM"}]]},{"prim":"view","args":[{"string":"get_owner"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"GET","args":[{"int":"3"}]}]]}]`, ), }; diff --git a/src/contractsTypes/tezosContractTypes/NFTStorage.types.ts b/src/contractsTypes/tezosContractTypes/NFTStorage.types.ts index 45b9ec98..15559c8c 100644 --- a/src/contractsTypes/tezosContractTypes/NFTStorage.types.ts +++ b/src/contractsTypes/tezosContractTypes/NFTStorage.types.ts @@ -7,16 +7,17 @@ import { address, nat } from './type-aliases'; export type Storage = { owner: address; collection: address; + locked: Array; }; type Methods = { unlock_token: (token_id: nat, to: address) => Promise; - deposit_token: (param: nat) => Promise; + add_deposited_token: (param: nat) => Promise; }; type MethodsObject = { unlock_token: (params: { token_id: nat; to: address }) => Promise; - deposit_token: (param: nat) => Promise; + add_deposited_token: (param: nat) => Promise; }; type contractTypes = { diff --git a/src/contractsTypes/tezosContractTypes/StorageFactory.code.ts b/src/contractsTypes/tezosContractTypes/StorageFactory.code.ts index b34ec4ce..662fde1f 100644 --- a/src/contractsTypes/tezosContractTypes/StorageFactory.code.ts +++ b/src/contractsTypes/tezosContractTypes/StorageFactory.code.ts @@ -6,6 +6,6 @@ export const StorageFactoryCode: { __type: 'StorageFactoryCode', protocol: 'PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA', code: JSON.parse( - `[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"address","annots":["%deploy_sft_storage"]},{"prim":"or","args":[{"prim":"address","annots":["%deploy_nft_storage"]},{"prim":"address","annots":["%set_owner"]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"option","annots":["%owner"],"args":[{"prim":"address"}]},{"prim":"map","annots":["%collection_to_store"],"args":[{"prim":"address"},{"prim":"address"}]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"option","args":[{"prim":"address"}]},{"prim":"map","args":[{"prim":"address"},{"prim":"address"}]}]},{"prim":"unit"},[{"prim":"DUP"},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Contract is not initialized"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SENDER"},{"prim":"SWAP"},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Only owner can call this function"}]},{"prim":"FAILWITH"}],[]]},{"prim":"UNIT"}]]},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PAIR"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NONE","args":[{"prim":"key_hash"}]},{"prim":"CREATE_CONTRACT","args":[[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"pair","annots":["%unlock_token"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%to"]},{"prim":"nat","annots":["%amt"]}]},{"prim":"pair","annots":["%deposit_token"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amt"]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%collection"]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"},{"prim":"nat"},{"prim":"address"},{"prim":"address"}]},{"prim":"operation"},[{"prim":"UNPAIR","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"CDR"},{"prim":"CONTRACT","annots":["%transfer"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]}]}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"CONS"},{"prim":"TRANSFER_TOKENS"}]]},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"SELF_ADDRESS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Cannot perform this function since you are not the owner."}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"PAIR","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}],[{"prim":"SELF_ADDRESS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SOURCE"},{"prim":"PAIR","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_collection_address"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CDR"}]]},{"prim":"view","args":[{"string":"get_owner"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CDR"}]]}]]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"CONS"}],[{"prim":"IF_LEFT","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PAIR"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NONE","args":[{"prim":"key_hash"}]},{"prim":"CREATE_CONTRACT","args":[[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"pair","annots":["%unlock_token"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%to"]}]},{"prim":"nat","annots":["%deposit_token"]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%collection"]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"},{"prim":"address"},{"prim":"address"}]},{"prim":"operation"},[{"prim":"UNPAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"CONTRACT","annots":["%transfer"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]}]}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"CONS"},{"prim":"TRANSFER_TOKENS"}]]},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"SELF_ADDRESS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Cannot perform this function since you are not the owner."}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}],[{"prim":"SELF_ADDRESS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUG","args":[{"int":"2"}]},{"prim":"SOURCE"},{"prim":"PAIR","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_collection_address"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CDR"}]]},{"prim":"view","args":[{"string":"get_owner"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CDR"}]]}]]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"CONS"}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}]]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Owner already set"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SOME"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_store"},{"prim":"address"},{"prim":"address"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"CDR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"MAP FIND"}]},{"prim":"FAILWITH"}],[]]}]]},{"prim":"view","args":[{"string":"get_owner"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]}]]}]`, + `[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"address","annots":["%deploy_sft_storage"]},{"prim":"or","args":[{"prim":"address","annots":["%deploy_nft_storage"]},{"prim":"address","annots":["%set_owner"]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"option","annots":["%owner"],"args":[{"prim":"address"}]},{"prim":"map","annots":["%collection_to_store"],"args":[{"prim":"address"},{"prim":"address"}]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"option","args":[{"prim":"address"}]},{"prim":"map","args":[{"prim":"address"},{"prim":"address"}]}]},{"prim":"unit"},[{"prim":"DUP"},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}]]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Contract is not initialized"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SENDER"},{"prim":"SWAP"},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Only owner can call this function"}]},{"prim":"FAILWITH"}],[]]},{"prim":"UNIT"}]]},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PAIR"},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NONE","args":[{"prim":"key_hash"}]},{"prim":"CREATE_CONTRACT","args":[[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"pair","annots":["%unlock_token"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%to"]},{"prim":"nat","annots":["%amt"]}]},{"prim":"pair","annots":["%deposit_token"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amt"]}]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%collection"]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"nat"},{"prim":"nat"},{"prim":"address"},{"prim":"address"}]},{"prim":"operation"},[{"prim":"UNPAIR","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"CDR"},{"prim":"CONTRACT","annots":["%transfer"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]}]}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"DIG","args":[{"int":"7"}]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"CONS"},{"prim":"TRANSFER_TOKENS"}]]},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"SELF_ADDRESS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Cannot perform this function since you are not the owner."}]},{"prim":"FAILWITH"}],[]]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"PAIR","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}],[{"prim":"SELF_ADDRESS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SOURCE"},{"prim":"PAIR","args":[{"int":"5"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"EXEC"}]]},{"prim":"SWAP"},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_collection_address"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CDR"}]]},{"prim":"view","args":[{"string":"get_owner"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CDR"}]]}]]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"CONS"}],[{"prim":"IF_LEFT","args":[[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"EMPTY_SET","args":[{"prim":"nat"}]},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DUP","args":[{"int":"4"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NONE","args":[{"prim":"key_hash"}]},{"prim":"CREATE_CONTRACT","args":[[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"pair","annots":["%unlock_token"],"args":[{"prim":"nat","annots":["%token_id"]},{"prim":"address","annots":["%to"]}]},{"prim":"nat","annots":["%add_deposited_token"]}]}]},{"prim":"storage","args":[{"prim":"pair","args":[{"prim":"address","annots":["%owner"]},{"prim":"address","annots":["%collection"]},{"prim":"set","annots":["%locked"],"args":[{"prim":"nat"}]}]}]},{"prim":"code","args":[[{"prim":"LAMBDA","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"address"},{"prim":"set","args":[{"prim":"nat"}]}]},{"prim":"unit"},[{"prim":"CAR"},{"prim":"SENDER"},{"prim":"COMPARE"},{"prim":"NEQ"},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Cannot perform this function since you are not the owner."}]},{"prim":"FAILWITH"}],[]]},{"prim":"UNIT"}]]},{"prim":"SWAP"},{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"SELF_ADDRESS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"3"}]},{"prim":"CONTRACT","annots":["%transfer"],"args":[{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address","annots":["%from_"]},{"prim":"list","annots":["%txs"],"args":[{"prim":"pair","args":[{"prim":"address","annots":["%to_"]},{"prim":"nat","annots":["%token_id"]},{"prim":"nat","annots":["%amount"]}]}]}]}]}]},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"bad address for get_entrypoint"}]},{"prim":"FAILWITH"}],[]]},{"prim":"PUSH","args":[{"prim":"mutez"},{"int":"0"}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"list","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]}]}]},{"prim":"NIL","args":[{"prim":"pair","args":[{"prim":"address"},{"prim":"nat"},{"prim":"nat"}]}]},{"prim":"PUSH","args":[{"prim":"nat"},{"int":"1"}]},{"prim":"DUP","args":[{"int":"7"}]},{"prim":"CAR"},{"prim":"DUP","args":[{"int":"8"}]},{"prim":"CDR"},{"prim":"PAIR","args":[{"int":"3"}]},{"prim":"CONS"},{"prim":"DIG","args":[{"int":"4"}]},{"prim":"PAIR"},{"prim":"CONS"},{"prim":"TRANSFER_TOKENS"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"CAR"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"4"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CONS"}],[{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"EXEC"},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"GET","args":[{"int":"4"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"UPDATE","args":[{"int":"4"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_collection_address"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"GET","args":[{"int":"3"}]}]]},{"prim":"view","args":[{"string":"has_locked_token"},{"prim":"nat"},{"prim":"bool"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"GET","args":[{"int":"4"}]},{"prim":"SWAP"},{"prim":"MEM"}]]},{"prim":"view","args":[{"string":"get_owner"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"GET","args":[{"int":"3"}]}]]}]]},{"prim":"PAIR"},{"prim":"DUP","args":[{"int":"3"}]},{"prim":"CDR"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CDR"},{"prim":"DIG","args":[{"int":"3"}]},{"prim":"SWAP"},{"prim":"SOME"},{"prim":"SWAP"},{"prim":"UPDATE"},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"SWAP"},{"prim":"UPDATE","args":[{"int":"2"}]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"DIG","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"CONS"}],[{"prim":"DIG","args":[{"int":"2"}]},{"prim":"DROP"},{"prim":"DUP","args":[{"int":"2"}]},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"False"}]}],[{"prim":"DROP"},{"prim":"PUSH","args":[{"prim":"bool"},{"prim":"True"}]}]]},{"prim":"IF","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"Owner already set"}]},{"prim":"FAILWITH"}],[]]},{"prim":"SOME"},{"prim":"UPDATE","args":[{"int":"1"}]},{"prim":"NIL","args":[{"prim":"operation"}]}]]}]]},{"prim":"PAIR"}]]},{"prim":"view","args":[{"string":"get_store"},{"prim":"address"},{"prim":"address"},[{"prim":"UNPAIR"},{"prim":"SWAP"},{"prim":"CDR"},{"prim":"SWAP"},{"prim":"GET"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"MAP FIND"}]},{"prim":"FAILWITH"}],[]]}]]},{"prim":"view","args":[{"string":"get_owner"},{"prim":"unit"},{"prim":"address"},[{"prim":"CDR"},{"prim":"CAR"},{"prim":"IF_NONE","args":[[{"prim":"PUSH","args":[{"prim":"string"},{"string":"option is None"}]},{"prim":"FAILWITH"}],[]]}]]}]`, ), }; diff --git a/src/contractsTypes/tezosContractTypes/type-aliases.ts b/src/contractsTypes/tezosContractTypes/type-aliases.ts index 6b5fb248..be44ea8d 100644 --- a/src/contractsTypes/tezosContractTypes/type-aliases.ts +++ b/src/contractsTypes/tezosContractTypes/type-aliases.ts @@ -27,8 +27,7 @@ export type nat = BigNumber & { __type: 'nat' }; export type mutez = BigNumber & { __type: 'mutez' }; export type tez = BigNumber & { __type: 'tez' }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type MapKey = Array | object | string | boolean | number; +type MapKey = Array | object | string | boolean | number; export type MMap = Omit, 'get'> & { get: (key: K) => V; }; @@ -83,12 +82,12 @@ function createLambdaTypeTas(expr: Expr): MichelsonCode { /** tas: Tezos 'as' casting for strict types */ export const tas = { - key: createStringTypeTas(), address: createStringTypeTas
(), - signature: createStringTypeTas(), bytes: createStringTypeTas(), contract: createStringTypeTas(), chest: createStringTypeTas(), + signature: createStringTypeTas(), + key: createStringTypeTas(), chest_key: createStringTypeTas(), timestamp: (value: string | Date): timestamp => new Date(value).toISOString() as timestamp, diff --git a/src/contractsTypes/tezosContractTypes/type-utils.ts b/src/contractsTypes/tezosContractTypes/type-utils.ts index 11eacaba..ede0686b 100644 --- a/src/contractsTypes/tezosContractTypes/type-utils.ts +++ b/src/contractsTypes/tezosContractTypes/type-utils.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/ban-types */ + import { ContractAbstraction, ContractMethod, diff --git a/src/utils/functions/getTezosBridgeContract.ts b/src/utils/functions/getTezosBridgeContract.ts index fed304a1..0a8b03c7 100644 --- a/src/utils/functions/getTezosBridgeContract.ts +++ b/src/utils/functions/getTezosBridgeContract.ts @@ -1,10 +1,13 @@ import { IBridge, ITezosChainConfigAndTezosWallet } from '@src/types'; import { TezosToolkit } from '@taquito/taquito'; import { InMemorySigner } from '@taquito/signer'; +import { validateAddress } from '@taquito/utils'; import { BridgeContractType } from '@src/contractsTypes/tezosContractTypes/Bridge.types'; import { address, key, + mutez, + nat, signature, tas, } from '@src/contractsTypes/tezosContractTypes/type-aliases'; @@ -14,18 +17,34 @@ import { SupportedChains } from '@src/config/chainSpecs'; export type TezosLockArgs = [ sourceNftContractAddress: string, - destinationChain: SupportedChains, address: string, tokenId: string, ]; +export type TezosClaimArgs = { + token_id: nat; + source_chain: string; + dest_chain: string; + dest_address: address; + source_nft_contract_address: string; + name: string; + symbol: string; + royalty: nat; + royalty_receiver: address; + metadata: string; + transaction_hash: string; + token_amount: nat; + nft_type: string; + fee: mutez; +}; + const getTezosBridgeContract = ({ tezosChainConfig, tezosWallet, }: ITezosChainConfigAndTezosWallet): IBridge< TezosLockArgs, - Record, + TezosClaimArgs, { signer: key; sig: signature; @@ -45,11 +64,63 @@ const getTezosBridgeContract = ({ }; return { - lock721: async () => { - throw new Error('Not implemented'); + lock721: async ( + sourceNftContractAddress, + destinationChain, + destAddress, + tokenId, + ) => { + const bridge = await getBridgeInstance(); + const tx = await bridge.methods + .lock_nft(tas.nat(tokenId), destinationChain, destAddress, { + addr: tas.address(sourceNftContractAddress), + }) + .send(); + + return { + hash: tx.hash, + wait: async () => { + await tx.confirmation(1); + }, + }; }, - claimNFT721: async () => { - throw new Error('Not implemented'); + claimNFT721: async (data, sigs) => { + const isTezosAddr = + validateAddress(data.source_nft_contract_address) === 3; + + const sourceNftContractAddress = isTezosAddr + ? { + addr: tas.address(data.source_nft_contract_address), + } + : { + str: data.source_nft_contract_address, + }; + const bridge = await getBridgeInstance(); + const tx = await bridge.methods + .claim_nft( + data.token_id, + data.source_chain, + data.dest_chain, + data.dest_address, + sourceNftContractAddress, + data.name, + data.symbol, + data.royalty, + data.royalty_receiver, + data.metadata, + data.transaction_hash, + data.token_amount, + data.nft_type, + data.fee, + sigs, + ) + .send(); + return { + hash: tx.hash, + wait: async () => { + await tx.confirmation(1); + }, + }; }, validators: async (address: string) => { const bridge = await getBridgeInstance(); From c19b8da9d4eb024ba350a63178a515b41149806f Mon Sep 17 00:00:00 2001 From: imsk17 Date: Thu, 18 Jan 2024 18:55:39 +0530 Subject: [PATCH 05/19] Packages: Remove bignumber.js as a dependency --- package.json | 1 - src/contractsTypes/contracts/secretBridge.ts | 14 ++++++-------- src/utils/functions/getMultiversXBridgeContract.ts | 3 +-- src/utils/functions/getSecretBridgeContract.ts | 7 +++---- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 00d02f5d..6699b353 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,6 @@ "@types/mocha": "^10.0.3", "@types/web3": "^1.2.2", "axios": "^1.6.0", - "bignumber.js": "^9.1.2", "bip39": "^3.1.0", "borsh": "^1.0.0", "bullmq": "^4.12.5", diff --git a/src/contractsTypes/contracts/secretBridge.ts b/src/contractsTypes/contracts/secretBridge.ts index 88bea09c..01ccfdae 100644 --- a/src/contractsTypes/contracts/secretBridge.ts +++ b/src/contractsTypes/contracts/secretBridge.ts @@ -1,5 +1,3 @@ -import BigNumber from 'bignumber.js'; - export type CodeInfo = { code_id: number; code_hash: string; @@ -48,7 +46,7 @@ export type Lock721 = { destination_user_address: string; source_nft_contract_address: string; collection_code_info: CodeInfo; - token_id: BigNumber; + token_id: string; }; }; }; @@ -60,14 +58,14 @@ export type Lock1155 = { destination_user_address: string; source_nft_contract_address: string; collection_code_info: CodeInfo; - token_id: BigNumber; - token_amount: BigNumber; + token_id: string; + token_amount: string; }; }; }; export type ClaimData = { - token_id: BigNumber; + token_id: string; source_chain: string; destination_chain: string; destination_user_address: string; @@ -79,9 +77,9 @@ export type ClaimData = { royalty_receiver: string; metadata: string; transaction_hash: string; - token_amount: BigNumber; + token_amount: string; nft_type: string; - fee: BigNumber; + fee: string; }; export type ClaimMsg = { diff --git a/src/utils/functions/getMultiversXBridgeContract.ts b/src/utils/functions/getMultiversXBridgeContract.ts index 74d7f9ca..2586dbd1 100644 --- a/src/utils/functions/getMultiversXBridgeContract.ts +++ b/src/utils/functions/getMultiversXBridgeContract.ts @@ -26,7 +26,6 @@ import { ProcessDelayMilliseconds } from '../constants/processDelayMilliseconds' import waitForMSWithMsg from './waitForMSWithMsg'; import { SupportedChains } from '@src/config/chainSpecs'; import { Nonce } from '@multiversx/sdk-network-providers/out/primitives'; -import BigNumber from 'bignumber.js'; export type MultiversXLockArgs = [ sourceNftContractAddress: string, @@ -360,7 +359,7 @@ const getMultiversXBridgeContract = ({ .withSender(signer.getAddress()) .withChainID('D') .withGasLimit(6_000_000_00) - .withValue(new BigUIntValue(new BigNumber('50000000000000000'))) + .withValue(new BigUIntValue('50000000000000000')) .buildTransaction(); transaction.setNonce(userAccount.getNonceThenIncrement()); transaction.applySignature( diff --git a/src/utils/functions/getSecretBridgeContract.ts b/src/utils/functions/getSecretBridgeContract.ts index 55cc3c82..f3ea27ec 100644 --- a/src/utils/functions/getSecretBridgeContract.ts +++ b/src/utils/functions/getSecretBridgeContract.ts @@ -1,6 +1,5 @@ import { AddValidatorType } from '@src/contractsTypes/contracts/secretBridge'; import { IBridge, ISecretChainConfigAndSecretWallet } from '@src/types'; -import BigNumber from 'bignumber.js'; import { SecretNetworkClient, pubkeyToAddress } from 'secretjs'; import { encodeSecp256k1Pubkey } from 'secretjs/dist/wallet_amino'; @@ -29,9 +28,9 @@ export type ClaimData = { royalty_receiver: string; metadata: string; transaction_hash: string; - token_amount: BigNumber; + token_amount: string; nft_type: string; - fee: BigNumber; + fee: string; }; const getSecretBridgeContract = ({ @@ -124,7 +123,7 @@ const getSecretBridgeContract = ({ source_nft_contract_address: sourceNftContractAddress, collection_code_info: collectionCodeInfo, token_id: tokenId, - token_amount: new BigNumber(amt.toString()), + token_amount: amt.toString(), }, code_hash: bridgeContractCodeHash, sender: secretjs.address, From e48e0ceaf38a5b230ec70639d127c7d2c9eaeed6 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Mon, 22 Jan 2024 16:03:27 +0530 Subject: [PATCH 06/19] Tests: Add an example for End-to-End Testing --- src/config/chainSpecs.ts | 2 +- src/test/evm-to-evm.ts | 149 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 src/test/evm-to-evm.ts diff --git a/src/config/chainSpecs.ts b/src/config/chainSpecs.ts index 9f3dfea2..9537d154 100644 --- a/src/config/chainSpecs.ts +++ b/src/config/chainSpecs.ts @@ -18,7 +18,7 @@ const storageTestnetConfig: IEvmChainConfig = { lastBlock: 17608314, }; -const bridgeTestChains = [ +export const bridgeTestChains = [ { chain: 'BSC', rpcURL: 'https://bsc-testnet.publicnode.com', diff --git a/src/test/evm-to-evm.ts b/src/test/evm-to-evm.ts new file mode 100644 index 00000000..89a3ae0f --- /dev/null +++ b/src/test/evm-to-evm.ts @@ -0,0 +1,149 @@ +import { JsonRpcProvider, Wallet } from 'ethers'; +import { generateWalletsForChains } from '../modules/setup/components'; +import { Wallet as SecretWallet } from 'secretjs'; +import { InMemorySigner } from '@taquito/signer'; +import { UserSigner } from '@multiversx/sdk-wallet/out'; +import { keyPairFromSecretKey } from 'ton-crypto'; +import { bridgeTestChains, testnetBridgeConfig } from '../config/chainSpecs'; +import { ERC721Royalty__factory } from '../contractsTypes'; +import { + getEvmBridgeContract, + getEvmSingleNftContract, + getStorageContract, +} from '../utils'; +import { IEvmChainConfig } from '../types'; + +(async () => { + const genWallets = await generateWalletsForChains(); + // Assuming we have enough funds on the validator accounts itself. + const signers = { + bsc: new Wallet(genWallets.evmWallet.privateKey), + eth: new Wallet(genWallets.evmWallet.privateKey), + tezos: new InMemorySigner(genWallets.tezosWallet.secretKey), + multiversx: UserSigner.fromWallet( + genWallets.multiversXWallet.userWallet, + genWallets.multiversXWallet.password, + ), + secret: new SecretWallet(genWallets.secretWallet.privateKey), + ton: keyPairFromSecretKey( + Buffer.from(genWallets.tonWallet.secretKey, 'hex'), + ), + }; + const configs = { + bsc: bridgeTestChains.find( + (e) => e.chain === 'BSC', + )! as IEvmChainConfig, + eth: bridgeTestChains.find( + (e) => e.chain === 'ETH', + )! as IEvmChainConfig, + }; + + const data = { + storage: getStorageContract({ + evmChainConfig: testnetBridgeConfig.storageConfig, + evmWallet: genWallets.evmWallet, + }), + bsc: { + signer: new Wallet(genWallets.evmWallet.privateKey), + bridge: getEvmBridgeContract({ + evmChainConfig: configs.bsc, + evmWallet: genWallets.evmWallet, + }), + config: configs.bsc, + }, + eth: { + signer: new Wallet(genWallets.evmWallet.privateKey), + bridge: getEvmBridgeContract({ + evmChainConfig: configs.eth, + evmWallet: genWallets.evmWallet, + }), + config: configs.eth, + }, + }; + + // Create a NFT Contract + + const contract = await createNftOnEvm( + data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), + ); + + // Mint 5 NFT on the contract + for (let i = 0; i < 5; i++) { + await contract.mint( + signers.bsc.address, + i, + 10, + signers.bsc.address, + 'https://meta.polkamon.com/meta?id=10001852306', + ); + } + console.log('Minted 5 NFTs ON BSC'); + + // Approve the contract to spend the NFTs + const nftC = getEvmSingleNftContract( + { + contractAddress: await contract.getAddress(), + rpcURL: configs.bsc.rpcURL, + }, + data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), + ); + for (let i = 0; i < 5; i++) { + await nftC.approve(BigInt(i), data.bsc.config.contractAddress); + } + + // Lock the NFTs + const lockTx = await data.bsc.bridge.lock721( + await contract.getAddress(), + '0', + 'ETH', + signers.eth.address, + ); + + // Wait for the NFTs to be locked + await new Promise((resolve) => setTimeout(resolve, 10000)); + + // Fetch the signatures + const signatures = await data.storage.getLockNftSignatures( + lockTx.hash, + 'BSC', + ); + + const signatureArray: string[] = []; + signatures.forEach((item) => { + signatureArray.push(item[1]); + }); + + const claimData = { + tokenId: '0', + sourceChain: 'BSC', + destinationChain: 'ETH', + destinationUserAddress: signers.eth.address, + sourceNftContractAddress: await contract.getAddress(), + name: 'TestContract', + symbol: 'TC', + royalty: '10', + royaltyReceiver: signers.bsc.address, + metadata: 'https://meta.polkamon.com/meta?id=10001852306', + transactionHash: lockTx.hash, + tokenAmount: '1', + nftType: 'singular', + fee: '100000000000000', + }; + + // Unlock it on the destination chain + const claimed = await data.eth.bridge.claimNFT721( + claimData, + signatureArray, + ); + + console.log(claimed); +})(); + +async function createNftOnEvm(signer: Wallet) { + const contract = await new ERC721Royalty__factory(signer).deploy( + 'TestContract', + 'TC', + signer.address, + ); + return contract; +} From e0359bf73f34ff2ec4249b6d6b27891112cf2340 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Wed, 24 Jan 2024 13:39:11 +0530 Subject: [PATCH 07/19] Tests: Add a generic test --- .../components/handleValidatorAddition.ts | 2 +- src/types/index.ts | 7 ++- src/utils/functions/getEvmBridgeContract.ts | 54 ++++++++++++++++--- .../functions/getHederaBridgeContract.ts | 54 ++++++++++++++++--- .../functions/getMultiversXBridgeContract.ts | 28 ++++++---- .../functions/getSecretBridgeContract.ts | 38 ++++++------- src/utils/functions/getTezosBridgeContract.ts | 20 +++---- src/utils/functions/getTonBridgeContract.ts | 20 +++---- 8 files changed, 154 insertions(+), 69 deletions(-) diff --git a/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts b/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts index 77363015..f93e46e2 100644 --- a/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts +++ b/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts @@ -36,7 +36,7 @@ const handleValidatorAddition = async ({ let failiure = true; // eslint-disable-next-line @typescript-eslint/no-explicit-any - let bridgeContract: IBridge; + let bridgeContract: IBridge; let publicWalletAddress: string; let isChainFunded: () => Promise; diff --git a/src/types/index.ts b/src/types/index.ts index 2f95c62d..6b65edaf 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -209,7 +209,7 @@ type IBridgeConfig = { stakingConfig: IStakingConfig; }; -type IBridge = { +type IBridge = { validators: (address: string) => Promise<{ added: boolean }>; validatorsCount: () => Promise; addValidator: ( @@ -220,11 +220,10 @@ type IBridge = { }[], ) => Promise<{ hash: string; wait: () => Promise }>; lock721: ( - ...lockArgs: TLockArgs + lockArgs: TLockArgs, ) => Promise<{ hash: string; wait: () => Promise }>; lock1155?: ( - amt: bigint, - ...lockArgs: TLockArgs + lockArgs: TLockArgs & { amt: bigint }, ) => Promise<{ hash: string; wait: () => Promise }>; claimNFT721: ( nftTransferData: TClaimData, diff --git a/src/utils/functions/getEvmBridgeContract.ts b/src/utils/functions/getEvmBridgeContract.ts index 78d48064..724ee560 100644 --- a/src/utils/functions/getEvmBridgeContract.ts +++ b/src/utils/functions/getEvmBridgeContract.ts @@ -3,12 +3,12 @@ import { Bridge, Bridge__factory } from '../../contractsTypes'; import { IBridge, IEvmChainConfigAndEvmWallet } from '@src/types'; import { SupportedChains } from '@src/config/chainSpecs'; -export type EvmLockArgs = [ - sourceNftContractAddress: string, - tokenId: string, - destinationChain: SupportedChains, - address: string, -]; +export type EvmLockArgs = { + sourceNftContractAddress: string; + tokenId: string; + destinationChain: SupportedChains; + address: string; +}; const getEvmBridgeContract = ({ evmChainConfig, @@ -20,7 +20,47 @@ const getEvmBridgeContract = ({ > => { const provider = new ethers.JsonRpcProvider(evmChainConfig.rpcURL); const wallet = new ethers.Wallet(evmWallet.privateKey, provider); - return Bridge__factory.connect(evmChainConfig.contractAddress, wallet); + const contract = Bridge__factory.connect( + evmChainConfig.contractAddress, + wallet, + ); + return { + addValidator: contract.addValidator, + + validators: contract.validators, + validatorsCount: contract.validatorsCount, + lock1155({ + address, + amt, + destinationChain, + sourceNftContractAddress, + tokenId, + }) { + return contract.lock1155( + tokenId, + destinationChain, + address, + sourceNftContractAddress, + amt, + ); + }, + claimNFT1155: contract.claimNFT1155, + + claimNFT721: contract.claimNFT721, + lock721({ + address, + destinationChain, + sourceNftContractAddress, + tokenId, + }) { + return contract.lock721( + tokenId, + destinationChain, + address, + sourceNftContractAddress, + ); + }, + }; }; export default getEvmBridgeContract; diff --git a/src/utils/functions/getHederaBridgeContract.ts b/src/utils/functions/getHederaBridgeContract.ts index fa07388e..df9928ab 100644 --- a/src/utils/functions/getHederaBridgeContract.ts +++ b/src/utils/functions/getHederaBridgeContract.ts @@ -3,12 +3,12 @@ import { Bridge, Bridge__factory } from '../../contractsTypes'; import { IBridge, IHederaChainConfigAndEvmWallet } from '@src/types'; import { SupportedChains } from '@src/config/chainSpecs'; -export type HederaLockArgs = [ - sourceNftContractAddress: string, - tokenId: string, - destinationChain: SupportedChains, - address: string, -]; +export type HederaLockArgs = { + sourceNftContractAddress: string; + tokenId: string; + destinationChain: SupportedChains; + address: string; +}; const getHederaBridgeContract = ({ hederaChainConfig, @@ -20,7 +20,47 @@ const getHederaBridgeContract = ({ > => { const provider = new ethers.JsonRpcProvider(hederaChainConfig.rpcURL); const wallet = new ethers.Wallet(evmWallet.privateKey, provider); - return Bridge__factory.connect(hederaChainConfig.contractAddress, wallet); + const contract = Bridge__factory.connect( + hederaChainConfig.contractAddress, + wallet, + ); + return { + addValidator: contract.addValidator, + + validators: contract.validators, + validatorsCount: contract.validatorsCount, + lock1155({ + address, + amt, + destinationChain, + sourceNftContractAddress, + tokenId, + }) { + return contract.lock1155( + tokenId, + destinationChain, + address, + sourceNftContractAddress, + amt, + ); + }, + claimNFT1155: contract.claimNFT1155, + + claimNFT721: contract.claimNFT721, + lock721({ + address, + destinationChain, + sourceNftContractAddress, + tokenId, + }) { + return contract.lock721( + tokenId, + destinationChain, + address, + sourceNftContractAddress, + ); + }, + }; }; export default getHederaBridgeContract; diff --git a/src/utils/functions/getMultiversXBridgeContract.ts b/src/utils/functions/getMultiversXBridgeContract.ts index 2586dbd1..612b3bb2 100644 --- a/src/utils/functions/getMultiversXBridgeContract.ts +++ b/src/utils/functions/getMultiversXBridgeContract.ts @@ -27,13 +27,13 @@ import waitForMSWithMsg from './waitForMSWithMsg'; import { SupportedChains } from '@src/config/chainSpecs'; import { Nonce } from '@multiversx/sdk-network-providers/out/primitives'; -export type MultiversXLockArgs = [ - sourceNftContractAddress: string, - nonce: string, - destinationChain: SupportedChains, - address: string, - tokenId: string, -]; +export type MultiversXLockArgs = { + sourceNftContractAddress: string; + nonce: string; + destinationChain: SupportedChains; + address: string; + tokenId: string; +}; export type ClaimStruct = { tokenId: string; sourceChain: string; @@ -78,7 +78,13 @@ const getMultiversXBridgeContract = ({ }); return { - lock721: async (srcNftAddr, nonce, destChain, destAddress, tokenId) => { + lock721: async ({ + address, + destinationChain, + nonce, + sourceNftContractAddress, + tokenId, + }) => { const ba = new Address(multiversXChainConfig.contractAddress); try { const signer = UserSigner.fromWallet( @@ -95,16 +101,16 @@ const getMultiversXBridgeContract = ({ userAccount.update(userOnNetwork); const collectionIdentifiers = - '@' + Buffer.from(srcNftAddr).toString('hex'); + '@' + Buffer.from(sourceNftContractAddress).toString('hex'); const noncec = '@' + nonce; const quantity = '@' + '01'; const destination_address = '@' + ba.hex(); const method = '@' + Buffer.from('lock721').toString('hex'); const token_id = '@' + Buffer.from(tokenId).toString('hex'); const destination_chain = - '@' + Buffer.from(destChain).toString('hex'); + '@' + Buffer.from(destinationChain).toString('hex'); const destination_user_address = - '@' + Buffer.from(destAddress).toString('hex'); + '@' + Buffer.from(address).toString('hex'); const source_nft_contract_address = collectionIdentifiers; const tx3 = new Transaction({ diff --git a/src/utils/functions/getSecretBridgeContract.ts b/src/utils/functions/getSecretBridgeContract.ts index f3ea27ec..26fd5565 100644 --- a/src/utils/functions/getSecretBridgeContract.ts +++ b/src/utils/functions/getSecretBridgeContract.ts @@ -1,3 +1,4 @@ +import { SupportedChains } from '@src/config/chainSpecs'; import { AddValidatorType } from '@src/contractsTypes/contracts/secretBridge'; import { IBridge, ISecretChainConfigAndSecretWallet } from '@src/types'; import { SecretNetworkClient, pubkeyToAddress } from 'secretjs'; @@ -8,13 +9,13 @@ export type CodeInfo = { code_hash: string; }; -export type SecretLockType = [ - destinationChain: string, - destinationUserAddress: string, - sourceNftContractAddress: string, - collectionCodeInfo: CodeInfo, - tokenId: string, -]; +export type SecretLockArgs = { + destinationChain: SupportedChains; + address: string; + sourceNftContractAddress: string; + collectionCodeInfo: CodeInfo; + tokenId: string; +}; export type ClaimData = { token_id: string; @@ -37,7 +38,7 @@ const getSecretBridgeContract = ({ secretChainConfig, secretWallet, }: ISecretChainConfigAndSecretWallet): IBridge< - SecretLockType, + SecretLockArgs, ClaimData, { signer: string; signature: string } > => { @@ -49,13 +50,13 @@ const getSecretBridgeContract = ({ }); return { - lock721: async ( + lock721: async ({ + collectionCodeInfo, destinationChain, - destinationUserAddress, + address, sourceNftContractAddress, - collectionCodeInfo, tokenId, - ) => { + }) => { const tx = await secretjs.tx.compute.executeContract( { contract_address: secretChainConfig.contractAddress, @@ -63,8 +64,7 @@ const getSecretBridgeContract = ({ lock721: { data: { destination_chain: destinationChain, - destination_user_address: - destinationUserAddress, + destination_user_address: address, source_nft_contract_address: sourceNftContractAddress, collection_code_info: collectionCodeInfo, @@ -106,20 +106,20 @@ const getSecretBridgeContract = ({ ); return { hash: tx.transactionHash, wait: async () => {} }; }, - async lock1155( + async lock1155({ amt, + collectionCodeInfo, destinationChain, - destinationUserAddress, + address, sourceNftContractAddress, - collectionCodeInfo, tokenId, - ) { + }) { const tx = await secretjs.tx.compute.executeContract( { contract_address: secretChainConfig.contractAddress, msg: { destination_chain: destinationChain, - destination_user_address: destinationUserAddress, + destination_user_address: address, source_nft_contract_address: sourceNftContractAddress, collection_code_info: collectionCodeInfo, token_id: tokenId, diff --git a/src/utils/functions/getTezosBridgeContract.ts b/src/utils/functions/getTezosBridgeContract.ts index 0a8b03c7..ac68bf39 100644 --- a/src/utils/functions/getTezosBridgeContract.ts +++ b/src/utils/functions/getTezosBridgeContract.ts @@ -15,12 +15,12 @@ import { b58cencode, prefix, b58cdecode } from '@taquito/utils'; import { hash } from '@stablelib/blake2b'; import { SupportedChains } from '@src/config/chainSpecs'; -export type TezosLockArgs = [ - sourceNftContractAddress: string, - destinationChain: SupportedChains, - address: string, - tokenId: string, -]; +export type TezosLockArgs = { + sourceNftContractAddress: string; + destinationChain: SupportedChains; + address: string; + tokenId: string; +}; export type TezosClaimArgs = { token_id: nat; @@ -64,15 +64,15 @@ const getTezosBridgeContract = ({ }; return { - lock721: async ( + lock721: async ({ sourceNftContractAddress, destinationChain, - destAddress, + address, tokenId, - ) => { + }) => { const bridge = await getBridgeInstance(); const tx = await bridge.methods - .lock_nft(tas.nat(tokenId), destinationChain, destAddress, { + .lock_nft(tas.nat(tokenId), destinationChain, address, { addr: tas.address(sourceNftContractAddress), }) .send(); diff --git a/src/utils/functions/getTonBridgeContract.ts b/src/utils/functions/getTonBridgeContract.ts index fdecbd49..9d263117 100644 --- a/src/utils/functions/getTonBridgeContract.ts +++ b/src/utils/functions/getTonBridgeContract.ts @@ -11,12 +11,12 @@ import { ProcessDelayMilliseconds } from '../constants/processDelayMilliseconds' import waitForMSWithMsg from './waitForMSWithMsg'; import TonWeb from 'tonweb'; -export type TonLockArgs = [ - destinationChain: string, - destinationUserAddress: string, - sourceNftContractAddress: string, - tokenId: bigint, -]; +export type TonLockArgs = { + destinationChain: string; + address: string; + sourceNftContractAddress: string; + tokenId: bigint; +}; const getTonBridgeContract = ({ tonChainConfig, @@ -52,12 +52,12 @@ const getTonBridgeContract = ({ const tonweb = new TonWeb(provider); return { - lock721: async ( + lock721: async ({ destinationChain, - destinationUserAddress, + address, sourceNftContractAddress, tokenId, - ) => { + }) => { await bridge.send( walletSender, { @@ -66,7 +66,7 @@ const getTonBridgeContract = ({ { $$type: 'Lock721', destinationChain, - destinationUserAddress, + destinationUserAddress: address, sourceNftContractAddress: Address.parseFriendly( sourceNftContractAddress, ).address, From 4d58cae8c1d3a74a715257f43c2cb7c6c8c2c2b9 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Wed, 24 Jan 2024 16:58:38 +0530 Subject: [PATCH 08/19] Tests: Add a generic test II --- src/test/generic-test.ts | 228 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 src/test/generic-test.ts diff --git a/src/test/generic-test.ts b/src/test/generic-test.ts new file mode 100644 index 00000000..3a1e28a0 --- /dev/null +++ b/src/test/generic-test.ts @@ -0,0 +1,228 @@ +import { JsonRpcProvider, Wallet } from 'ethers'; +import { generateWalletsForChains } from '../modules/setup/components'; +import { Wallet as SecretWallet } from 'secretjs'; +import { InMemorySigner } from '@taquito/signer'; +import { UserSigner } from '@multiversx/sdk-wallet/out'; +import { keyPairFromSecretKey } from 'ton-crypto'; +import { bridgeTestChains, testnetBridgeConfig } from '../config/chainSpecs'; +import { BridgeStorage, ERC721Royalty__factory } from '../contractsTypes'; +import { + getEvmBridgeContract, + getEvmSingleNftContract, + getStorageContract, +} from '../utils'; +import { IBridge, IEvmChainConfig, TChain } from '../types'; +import { getNftDetails } from '../modules/validator/components/nftLockListener/utils'; +import { HederaLockArgs } from '../utils/functions/getHederaBridgeContract'; +import { TezosLockArgs } from '../utils/functions/getTezosBridgeContract'; +import { MultiversXLockArgs } from '../utils/functions/getMultiversXBridgeContract'; + +import { TonLockArgs } from '../utils/functions/getTonBridgeContract'; +import { SecretLockArgs } from '../utils/functions/getSecretBridgeContract'; +import { EvmLockArgs } from '../utils/functions/getEvmBridgeContract'; + +(async () => { + const genWallets = await generateWalletsForChains(); + // Assuming we have enough funds on the validator accounts itself. + const signers = { + bsc: new Wallet(genWallets.evmWallet.privateKey), + eth: new Wallet(genWallets.evmWallet.privateKey), + tezos: new InMemorySigner(genWallets.tezosWallet.secretKey), + multiversx: UserSigner.fromWallet( + genWallets.multiversXWallet.userWallet, + genWallets.multiversXWallet.password, + ), + secret: new SecretWallet(genWallets.secretWallet.privateKey), + ton: keyPairFromSecretKey( + Buffer.from(genWallets.tonWallet.secretKey, 'hex'), + ), + }; + const configs = { + bsc: bridgeTestChains.find( + (e) => e.chain === 'BSC', + )! as IEvmChainConfig, + eth: bridgeTestChains.find( + (e) => e.chain === 'ETH', + )! as IEvmChainConfig, + }; + + const data = { + storage: getStorageContract({ + evmChainConfig: testnetBridgeConfig.storageConfig, + evmWallet: genWallets.evmWallet, + }), + bsc: { + signer: new Wallet(genWallets.evmWallet.privateKey), + bridge: getEvmBridgeContract({ + evmChainConfig: configs.bsc, + evmWallet: genWallets.evmWallet, + }), + config: configs.bsc, + }, + eth: { + signer: new Wallet(genWallets.evmWallet.privateKey), + bridge: getEvmBridgeContract({ + evmChainConfig: configs.eth, + evmWallet: genWallets.evmWallet, + }), + config: configs.eth, + }, + }; + + // Create a NFT Contract + + const contract = await createNftOnEvm( + data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), + ); + + // Mint 5 NFT on the contract + for (let i = 0; i < 5; i++) { + await contract.mint( + signers.bsc.address, + i, + 10, + signers.bsc.address, + 'https://meta.polkamon.com/meta?id=10001852306', + ); + } + console.log('Minted 5 NFTs ON BSC'); + + // Approve the contract to spend the NFTs + const nftC = getEvmSingleNftContract( + { + contractAddress: await contract.getAddress(), + rpcURL: configs.bsc.rpcURL, + }, + data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), + ); + for (let i = 0; i < 5; i++) { + await nftC.approve(BigInt(i), data.bsc.config.contractAddress); + } + + // Lock the NFTs + + const lockTx = await data.bsc.bridge.lock721( + await contract.getAddress(), + '0', + 'ETH', + signers.eth.address, + ); + + // Wait for the NFTs to be locked + await new Promise((resolve) => setTimeout(resolve, 10000)); + + // Fetch the signatures + const signatures = await data.storage.getLockNftSignatures( + lockTx.hash, + 'BSC', + ); + + const signatureArray: string[] = []; + signatures.forEach((item) => { + signatureArray.push(item[1]); + }); + + const claimData = { + tokenId: '0', + sourceChain: 'BSC', + destinationChain: 'ETH', + destinationUserAddress: signers.eth.address, + sourceNftContractAddress: await contract.getAddress(), + name: 'TestContract', + symbol: 'TC', + royalty: '10', + royaltyReceiver: signers.bsc.address, + metadata: 'https://meta.polkamon.com/meta?id=10001852306', + transactionHash: lockTx.hash, + tokenAmount: '1', + nftType: 'singular', + fee: '100000000000000', + }; + + // Unlock it on the destination chain + const claimed = await data.eth.bridge.claimNFT721( + claimData, + signatureArray, + ); + + console.log(claimed); + const tokenId = 0; + const collectionAddress = ''; + pipe([tokenId, collectionAddress], []); +})(); + +async function createNftOnEvm(signer: Wallet) { + const contract = await new ERC721Royalty__factory(signer).deploy( + 'TestContract', + 'TC', + signer.address, + ); + return contract; +} + +type LockArgs = EvmLockArgs & + HederaLockArgs & + TezosLockArgs & + MultiversXLockArgs & + SecretLockArgs & + TonLockArgs; + +export async function pipe( + chainStart: T, + promises: Array<(arg0: T) => Promise>, +) { + if (promises.length > 0) { + return promises.pop()!(chainStart).then((s) => pipe(s, promises)); + } +} + +export async function transferNft( + sourceChain: IBridge, + sourceChainConfig: TChain, + lockArgs: LockArgs, + storage: BridgeStorage, + destinationChain: IBridge, +): Promise<[bigint, string]> { + // as any + const lockTx = await sourceChain.lock721(lockArgs); + + // Wait for the NFTs to be locked + await new Promise((resolve) => setTimeout(resolve, 10000)); + + // Fetch the signatures + const signatures = await storage.getLockNftSignatures( + lockTx.hash, + sourceChainConfig.chain, + ); + const fee = await storage.chainFee(lockArgs.destinationChain); + + const nftContract = await getNftDetails({ + nftType: 'singular', + sourceChain: sourceChainConfig, + sourceNftContractAddress: lockArgs.sourceNftContractAddress, + tokenId: lockArgs.tokenId, + }); + + const signatureArray: string[] = []; + signatures.forEach((item) => { + signatureArray.push(item[1]); + }); + const claimData = { + tokenId: '0', + sourceChain: sourceChainConfig.chain, + destinationChain: lockArgs.destinationChain, + destinationUserAddress: lockArgs.address, + sourceNftContractAddress: lockArgs.sourceNftContractAddress, + name: nftContract.name, + symbol: nftContract.symbol, + royalty: nftContract.royalty, + royaltyReceiver: '', + metadata: nftContract.metadata, + transactionHash: lockTx.hash, + tokenAmount: '1', + nftType: 'singular', + fee: fee.toString(), + }; + await destinationChain.claimNFT721(claimData, signatureArray); + return [0n, '']; +} From 17ad53cde76f3d726b7c5a51bb5469a6e0781afc Mon Sep 17 00:00:00 2001 From: imsk17 Date: Wed, 24 Jan 2024 18:37:08 +0530 Subject: [PATCH 09/19] Tests: Add a generic test III --- src/generic-test.ts | 272 ++++++++++++++++++++ src/utils/functions/getEvmBridgeContract.ts | 10 +- 2 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 src/generic-test.ts diff --git a/src/generic-test.ts b/src/generic-test.ts new file mode 100644 index 00000000..75bbe9cc --- /dev/null +++ b/src/generic-test.ts @@ -0,0 +1,272 @@ +import { JsonRpcProvider, Wallet } from 'ethers'; +import { generateWalletsForChains } from './modules/setup/components'; +import { Wallet as SecretWallet } from 'secretjs'; +import { InMemorySigner } from '@taquito/signer'; +import { UserSigner } from '@multiversx/sdk-wallet/out'; +import { keyPairFromSecretKey } from 'ton-crypto'; +import { + SupportedChains, + bridgeTestChains, + testnetBridgeConfig, +} from './config/chainSpecs'; +import { Bridge__factory, ERC721Royalty__factory } from './contractsTypes'; +import { + getEvmBridgeContract, + getEvmSingleNftContract, + getStorageContract, + waitForMSWithMsg, +} from './utils'; +import { IEvmChainConfig, ITezosChainConfig } from './types'; +import { + getEvmSignedNftDetails, + getNftDetails, +} from './modules/validator/components/nftLockListener/utils'; + +import { CodeInfo } from './utils/functions/getSecretBridgeContract'; + +import getLockEventDecodedLog from './modules/validator/components/nftLockListener/components/evmLockListener/utils/getLockEventDecodedLog'; +import { LogObject } from '@src/modules/validator/utils/evmContractListener/types'; + +(async () => { + const genWallets = await generateWalletsForChains(); + // Assuming we have enough funds on the validator accounts itself. + const signers = { + bsc: new Wallet(genWallets.evmWallet.privateKey), + eth: new Wallet(genWallets.evmWallet.privateKey), + tezos: new InMemorySigner(genWallets.tezosWallet.secretKey), + multiversx: UserSigner.fromWallet( + genWallets.multiversXWallet.userWallet, + genWallets.multiversXWallet.password, + ), + secret: new SecretWallet(genWallets.secretWallet.privateKey), + ton: keyPairFromSecretKey( + Buffer.from(genWallets.tonWallet.secretKey, 'hex'), + ), + }; + const configs = { + bsc: bridgeTestChains.find( + (e) => e.chain === 'BSC', + )! as IEvmChainConfig, + eth: bridgeTestChains.find( + (e) => e.chain === 'ETH', + )! as IEvmChainConfig, + tezos: bridgeTestChains.find( + (e) => e.chain === 'TEZOS', + )! as ITezosChainConfig, + }; + const storage = getStorageContract({ + evmChainConfig: testnetBridgeConfig.storageConfig, + evmWallet: genWallets.evmWallet, + }); + + const data = { + bsc: { + signer: new Wallet(genWallets.evmWallet.privateKey), + bridge: getEvmBridgeContract({ + evmChainConfig: configs.bsc, + evmWallet: genWallets.evmWallet, + }), + config: configs.bsc, + logDecoder: getLockEventDecodedLog, + signedNftDetails: getEvmSignedNftDetails, + address: genWallets.evmWallet.address, + extractLogFromTx: async (hash: string): Promise => { + const { topicHash } = + Bridge__factory.createInterface().getEvent('Locked'); + const provider = new JsonRpcProvider(configs.bsc.rpcURL); + const receipt = await provider.getTransactionReceipt(hash)!; + + return (receipt?.logs.filter( + (e) => e.topics.includes(topicHash), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ) ?? [])[0] as unknown as any; + }, + }, + eth: { + signer: new Wallet(genWallets.evmWallet.privateKey), + bridge: getEvmBridgeContract({ + evmChainConfig: configs.eth, + evmWallet: genWallets.evmWallet, + }), + config: configs.eth, + logDecoder: getLockEventDecodedLog, + signedNftDetails: getEvmSignedNftDetails, + address: genWallets.evmWallet.address, + extractLogFromTx: async (hash: string): Promise => { + const { topicHash } = + Bridge__factory.createInterface().getEvent('Locked'); + const provider = new JsonRpcProvider(configs.bsc.rpcURL); + const receipt = await provider.getTransactionReceipt(hash)!; + + return (receipt?.logs.filter( + (e) => e.topics.includes(topicHash), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ) ?? [])[0] as unknown as any; + }, + }, + // tezos: { + // signer: new InMemorySigner(genWallets.tezosWallet.secretKey), + // bridge: getTezosBridgeContract({ + // tezosChainConfig: configs.tezos, + // tezosWallet: genWallets.tezosWallet, + // }), + // config: configs.eth, + // logDecoder: (log: LogObject) => log, + // signedNftDetails: getTezosSignedNftDetails, + // address: genWallets.evmWallet.address, + // extractLogFromTx: async (hash: string): Promise => { + // throw new Error(`Not implemented`) + // }, + // }, + }; + + // Create a NFT Contract + + const contract = await createNftOnEvm( + data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), + ); + + // Mint 5 NFT on the contract + for (let i = 0; i < 5; i++) { + await contract.mint( + signers.bsc.address, + i, + 10, + signers.bsc.address, + 'https://meta.polkamon.com/meta?id=10001852306', + ); + } + console.log('Minted 5 NFTs ON BSC'); + + // Approve the contract to spend the NFTs + const nftC = getEvmSingleNftContract( + { + contractAddress: await contract.getAddress(), + rpcURL: configs.bsc.rpcURL, + }, + data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), + ); + for (let i = 0; i < 5; i++) { + await nftC.approve(BigInt(i), data.bsc.config.contractAddress); + } + + // Lock the NFTs + async function transfer( + args: [ + { + fromChain: (typeof data)[keyof typeof data]; + toChain: (typeof data)[keyof typeof data]; + tokenId: string; + contractAddress: string; + codeInfo?: CodeInfo; + nftType: 'singular' | 'multiple'; + }, + ], + ) { + for (const tx of args) { + const from = await tx.fromChain.bridge.lock721({ + address: tx.toChain.address, + destinationChain: tx.toChain.config.chain as SupportedChains, + sourceNftContractAddress: tx.contractAddress, + tokenId: tx.tokenId, + }); + const log = await tx.fromChain.extractLogFromTx(from.hash); + const { + tokenId, // Unique ID for the NFT transfer + destinationChain, // Chain to where the NFT is being transferred + destinationUserAddress, // User's address in the destination chain + sourceNftContractAddress, // Address of the NFT contract in the source chain + tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) + nftType, // Sigular or multiple ( 721 / 1155) + sourceChain, // Source chain of NFT + } = tx.fromChain.logDecoder({ + log: log, + }); + + // if user gives a destination chain which is not registered with us, we early return + const sourceChain_ = tx.fromChain.config; + + const fee = String(await storage.chainFee(tx.toChain.config.chain)); // Required fee for claming nft on target chain + const royaltyReceiver = String( + await storage.chainRoyalty(tx.toChain.config.chain), + ); + + const { royalty, name, symbol, metadata } = await getNftDetails({ + sourceNftContractAddress, + sourceChain: sourceChain_, + tokenId, + nftType, + }); + + const nftTransferDetailsObject = { + tokenId, + sourceChain, + destinationChain, + destinationUserAddress, + sourceNftContractAddress, + name, + symbol, + royalty, + royaltyReceiver, + metadata, + transactionHash: from.hash, + tokenAmount, + nftType, + fee, + }; + let signatures = await storage.getLockNftSignatures( + from.hash, + tx.fromChain.config.chain, + ); + const neededSignatures = + Math.floor( + (2 / 3) * Number(await tx.toChain.bridge.validatorsCount()), + ) + 1; + while (signatures.length < neededSignatures) { + await waitForMSWithMsg( + 1000, + `waiting for signatures, ${signatures.length}`, + ); + signatures = await storage.getLockNftSignatures( + from.hash, + tx.fromChain.config.chain, + ); + } + + const signatureArray: string[] = []; + signatures.forEach((item) => { + signatureArray.push(item[1]); + }); + + console.log(signatures); + + const claimTx = await tx.toChain.bridge.claimNFT721( + nftTransferDetailsObject, + signatureArray, + ); + await claimTx.wait(); + + return claimTx.hash; + } + return ''; + } + + await transfer([ + { + fromChain: data.bsc, + toChain: data.eth, + contractAddress: await contract.getAddress(), + tokenId: '1', + nftType: 'singular', + }, + ]); +})(); + +async function createNftOnEvm(signer: Wallet) { + const contract = await new ERC721Royalty__factory(signer).deploy( + 'TestContract', + 'TC', + signer.address, + ); + return contract; +} diff --git a/src/utils/functions/getEvmBridgeContract.ts b/src/utils/functions/getEvmBridgeContract.ts index 724ee560..82baf319 100644 --- a/src/utils/functions/getEvmBridgeContract.ts +++ b/src/utils/functions/getEvmBridgeContract.ts @@ -44,9 +44,15 @@ const getEvmBridgeContract = ({ amt, ); }, - claimNFT1155: contract.claimNFT1155, + claimNFT1155: async (cd, sigs) => + contract.claimNFT1155(cd, sigs, { + value: cd.fee, + }), - claimNFT721: contract.claimNFT721, + claimNFT721: async (cd, sigs) => + contract.claimNFT721(cd, sigs, { + value: cd.fee, + }), lock721({ address, destinationChain, From 3b488cb1a37c7140eb1589862a4ba8d0d4495289 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Thu, 25 Jan 2024 18:57:59 +0530 Subject: [PATCH 10/19] Tests: Adapt Tezos and Other Chains for Generic Tests --- src/config/chainSpecs.ts | 6 +- src/generic-test.ts | 193 ++++++++++++--- .../components/handleValidatorAddition.ts | 2 +- .../utils/getTezosLockListenerHandler.ts | 4 +- .../utils/tezosContractListener/index.ts | 2 +- src/test/generic-test.ts | 228 ------------------ src/types/index.ts | 11 +- src/utils/functions/getEvmBridgeContract.ts | 28 ++- .../functions/getHederaBridgeContract.ts | 23 +- .../functions/getMultiversXBridgeContract.ts | 10 +- .../functions/getSecretBridgeContract.ts | 6 +- src/utils/functions/getTezosBridgeContract.ts | 114 ++++++--- src/utils/functions/getTonBridgeContract.ts | 13 +- 13 files changed, 301 insertions(+), 339 deletions(-) delete mode 100644 src/test/generic-test.ts diff --git a/src/config/chainSpecs.ts b/src/config/chainSpecs.ts index 9537d154..8a6f82b0 100644 --- a/src/config/chainSpecs.ts +++ b/src/config/chainSpecs.ts @@ -26,7 +26,7 @@ export const bridgeTestChains = [ intialFund: '50000000000000000', contractAddress: '0x3EC2839EcEAfa2Ce9e419718364B070563Db516e', chainType: 'evm', - lastBlock: 36788832, + lastBlock: 37159108, }, { chain: 'ETH', @@ -35,7 +35,7 @@ export const bridgeTestChains = [ intialFund: '50000000000000000', contractAddress: '0xA0C15702892491597D369A04d7366Af234cF5F73', chainType: 'evm', - lastBlock: 5053386, + lastBlock: 5150604, }, { chain: 'MATIC', @@ -82,7 +82,7 @@ export const bridgeTestChains = [ restApiURL: 'https://api.ghostnet.tzkt.io', contractAddress: 'KT1NHxTSXAFKH2y94PpfqDsg4bZ5SiF2V8a4', intialFund: '50000', - lastBlock: 5058309, + lastBlock: 5240862, nativeCoinSymbol: 'XTZ', chainType: 'tezos', }, diff --git a/src/generic-test.ts b/src/generic-test.ts index 75bbe9cc..b1507985 100644 --- a/src/generic-test.ts +++ b/src/generic-test.ts @@ -1,31 +1,51 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { JsonRpcProvider, Wallet } from 'ethers'; import { generateWalletsForChains } from './modules/setup/components'; import { Wallet as SecretWallet } from 'secretjs'; import { InMemorySigner } from '@taquito/signer'; import { UserSigner } from '@multiversx/sdk-wallet/out'; import { keyPairFromSecretKey } from 'ton-crypto'; + import { SupportedChains, bridgeTestChains, testnetBridgeConfig, } from './config/chainSpecs'; -import { Bridge__factory, ERC721Royalty__factory } from './contractsTypes'; +import { + Bridge__factory, + ERC721Royalty, + ERC721Royalty__factory, +} from './contractsTypes'; import { getEvmBridgeContract, getEvmSingleNftContract, getStorageContract, + getTezosBridgeContract, waitForMSWithMsg, } from './utils'; -import { IEvmChainConfig, ITezosChainConfig } from './types'; +import { + IEvmChainConfig, + ITezosChainConfig, + SignerAndSignature, +} from './types'; import { getEvmSignedNftDetails, getNftDetails, + getTezosSignedNftDetails, } from './modules/validator/components/nftLockListener/utils'; import { CodeInfo } from './utils/functions/getSecretBridgeContract'; import getLockEventDecodedLog from './modules/validator/components/nftLockListener/components/evmLockListener/utils/getLockEventDecodedLog'; import { LogObject } from '@src/modules/validator/utils/evmContractListener/types'; +import { getContractOperations } from './modules/validator/utils/tezosContractListener'; +import { + ILog, + ITransactions, +} from './modules/validator/utils/tezosContractListener/types'; +import { extractStrOrAddr } from './modules/validator/components/nftLockListener/components/tezosLockListener/utils/getTezosLockListenerHandler'; +import { TezosToolkit } from '@taquito/taquito'; +import { INftTransferDetailsObject } from './modules/validator/components/nftLockListener/components/types'; (async () => { const genWallets = await generateWalletsForChains(); @@ -81,6 +101,9 @@ import { LogObject } from '@src/modules/validator/utils/evmContractListener/type // eslint-disable-next-line @typescript-eslint/no-explicit-any ) ?? [])[0] as unknown as any; }, + cdMapper: (cd: INftTransferDetailsObject) => { + return cd; + }, }, eth: { signer: new Wallet(genWallets.evmWallet.privateKey), @@ -103,52 +126,141 @@ import { LogObject } from '@src/modules/validator/utils/evmContractListener/type // eslint-disable-next-line @typescript-eslint/no-explicit-any ) ?? [])[0] as unknown as any; }, + cdMapper: (cd: INftTransferDetailsObject) => { + return cd; + }, + }, + tezos: { + signer: new InMemorySigner(genWallets.tezosWallet.secretKey), + bridge: getTezosBridgeContract({ + tezosChainConfig: configs.tezos, + tezosWallet: genWallets.tezosWallet, + }), + config: configs.tezos, + logDecoder: (log: LogObject) => { + const data = log as ILog & { transaction_hash: string }; + const sourceNftContractAddress = extractStrOrAddr( + data.source_nft_address, + ); + const { + token_id: tokenId, // Unique ID for the NFT transfer + dest_chain: destinationChain, // Chain to where the NFT is being transferred + dest_address: destinationUserAddress, // User's address in the destination chain + token_amount: tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) + nft_type: nftType, // Sigular or multiple ( 721 / 1155) + source_chain: sourceChain, // Source chain of NFT + transaction_hash: transactionHash, + } = data; + return { + tokenId, + destinationChain, + destinationUserAddress, + tokenAmount, + nftType, + sourceChain, + transactionHash, + sourceNftContractAddress, + }; + }, + signedNftDetails: getTezosSignedNftDetails, + address: await new InMemorySigner( + genWallets.tezosWallet.secretKey, + ).publicKeyHash(), + extractLogFromTx: async (block: string): Promise => { + const Tezos = new TezosToolkit(configs.tezos.rpcURL); + const logs: ITransactions[] = await getContractOperations({ + contractAddress: configs.tezos.contractAddress, + fromLevel: parseInt(block) - 1, + toLevel: (await Tezos.rpc.getBlockHeader()).level, + restApiURL: configs.tezos.restApiURL, + }); + let payload = undefined; + for (const log of logs) { + payload = log.payload; + } + return payload! as LogObject; + }, + cdMapper: (nftTransferDetailsObject: INftTransferDetailsObject) => { + return { + token_id: nftTransferDetailsObject.tokenId, + source_chain: nftTransferDetailsObject.sourceChain, + dest_chain: nftTransferDetailsObject.destinationChain, + dest_address: + nftTransferDetailsObject.destinationUserAddress, + source_nft_contract_address: + nftTransferDetailsObject.sourceNftContractAddress, + name: nftTransferDetailsObject.name, + symbol: nftTransferDetailsObject.symbol, + royalty: nftTransferDetailsObject.royalty, + royalty_receiver: nftTransferDetailsObject.royaltyReceiver, + metadata: nftTransferDetailsObject.metadata, + transaction_hash: nftTransferDetailsObject.transactionHash, + token_amount: nftTransferDetailsObject.tokenAmount, + nft_type: nftTransferDetailsObject.nftType, + fee: nftTransferDetailsObject.fee, + }; + }, }, - // tezos: { - // signer: new InMemorySigner(genWallets.tezosWallet.secretKey), - // bridge: getTezosBridgeContract({ - // tezosChainConfig: configs.tezos, - // tezosWallet: genWallets.tezosWallet, - // }), - // config: configs.eth, - // logDecoder: (log: LogObject) => log, - // signedNftDetails: getTezosSignedNftDetails, - // address: genWallets.evmWallet.address, - // extractLogFromTx: async (hash: string): Promise => { - // throw new Error(`Not implemented`) - // }, - // }, }; // Create a NFT Contract + console.log(`Deploying NFT Contract on BSC`); + let contract: ERC721Royalty; + let deployed = false; - const contract = await createNftOnEvm( - data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), - ); + while (!deployed) { + try { + contract = await createNftOnEvm( + data.bsc.signer.connect( + new JsonRpcProvider(data.bsc.config.rpcURL), + ), + ); + deployed = true; + } catch (e) { + `Retrying to deploy NFT Contract on BSC`; + } + } // Mint 5 NFT on the contract - for (let i = 0; i < 5; i++) { - await contract.mint( - signers.bsc.address, - i, - 10, - signers.bsc.address, - 'https://meta.polkamon.com/meta?id=10001852306', - ); + for (let i = 0; i < 2; i++) { + let minted = false; + while (!minted) { + try { + await contract!.mint( + signers.bsc.address, + i, + 10, + signers.bsc.address, + 'https://meta.polkamon.com/meta?id=10001852306', + ); + minted = true; + } catch (e) { + console.log(`Retrying to mint NFT on BSC`); + } + } } - console.log('Minted 5 NFTs ON BSC'); + console.log('Minted 2 NFTs ON BSC'); // Approve the contract to spend the NFTs const nftC = getEvmSingleNftContract( { - contractAddress: await contract.getAddress(), + contractAddress: await contract!.getAddress(), rpcURL: configs.bsc.rpcURL, }, data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), ); - for (let i = 0; i < 5; i++) { - await nftC.approve(BigInt(i), data.bsc.config.contractAddress); + for (let i = 0; i < 2; i++) { + let approved = false; + while (!approved) { + try { + await nftC.approve(BigInt(i), data.bsc.config.contractAddress); + approved = true; + } catch (e) { + console.log(`Retrying to approve NFT on BSC`); + } + } } + console.log(`Approved NFTs on BSC`); // Lock the NFTs async function transfer( @@ -170,6 +282,11 @@ import { LogObject } from '@src/modules/validator/utils/evmContractListener/type sourceNftContractAddress: tx.contractAddress, tokenId: tx.tokenId, }); + await from.wait(); + console.log(`Locked on ${tx.fromChain.config.chain} ${from.hash}`); + + await new Promise((e) => setTimeout(e, 10000)); + const log = await tx.fromChain.extractLogFromTx(from.hash); const { tokenId, // Unique ID for the NFT transfer @@ -233,15 +350,18 @@ import { LogObject } from '@src/modules/validator/utils/evmContractListener/type ); } - const signatureArray: string[] = []; + const signatureArray: SignerAndSignature[] = []; signatures.forEach((item) => { - signatureArray.push(item[1]); + signatureArray.push({ + signer: item.signerAddress, + signature: item.signature, + }); }); console.log(signatures); const claimTx = await tx.toChain.bridge.claimNFT721( - nftTransferDetailsObject, + tx.toChain.cdMapper(nftTransferDetailsObject) as unknown as any, signatureArray, ); await claimTx.wait(); @@ -254,8 +374,8 @@ import { LogObject } from '@src/modules/validator/utils/evmContractListener/type await transfer([ { fromChain: data.bsc, - toChain: data.eth, - contractAddress: await contract.getAddress(), + toChain: data.tezos, + contractAddress: await contract!.getAddress(), tokenId: '1', nftType: 'singular', }, @@ -268,5 +388,6 @@ async function createNftOnEvm(signer: Wallet) { 'TC', signer.address, ); + await contract.deploymentTransaction()?.wait(); return contract; } diff --git a/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts b/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts index f93e46e2..529ffc53 100644 --- a/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts +++ b/src/modules/setup/components/addSelfInBridges/components/handleValidatorAddition.ts @@ -36,7 +36,7 @@ const handleValidatorAddition = async ({ let failiure = true; // eslint-disable-next-line @typescript-eslint/no-explicit-any - let bridgeContract: IBridge; + let bridgeContract: IBridge; let publicWalletAddress: string; let isChainFunded: () => Promise; diff --git a/src/modules/validator/components/nftLockListener/components/tezosLockListener/utils/getTezosLockListenerHandler.ts b/src/modules/validator/components/nftLockListener/components/tezosLockListener/utils/getTezosLockListenerHandler.ts index ad8002be..f9a023b8 100644 --- a/src/modules/validator/components/nftLockListener/components/tezosLockListener/utils/getTezosLockListenerHandler.ts +++ b/src/modules/validator/components/nftLockListener/components/tezosLockListener/utils/getTezosLockListenerHandler.ts @@ -5,7 +5,9 @@ import { getNftDetails } from '../../../utils'; import { approveLock } from '../..'; import { INftTransferDetailsObject } from '../../types'; -const extractStrOrAddr = (addr: { str: string } | { addr: string }): string => { +export const extractStrOrAddr = ( + addr: { str: string } | { addr: string }, +): string => { if ('str' in addr) return addr.str; return addr.addr; }; diff --git a/src/modules/validator/utils/tezosContractListener/index.ts b/src/modules/validator/utils/tezosContractListener/index.ts index 10dd1416..63357536 100644 --- a/src/modules/validator/utils/tezosContractListener/index.ts +++ b/src/modules/validator/utils/tezosContractListener/index.ts @@ -6,7 +6,7 @@ import { BLOCK_CHUNKS } from '@src/config/chainSpecs'; import { TezosToolkit } from '@taquito/taquito'; import axios from 'axios'; -async function getContractOperations({ +export async function getContractOperations({ contractAddress, fromLevel, toLevel, diff --git a/src/test/generic-test.ts b/src/test/generic-test.ts deleted file mode 100644 index 3a1e28a0..00000000 --- a/src/test/generic-test.ts +++ /dev/null @@ -1,228 +0,0 @@ -import { JsonRpcProvider, Wallet } from 'ethers'; -import { generateWalletsForChains } from '../modules/setup/components'; -import { Wallet as SecretWallet } from 'secretjs'; -import { InMemorySigner } from '@taquito/signer'; -import { UserSigner } from '@multiversx/sdk-wallet/out'; -import { keyPairFromSecretKey } from 'ton-crypto'; -import { bridgeTestChains, testnetBridgeConfig } from '../config/chainSpecs'; -import { BridgeStorage, ERC721Royalty__factory } from '../contractsTypes'; -import { - getEvmBridgeContract, - getEvmSingleNftContract, - getStorageContract, -} from '../utils'; -import { IBridge, IEvmChainConfig, TChain } from '../types'; -import { getNftDetails } from '../modules/validator/components/nftLockListener/utils'; -import { HederaLockArgs } from '../utils/functions/getHederaBridgeContract'; -import { TezosLockArgs } from '../utils/functions/getTezosBridgeContract'; -import { MultiversXLockArgs } from '../utils/functions/getMultiversXBridgeContract'; - -import { TonLockArgs } from '../utils/functions/getTonBridgeContract'; -import { SecretLockArgs } from '../utils/functions/getSecretBridgeContract'; -import { EvmLockArgs } from '../utils/functions/getEvmBridgeContract'; - -(async () => { - const genWallets = await generateWalletsForChains(); - // Assuming we have enough funds on the validator accounts itself. - const signers = { - bsc: new Wallet(genWallets.evmWallet.privateKey), - eth: new Wallet(genWallets.evmWallet.privateKey), - tezos: new InMemorySigner(genWallets.tezosWallet.secretKey), - multiversx: UserSigner.fromWallet( - genWallets.multiversXWallet.userWallet, - genWallets.multiversXWallet.password, - ), - secret: new SecretWallet(genWallets.secretWallet.privateKey), - ton: keyPairFromSecretKey( - Buffer.from(genWallets.tonWallet.secretKey, 'hex'), - ), - }; - const configs = { - bsc: bridgeTestChains.find( - (e) => e.chain === 'BSC', - )! as IEvmChainConfig, - eth: bridgeTestChains.find( - (e) => e.chain === 'ETH', - )! as IEvmChainConfig, - }; - - const data = { - storage: getStorageContract({ - evmChainConfig: testnetBridgeConfig.storageConfig, - evmWallet: genWallets.evmWallet, - }), - bsc: { - signer: new Wallet(genWallets.evmWallet.privateKey), - bridge: getEvmBridgeContract({ - evmChainConfig: configs.bsc, - evmWallet: genWallets.evmWallet, - }), - config: configs.bsc, - }, - eth: { - signer: new Wallet(genWallets.evmWallet.privateKey), - bridge: getEvmBridgeContract({ - evmChainConfig: configs.eth, - evmWallet: genWallets.evmWallet, - }), - config: configs.eth, - }, - }; - - // Create a NFT Contract - - const contract = await createNftOnEvm( - data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), - ); - - // Mint 5 NFT on the contract - for (let i = 0; i < 5; i++) { - await contract.mint( - signers.bsc.address, - i, - 10, - signers.bsc.address, - 'https://meta.polkamon.com/meta?id=10001852306', - ); - } - console.log('Minted 5 NFTs ON BSC'); - - // Approve the contract to spend the NFTs - const nftC = getEvmSingleNftContract( - { - contractAddress: await contract.getAddress(), - rpcURL: configs.bsc.rpcURL, - }, - data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), - ); - for (let i = 0; i < 5; i++) { - await nftC.approve(BigInt(i), data.bsc.config.contractAddress); - } - - // Lock the NFTs - - const lockTx = await data.bsc.bridge.lock721( - await contract.getAddress(), - '0', - 'ETH', - signers.eth.address, - ); - - // Wait for the NFTs to be locked - await new Promise((resolve) => setTimeout(resolve, 10000)); - - // Fetch the signatures - const signatures = await data.storage.getLockNftSignatures( - lockTx.hash, - 'BSC', - ); - - const signatureArray: string[] = []; - signatures.forEach((item) => { - signatureArray.push(item[1]); - }); - - const claimData = { - tokenId: '0', - sourceChain: 'BSC', - destinationChain: 'ETH', - destinationUserAddress: signers.eth.address, - sourceNftContractAddress: await contract.getAddress(), - name: 'TestContract', - symbol: 'TC', - royalty: '10', - royaltyReceiver: signers.bsc.address, - metadata: 'https://meta.polkamon.com/meta?id=10001852306', - transactionHash: lockTx.hash, - tokenAmount: '1', - nftType: 'singular', - fee: '100000000000000', - }; - - // Unlock it on the destination chain - const claimed = await data.eth.bridge.claimNFT721( - claimData, - signatureArray, - ); - - console.log(claimed); - const tokenId = 0; - const collectionAddress = ''; - pipe([tokenId, collectionAddress], []); -})(); - -async function createNftOnEvm(signer: Wallet) { - const contract = await new ERC721Royalty__factory(signer).deploy( - 'TestContract', - 'TC', - signer.address, - ); - return contract; -} - -type LockArgs = EvmLockArgs & - HederaLockArgs & - TezosLockArgs & - MultiversXLockArgs & - SecretLockArgs & - TonLockArgs; - -export async function pipe( - chainStart: T, - promises: Array<(arg0: T) => Promise>, -) { - if (promises.length > 0) { - return promises.pop()!(chainStart).then((s) => pipe(s, promises)); - } -} - -export async function transferNft( - sourceChain: IBridge, - sourceChainConfig: TChain, - lockArgs: LockArgs, - storage: BridgeStorage, - destinationChain: IBridge, -): Promise<[bigint, string]> { - // as any - const lockTx = await sourceChain.lock721(lockArgs); - - // Wait for the NFTs to be locked - await new Promise((resolve) => setTimeout(resolve, 10000)); - - // Fetch the signatures - const signatures = await storage.getLockNftSignatures( - lockTx.hash, - sourceChainConfig.chain, - ); - const fee = await storage.chainFee(lockArgs.destinationChain); - - const nftContract = await getNftDetails({ - nftType: 'singular', - sourceChain: sourceChainConfig, - sourceNftContractAddress: lockArgs.sourceNftContractAddress, - tokenId: lockArgs.tokenId, - }); - - const signatureArray: string[] = []; - signatures.forEach((item) => { - signatureArray.push(item[1]); - }); - const claimData = { - tokenId: '0', - sourceChain: sourceChainConfig.chain, - destinationChain: lockArgs.destinationChain, - destinationUserAddress: lockArgs.address, - sourceNftContractAddress: lockArgs.sourceNftContractAddress, - name: nftContract.name, - symbol: nftContract.symbol, - royalty: nftContract.royalty, - royaltyReceiver: '', - metadata: nftContract.metadata, - transactionHash: lockTx.hash, - tokenAmount: '1', - nftType: 'singular', - fee: fee.toString(), - }; - await destinationChain.claimNFT721(claimData, signatureArray); - return [0n, '']; -} diff --git a/src/types/index.ts b/src/types/index.ts index 6b65edaf..5d3044bd 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -209,7 +209,12 @@ type IBridgeConfig = { stakingConfig: IStakingConfig; }; -type IBridge = { +export type SignerAndSignature = { + signer: string; + signature: string; +}; + +type IBridge = { validators: (address: string) => Promise<{ added: boolean }>; validatorsCount: () => Promise; addValidator: ( @@ -227,11 +232,11 @@ type IBridge = { ) => Promise<{ hash: string; wait: () => Promise }>; claimNFT721: ( nftTransferData: TClaimData, - sigs: TSig[], + sigs: SignerAndSignature[], ) => Promise<{ hash: string; wait: () => Promise }>; claimNFT1155?: ( nftTransferData: TClaimData, - sigs: TSig[], + sigs: SignerAndSignature[], ) => Promise<{ hash: string; wait: () => Promise }>; }; diff --git a/src/utils/functions/getEvmBridgeContract.ts b/src/utils/functions/getEvmBridgeContract.ts index 82baf319..30104154 100644 --- a/src/utils/functions/getEvmBridgeContract.ts +++ b/src/utils/functions/getEvmBridgeContract.ts @@ -1,4 +1,4 @@ -import { BytesLike, ethers } from 'ethers'; +import { ethers } from 'ethers'; import { Bridge, Bridge__factory } from '../../contractsTypes'; import { IBridge, IEvmChainConfigAndEvmWallet } from '@src/types'; import { SupportedChains } from '@src/config/chainSpecs'; @@ -15,8 +15,7 @@ const getEvmBridgeContract = ({ evmWallet, }: IEvmChainConfigAndEvmWallet): IBridge< EvmLockArgs, - Bridge.ClaimDataStruct, - BytesLike + Bridge.ClaimDataStruct > => { const provider = new ethers.JsonRpcProvider(evmChainConfig.rpcURL); const wallet = new ethers.Wallet(evmWallet.privateKey, provider); @@ -45,14 +44,22 @@ const getEvmBridgeContract = ({ ); }, claimNFT1155: async (cd, sigs) => - contract.claimNFT1155(cd, sigs, { - value: cd.fee, - }), + contract.claimNFT1155( + cd, + sigs.map((e) => e.signature), + { + value: cd.fee, + }, + ), claimNFT721: async (cd, sigs) => - contract.claimNFT721(cd, sigs, { - value: cd.fee, - }), + contract.claimNFT721( + cd, + sigs.map((e) => e.signature), + { + value: cd.fee, + }, + ), lock721({ address, destinationChain, @@ -64,6 +71,9 @@ const getEvmBridgeContract = ({ destinationChain, address, sourceNftContractAddress, + { + gasLimit: 500_000, + }, ); }, }; diff --git a/src/utils/functions/getHederaBridgeContract.ts b/src/utils/functions/getHederaBridgeContract.ts index df9928ab..45ecc4aa 100644 --- a/src/utils/functions/getHederaBridgeContract.ts +++ b/src/utils/functions/getHederaBridgeContract.ts @@ -1,4 +1,4 @@ -import { BytesLike, ethers } from 'ethers'; +import { ethers } from 'ethers'; import { Bridge, Bridge__factory } from '../../contractsTypes'; import { IBridge, IHederaChainConfigAndEvmWallet } from '@src/types'; import { SupportedChains } from '@src/config/chainSpecs'; @@ -15,8 +15,7 @@ const getHederaBridgeContract = ({ evmWallet, }: IHederaChainConfigAndEvmWallet): IBridge< HederaLockArgs, - Bridge.ClaimDataStruct, - BytesLike + Bridge.ClaimDataStruct > => { const provider = new ethers.JsonRpcProvider(hederaChainConfig.rpcURL); const wallet = new ethers.Wallet(evmWallet.privateKey, provider); @@ -44,9 +43,23 @@ const getHederaBridgeContract = ({ amt, ); }, - claimNFT1155: contract.claimNFT1155, + claimNFT1155: async (cd, sigs) => + contract.claimNFT1155( + cd, + sigs.map((e) => e.signature), + { + value: cd.fee, + }, + ), - claimNFT721: contract.claimNFT721, + claimNFT721: async (cd, sigs) => + contract.claimNFT721( + cd, + sigs.map((e) => e.signature), + { + value: cd.fee, + }, + ), lock721({ address, destinationChain, diff --git a/src/utils/functions/getMultiversXBridgeContract.ts b/src/utils/functions/getMultiversXBridgeContract.ts index 612b3bb2..a84a4193 100644 --- a/src/utils/functions/getMultiversXBridgeContract.ts +++ b/src/utils/functions/getMultiversXBridgeContract.ts @@ -57,11 +57,7 @@ const getMultiversXBridgeContract = ({ multiversXWallet, }: IMultiversXChainConfigAndMultiversXWallet): IBridge< MultiversXLockArgs, - ClaimStruct, - { - signerAddress: string; - signature: string; - } + ClaimStruct > => { const abiRegistry = AbiRegistry.create(multiversXBridgeABI); @@ -344,9 +340,7 @@ const getMultiversXBridgeContract = ({ sigs.map((item) => { return { public_key: new AddressValue( - new Address( - Buffer.from(item.signerAddress, 'hex'), - ), + new Address(Buffer.from(item.signer, 'hex')), ), sig: new BytesValue( Buffer.from(item.signature, 'hex'), diff --git a/src/utils/functions/getSecretBridgeContract.ts b/src/utils/functions/getSecretBridgeContract.ts index 26fd5565..cb48cc6c 100644 --- a/src/utils/functions/getSecretBridgeContract.ts +++ b/src/utils/functions/getSecretBridgeContract.ts @@ -37,11 +37,7 @@ export type ClaimData = { const getSecretBridgeContract = ({ secretChainConfig, secretWallet, -}: ISecretChainConfigAndSecretWallet): IBridge< - SecretLockArgs, - ClaimData, - { signer: string; signature: string } -> => { +}: ISecretChainConfigAndSecretWallet): IBridge => { const bridgeContractCodeHash = 'dbccb5a7abf668d050d720cd01ea39d556492456ceb870dcae80dc4ff8572575'; const secretjs = new SecretNetworkClient({ diff --git a/src/utils/functions/getTezosBridgeContract.ts b/src/utils/functions/getTezosBridgeContract.ts index ac68bf39..219ee3a7 100644 --- a/src/utils/functions/getTezosBridgeContract.ts +++ b/src/utils/functions/getTezosBridgeContract.ts @@ -5,10 +5,8 @@ import { validateAddress } from '@taquito/utils'; import { BridgeContractType } from '@src/contractsTypes/tezosContractTypes/Bridge.types'; import { address, - key, mutez, nat, - signature, tas, } from '@src/contractsTypes/tezosContractTypes/type-aliases'; import { b58cencode, prefix, b58cdecode } from '@taquito/utils'; @@ -42,15 +40,7 @@ export type TezosClaimArgs = { const getTezosBridgeContract = ({ tezosChainConfig, tezosWallet, -}: ITezosChainConfigAndTezosWallet): IBridge< - TezosLockArgs, - TezosClaimArgs, - { - signer: key; - sig: signature; - addr: address; - } -> => { +}: ITezosChainConfigAndTezosWallet): IBridge => { const getBridgeInstance = async () => { const Tezos = new TezosToolkit(tezosChainConfig.rpcURL); const tezosSigner = await InMemorySigner.fromSecretKey( @@ -96,30 +86,96 @@ const getTezosBridgeContract = ({ str: data.source_nft_contract_address, }; const bridge = await getBridgeInstance(); - const tx = await bridge.methods - .claim_nft( - data.token_id, - data.source_chain, - data.dest_chain, - data.dest_address, - sourceNftContractAddress, - data.name, - data.symbol, - data.royalty, - data.royalty_receiver, - data.metadata, - data.transaction_hash, - data.token_amount, - data.nft_type, - data.fee, - sigs, - ) + + console.log({ + dest_address: data.dest_address, + dest_chain: data.dest_chain, + fee: data.fee, + metadata: data.metadata, + name: data.name, + nft_type: data.nft_type, + royalty: data.royalty, + royalty_receiver: data.royalty_receiver, + source_chain: data.source_chain, + symbol: data.symbol, + token_amount: data.token_amount, + token_id: data.token_id, + transaction_hash: data.transaction_hash, + source_nft_contract_address: sourceNftContractAddress, + sigs: sigs.map((e) => { + console.log(e); + const addr = tas.address( + b58cencode( + hash( + new Uint8Array( + b58cdecode(e.signer, prefix.edpk), + ), + 20, + ), + prefix.tz1, + ), + ); + return { + addr, + sig: tas.signature( + Buffer.from( + e.signature.replace('0x', ''), + 'hex', + ).toString(), + ), + signer: tas.key(e.signer), + }; + }), + }); + + const tx = await bridge.methodsObject + .claim_nft({ + dest_address: data.dest_address, + dest_chain: data.dest_chain, + fee: data.fee, + metadata: data.metadata, + name: data.name, + nft_type: data.nft_type, + royalty: data.royalty, + royalty_receiver: data.royalty_receiver, + source_chain: data.source_chain, + symbol: data.symbol, + token_amount: data.token_amount, + token_id: data.token_id, + transaction_hash: data.transaction_hash, + source_nft_contract_address: sourceNftContractAddress, + sigs: sigs.map((e) => { + console.log(e); + const addr = tas.address( + b58cencode( + hash( + new Uint8Array( + b58cdecode(e.signer, prefix.edpk), + ), + 20, + ), + prefix.tz1, + ), + ); + return { + addr, + sig: tas.signature( + Buffer.from( + e.signature.replace('0x', ''), + 'hex', + ).toString(), + ), + signer: tas.key(e.signer), + }; + }), + }) .send(); return { hash: tx.hash, wait: async () => { await tx.confirmation(1); }, + block: tx.includedInBlock, }; }, validators: async (address: string) => { diff --git a/src/utils/functions/getTonBridgeContract.ts b/src/utils/functions/getTonBridgeContract.ts index 9d263117..4df9dad8 100644 --- a/src/utils/functions/getTonBridgeContract.ts +++ b/src/utils/functions/getTonBridgeContract.ts @@ -21,14 +21,7 @@ export type TonLockArgs = { const getTonBridgeContract = ({ tonChainConfig, tonWallet, -}: ITonChainConfigAndTonWallet): IBridge< - TonLockArgs, - ClaimData, - { - publicKey: bigint; - sig: string; - } -> => { +}: ITonChainConfigAndTonWallet): IBridge => { const client = new TonClient({ endpoint: tonChainConfig.rpcURL, apiKey: 'f3f6ef64352ac53cdfca18a3ba5372983e4037182c2b510fc52de5a259ecf292', @@ -79,9 +72,9 @@ const getTonBridgeContract = ({ const sigs: SignerAndSignature[] = sigsA.map((e) => { return { $$type: 'SignerAndSignature', - key: e.publicKey, + key: BigInt(e.signer), signature: beginCell() - .storeBuffer(Buffer.from(e.sig, 'hex')) + .storeBuffer(Buffer.from(e.signature, 'hex')) .endCell(), }; }); From dfbd6efd29adee0cb7981b254820190cd0107cea Mon Sep 17 00:00:00 2001 From: imsk17 Date: Fri, 26 Jan 2024 17:44:28 +0530 Subject: [PATCH 11/19] Tests: Adapt MultiversX for Generic Test --- src/config/chainSpecs.ts | 61 ++++----- src/generic-test.ts | 123 +++++++++++++++++- .../utils/getLogs.ts | 2 +- 3 files changed, 153 insertions(+), 33 deletions(-) diff --git a/src/config/chainSpecs.ts b/src/config/chainSpecs.ts index 8a6f82b0..5a22bf3a 100644 --- a/src/config/chainSpecs.ts +++ b/src/config/chainSpecs.ts @@ -46,36 +46,37 @@ export const bridgeTestChains = [ chainType: 'evm', lastBlock: 52122800, }, - // { - // chain: "MULTIVERSX", - // nativeCoinSymbol: "EGLD", - // intialFund: "50000000000000000", - // contractAddress: "erd1qqqqqqqqqqqqqpgqtsw8s3evjjyqqa2j2tfn9yvufqskdv236n9s2a06h9", - // chainType: 'multiversX', - // elasticSearchURL: "https://devnet-index.multiversx.com", - // gatewayURL: "https://devnet-gateway.multiversx.com", - // lastBlock: 0, - // chainID: "D" - // }, - // { - // chain: "TON", - // rpcURL: "https://testnet.toncenter.com/api/v2/jsonRPC", - // nativeCoinSymbol: "TON", - // intialFund: "500000000", - // contractAddress: "EQDI6P9gheuWLh1euThjFE2muUpa9tp2y49TD6Zz5oOF5gWL", - // chainType: 'ton', - // lastBlock: 16810573000003 - // }, - // { - // chain: "SECRET", - // rpcURL: "https://pulsar.api.trivium.network:1317", - // nativeCoinSymbol: "USCRT", - // intialFund: "50000", - // contractAddress: "secret1jcfm9ct9jdy9uugcnfnjzpv4eydaj620kuvulp", - // chainType: 'scrt', - // chainId: 'pulsar-3', - // lastBlock: 50883 - // }, + { + chain: 'MULTIVERSX', + nativeCoinSymbol: 'EGLD', + intialFund: '50000000000000000', + contractAddress: + 'erd1qqqqqqqqqqqqqpgqtsw8s3evjjyqqa2j2tfn9yvufqskdv236n9s2a06h9', + chainType: 'multiversX', + elasticSearchURL: 'https://devnet-index.multiversx.com', + gatewayURL: 'https://devnet-gateway.multiversx.com', + lastBlock: 0, + chainID: 'D', + }, + { + chain: 'TON', + rpcURL: 'https://testnet.toncenter.com/api/v2/jsonRPC', + nativeCoinSymbol: 'TON', + intialFund: '500000000', + contractAddress: 'EQDI6P9gheuWLh1euThjFE2muUpa9tp2y49TD6Zz5oOF5gWL', + chainType: 'ton', + lastBlock: 16810573000003, + }, + { + chain: 'SECRET', + rpcURL: 'https://pulsar.api.trivium.network:1317', + nativeCoinSymbol: 'USCRT', + intialFund: '50000', + contractAddress: 'secret1jcfm9ct9jdy9uugcnfnjzpv4eydaj620kuvulp', + chainType: 'scrt', + chainId: 'pulsar-3', + lastBlock: 50883, + }, { chain: 'TEZOS', rpcURL: 'https://ghostnet.ecadinfra.com', diff --git a/src/generic-test.ts b/src/generic-test.ts index b1507985..12df6073 100644 --- a/src/generic-test.ts +++ b/src/generic-test.ts @@ -19,23 +19,30 @@ import { import { getEvmBridgeContract, getEvmSingleNftContract, + getHederaBridgeContract, + getMultiversXBridgeContract, getStorageContract, getTezosBridgeContract, waitForMSWithMsg, } from './utils'; import { IEvmChainConfig, + IHederaChainConfig, + IMultiversXChainConfig, + ISecretChainConfig, ITezosChainConfig, + ITonChainConfig, SignerAndSignature, } from './types'; import { getEvmSignedNftDetails, + getMultiversXSignedNftDetails, getNftDetails, getTezosSignedNftDetails, } from './modules/validator/components/nftLockListener/utils'; import { CodeInfo } from './utils/functions/getSecretBridgeContract'; - +import { getLockEventDecodedLog as getMxLockEventDecodedLog } from './modules/validator/components/nftLockListener/components/multiversXLockListener/utils'; import getLockEventDecodedLog from './modules/validator/components/nftLockListener/components/evmLockListener/utils/getLockEventDecodedLog'; import { LogObject } from '@src/modules/validator/utils/evmContractListener/types'; import { getContractOperations } from './modules/validator/utils/tezosContractListener'; @@ -46,6 +53,12 @@ import { import { extractStrOrAddr } from './modules/validator/components/nftLockListener/components/tezosLockListener/utils/getTezosLockListenerHandler'; import { TezosToolkit } from '@taquito/taquito'; import { INftTransferDetailsObject } from './modules/validator/components/nftLockListener/components/types'; +import { ClaimStruct } from './utils/functions/getMultiversXBridgeContract'; +import axios from 'axios'; +import { + IMultiverseXLogEvent, + IMultiverseXLogs, +} from './modules/validator/utils/multiversXContractListener/utils/types'; (async () => { const genWallets = await generateWalletsForChains(); @@ -70,9 +83,21 @@ import { INftTransferDetailsObject } from './modules/validator/components/nftLoc eth: bridgeTestChains.find( (e) => e.chain === 'ETH', )! as IEvmChainConfig, + hedera: bridgeTestChains.find( + (e) => e.chain === 'HEDERA', + )! as IHederaChainConfig, tezos: bridgeTestChains.find( (e) => e.chain === 'TEZOS', )! as ITezosChainConfig, + multiversx: bridgeTestChains.find( + (e) => e.chain === 'MULTIVERSX', + )! as IMultiversXChainConfig, + secret: bridgeTestChains.find( + (e) => e.chain === 'SECRET', + )! as ISecretChainConfig, + ton: bridgeTestChains.find( + (e) => e.chain === 'TON', + )! as ITonChainConfig, }; const storage = getStorageContract({ evmChainConfig: testnetBridgeConfig.storageConfig, @@ -105,6 +130,98 @@ import { INftTransferDetailsObject } from './modules/validator/components/nftLoc return cd; }, }, + hedera: { + signer: new Wallet(genWallets.evmWallet.privateKey), + bridge: getHederaBridgeContract({ + hederaChainConfig: configs.hedera, + evmWallet: genWallets.evmWallet, + }), + config: configs.hedera, + logDecoder: getLockEventDecodedLog, + signedNftDetails: getEvmSignedNftDetails, + address: genWallets.evmWallet.address, + extractLogFromTx: async (hash: string): Promise => { + const { topicHash } = + Bridge__factory.createInterface().getEvent('Locked'); + const provider = new JsonRpcProvider(configs.bsc.rpcURL); + const receipt = await provider.getTransactionReceipt(hash)!; + + return (receipt?.logs.filter( + (e) => e.topics.includes(topicHash), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ) ?? [])[0] as unknown as any; + }, + cdMapper: (cd: INftTransferDetailsObject) => { + return cd; + }, + }, + multiversx: { + signer: UserSigner.fromWallet( + genWallets.multiversXWallet, + genWallets.multiversXWallet.password, + ), + config: configs.multiversx, + address: genWallets.multiversXWallet.userWallet.address, + bridge: getMultiversXBridgeContract({ + multiversXChainConfig: configs.multiversx, + multiversXWallet: genWallets.multiversXWallet, + }), + signedNftDetails: getMultiversXSignedNftDetails, + cdMapper: (cd: INftTransferDetailsObject): ClaimStruct => { + return { ...cd, attrs: cd.metadata }; + }, + extractLogFromTx: async (hash: string): Promise => { + const eventIdentifier = ['lock721', 'lock1155']; + const resultantLogs: (IMultiverseXLogEvent & { + txHash: string; + })[] = []; + const incompleteTx: { [txHash: string]: boolean } = {}; + + const getResultantLogs = ( + logs: IMultiverseXLogs, + txHash: string, + ) => { + const eventLog = logs.events.find((_event) => { + return eventIdentifier.includes(_event.identifier); + }); + const isCompletedTx = logs.events.find( + (_event) => _event.identifier === 'completedTxEvent', + ); + if (eventLog && isCompletedTx) { + resultantLogs.push({ ...eventLog, txHash }); + } else if (eventLog && !isCompletedTx) { + incompleteTx[txHash] = true; + } + }; + const response = ( + await axios.get( + `${configs.multiversx.gatewayURL.replace('gateway', 'api')}/transactions/${hash}`, + ) + ).data; + + if (response?.logs) getResultantLogs(response.logs, hash); + if (response?.results?.logs) + getResultantLogs(response.results.log, hash); + if (response?.results.length > 0) { + for (const i of response.results) { + if (i?.logs) { + getResultantLogs(i.logs, hash); + } + } + } + return resultantLogs as any; + }, + logDecoder: (log: LogObject) => { + const data = log as (IMultiverseXLogEvent & { + txHash: string; + })[]; + for (const log of data) { + const decodedLog = getMxLockEventDecodedLog({ log: log }); + return decodedLog; + } + }, + }, + eth: { signer: new Wallet(genWallets.evmWallet.privateKey), bridge: getEvmBridgeContract({ @@ -271,6 +388,7 @@ import { INftTransferDetailsObject } from './modules/validator/components/nftLoc tokenId: string; contractAddress: string; codeInfo?: CodeInfo; + nonce?: string; nftType: 'singular' | 'multiple'; }, ], @@ -281,6 +399,7 @@ import { INftTransferDetailsObject } from './modules/validator/components/nftLoc destinationChain: tx.toChain.config.chain as SupportedChains, sourceNftContractAddress: tx.contractAddress, tokenId: tx.tokenId, + nonce: tx.nonce!, }); await from.wait(); console.log(`Locked on ${tx.fromChain.config.chain} ${from.hash}`); @@ -298,7 +417,7 @@ import { INftTransferDetailsObject } from './modules/validator/components/nftLoc sourceChain, // Source chain of NFT } = tx.fromChain.logDecoder({ log: log, - }); + })!; // if user gives a destination chain which is not registered with us, we early return const sourceChain_ = tx.fromChain.config; diff --git a/src/modules/validator/utils/multiversXContractListener/utils/getLogs.ts b/src/modules/validator/utils/multiversXContractListener/utils/getLogs.ts index a7b42227..cc0d2888 100644 --- a/src/modules/validator/utils/multiversXContractListener/utils/getLogs.ts +++ b/src/modules/validator/utils/multiversXContractListener/utils/getLogs.ts @@ -6,7 +6,7 @@ import { } from './types'; import { MultiversXTransactions } from '@src/db/entity/MultiversXTransactions'; -const getLogs = async ({ +export const getLogs = async ({ gatewayURL, txHashes, eventIdentifier, From da1ad9ce0c781ef768618dfd26fe4149505fac28 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Fri, 26 Jan 2024 17:57:53 +0530 Subject: [PATCH 12/19] Tests: Adapt Secret for Generic Test --- src/generic-test.ts | 100 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/src/generic-test.ts b/src/generic-test.ts index 12df6073..8a895c96 100644 --- a/src/generic-test.ts +++ b/src/generic-test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { JsonRpcProvider, Wallet } from 'ethers'; import { generateWalletsForChains } from './modules/setup/components'; -import { Wallet as SecretWallet } from 'secretjs'; +import { SecretNetworkClient, Wallet as SecretWallet } from 'secretjs'; import { InMemorySigner } from '@taquito/signer'; import { UserSigner } from '@multiversx/sdk-wallet/out'; import { keyPairFromSecretKey } from 'ton-crypto'; @@ -38,10 +38,14 @@ import { getEvmSignedNftDetails, getMultiversXSignedNftDetails, getNftDetails, + getSecretSignedNftDetails, getTezosSignedNftDetails, } from './modules/validator/components/nftLockListener/utils'; -import { CodeInfo } from './utils/functions/getSecretBridgeContract'; +import getSecretBridgeContract, { + ClaimData, + CodeInfo, +} from './utils/functions/getSecretBridgeContract'; import { getLockEventDecodedLog as getMxLockEventDecodedLog } from './modules/validator/components/nftLockListener/components/multiversXLockListener/utils'; import getLockEventDecodedLog from './modules/validator/components/nftLockListener/components/evmLockListener/utils/getLockEventDecodedLog'; import { LogObject } from '@src/modules/validator/utils/evmContractListener/types'; @@ -318,6 +322,97 @@ import { }; }, }, + secret: { + signer: new SecretWallet(genWallets.secretWallet.privateKey), + bridge: getSecretBridgeContract({ + secretChainConfig: configs.secret, + secretWallet: genWallets.secretWallet, + }), + config: configs.secret, + logDecoder: (log: LogObject) => { + const data = log as ILog & { transaction_hash: string }; + const sourceNftContractAddress = extractStrOrAddr( + data.source_nft_address, + ); + const { + token_id: tokenId, // Unique ID for the NFT transfer + dest_chain: destinationChain, // Chain to where the NFT is being transferred + dest_address: destinationUserAddress, // User's address in the destination chain + token_amount: tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) + nft_type: nftType, // Sigular or multiple ( 721 / 1155) + source_chain: sourceChain, // Source chain of NFT + transaction_hash: transactionHash, + } = data; + return { + tokenId, + destinationChain, + destinationUserAddress, + tokenAmount, + nftType, + sourceChain, + transactionHash, + sourceNftContractAddress, + }; + }, + signedNftDetails: getSecretSignedNftDetails, + address: genWallets.secretWallet.publicKey, + extractLogFromTx: async (hash: string): Promise => { + const eventId = 'LockedEventInfo'; + const secretjs = new SecretNetworkClient({ + url: configs.secret.rpcURL, + chainId: configs.secret.chainId, + }); + const tx = await secretjs.query.getTx(hash)!; + if (!tx) { + throw new Error('Tx not found'); + } + const log = tx.jsonLog + ?.at(0) + ?.events.find((item) => item.type === 'wasm') + ?.attributes.find((item) => item.key === eventId); + const { + token_id: tokenId, // Unique ID for the NFT transfer + destination_chain: destinationChain, // Chain to where the NFT is being transferred + destination_user_address: destinationUserAddress, // User's address in the destination chain + source_nft_contract_address: sourceNftContractAddress, // Address of the NFT contract in the source chain + token_amount: tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) + nft_type: nftType, // Sigular or multiple ( 721 / 1155) + source_chain: sourceChain, // Source chain of NFT + } = JSON.parse(log!.value); + return { + tokenId, + destinationChain, + destinationUserAddress, + sourceNftContractAddress, + tokenAmount, + nftType, + sourceChain, + } as LogObject; + }, + cdMapper: ( + nftTransferDetailsObject: INftTransferDetailsObject, + ): ClaimData => { + return { + token_id: nftTransferDetailsObject.tokenId, + source_chain: nftTransferDetailsObject.sourceChain, + destination_chain: + nftTransferDetailsObject.destinationChain, + destination_user_address: + nftTransferDetailsObject.destinationUserAddress, + source_nft_contract_address: + nftTransferDetailsObject.sourceNftContractAddress, + name: nftTransferDetailsObject.name, + symbol: nftTransferDetailsObject.symbol, + royalty: parseInt(nftTransferDetailsObject.royalty), + royalty_receiver: nftTransferDetailsObject.royaltyReceiver, + metadata: nftTransferDetailsObject.metadata, + transaction_hash: nftTransferDetailsObject.transactionHash, + token_amount: nftTransferDetailsObject.tokenAmount, + nft_type: nftTransferDetailsObject.nftType, + fee: nftTransferDetailsObject.fee, + }; + }, + }, }; // Create a NFT Contract @@ -400,6 +495,7 @@ import { sourceNftContractAddress: tx.contractAddress, tokenId: tx.tokenId, nonce: tx.nonce!, + collectionCodeInfo: tx.codeInfo!, }); await from.wait(); console.log(`Locked on ${tx.fromChain.config.chain} ${from.hash}`); From be6c1d6421e1cd2491919d639c293cc0468d5421 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Fri, 26 Jan 2024 18:37:04 +0530 Subject: [PATCH 13/19] Tests: Adapt Ton for Generic Test --- src/generic-test.ts | 47 ++++++++++++++++++++- src/utils/functions/getTonBridgeContract.ts | 4 +- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/generic-test.ts b/src/generic-test.ts index 8a895c96..fe382f5a 100644 --- a/src/generic-test.ts +++ b/src/generic-test.ts @@ -225,7 +225,6 @@ import { } }, }, - eth: { signer: new Wallet(genWallets.evmWallet.privateKey), bridge: getEvmBridgeContract({ @@ -413,6 +412,52 @@ import { }; }, }, + // ton: { + // signer: WalletContractV4.create({ + // publicKey: Buffer.from(genWallets.tonWallet.publicKey, 'hex'), + // workchain: 0, + // }), + + // bridge: getTonBridgeContract({ + // tonChainConfig: configs.ton, + // tonWallet: genWallets.tonWallet, + // }), + // config: configs.ton, + // logDecoder: (_log: LogObject) => {}, + // signedNftDetails: getTonSignedNftDetails, + // address: genWallets.tonWallet.publicKey, + // extractLogFromTx: async (_hash: string): Promise => { + // const client = new TonClient({ + // endpoint: configs.ton.rpcURL, + // apiKey: 'f3f6ef64352ac53cdfca18a3ba5372983e4037182c2b510fc52de5a259ecf292', + // }); + // const latestTx = await client.getTransactions( + // Address.parseFriendly(configs.ton.contractAddress).address, + // { limit: 1 }, + // ); + // if (!latestTx.length) { + // throw new Error('No Transactions found'); + // } + // const tx = latestTx[0]; + + // const handleLog = getTonLockListenerHandler({ + // config: testnetBridgeConfig, + // tonChainConfig: configs.ton, + // wallets: genWallets, + // }); + // for (let i = 0; i < tx.outMessages.size; i++) { + // await handleLog({ + // log: tx.outMessages.get(i)!, + // hash: tx.hash().toString('base64'), + // }); + // } + // }, + // cdMapper: ( + // _nftTransferDetailsObject: INftTransferDetailsObject, + // ): ClaimData => { + // throw new Error('Not Implemented'); + // }, + // }, }; // Create a NFT Contract diff --git a/src/utils/functions/getTonBridgeContract.ts b/src/utils/functions/getTonBridgeContract.ts index 4df9dad8..e6f2a222 100644 --- a/src/utils/functions/getTonBridgeContract.ts +++ b/src/utils/functions/getTonBridgeContract.ts @@ -15,7 +15,7 @@ export type TonLockArgs = { destinationChain: string; address: string; sourceNftContractAddress: string; - tokenId: bigint; + tokenId: string; }; const getTonBridgeContract = ({ @@ -63,7 +63,7 @@ const getTonBridgeContract = ({ sourceNftContractAddress: Address.parseFriendly( sourceNftContractAddress, ).address, - tokenId: tokenId, + tokenId: BigInt(tokenId), }, ); return { hash: 'No Tx Hash', wait: async () => {} }; From 610057ef7bf5491629c0bb05d90b4060aeb583a6 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Mon, 29 Jan 2024 18:28:50 +0530 Subject: [PATCH 14/19] Tests: Fix Tezos and Multiversx --- src/config/chainSpecs.ts | 2 +- src/generic-test.ts | 125 +++++++++--------- .../functions/getMultiversXBridgeContract.ts | 28 ++-- src/utils/functions/getTezosBridgeContract.ts | 79 ++++------- 4 files changed, 105 insertions(+), 129 deletions(-) diff --git a/src/config/chainSpecs.ts b/src/config/chainSpecs.ts index 5a22bf3a..cf5862c6 100644 --- a/src/config/chainSpecs.ts +++ b/src/config/chainSpecs.ts @@ -26,7 +26,7 @@ export const bridgeTestChains = [ intialFund: '50000000000000000', contractAddress: '0x3EC2839EcEAfa2Ce9e419718364B070563Db516e', chainType: 'evm', - lastBlock: 37159108, + lastBlock: 37274133, }, { chain: 'ETH', diff --git a/src/generic-test.ts b/src/generic-test.ts index fe382f5a..072f5cc9 100644 --- a/src/generic-test.ts +++ b/src/generic-test.ts @@ -23,6 +23,7 @@ import { getMultiversXBridgeContract, getStorageContract, getTezosBridgeContract, + getTonBridgeContract, waitForMSWithMsg, } from './utils'; import { @@ -40,6 +41,7 @@ import { getNftDetails, getSecretSignedNftDetails, getTezosSignedNftDetails, + getTonSignedNftDetails, } from './modules/validator/components/nftLockListener/utils'; import getSecretBridgeContract, { @@ -63,6 +65,10 @@ import { IMultiverseXLogEvent, IMultiverseXLogs, } from './modules/validator/utils/multiversXContractListener/utils/types'; +import { TezosClaimArgs } from './utils/functions/getTezosBridgeContract'; +import { tas } from './contractsTypes/tezosContractTypes/type-aliases'; + +import { WalletContractV4 } from 'ton'; (async () => { const genWallets = await generateWalletsForChains(); @@ -161,7 +167,7 @@ import { }, multiversx: { signer: UserSigner.fromWallet( - genWallets.multiversXWallet, + genWallets.multiversXWallet.userWallet, genWallets.multiversXWallet.password, ), config: configs.multiversx, @@ -223,6 +229,7 @@ import { const decodedLog = getMxLockEventDecodedLog({ log: log }); return decodedLog; } + throw new Error(`No Log Found`); }, }, eth: { @@ -300,24 +307,29 @@ import { } return payload! as LogObject; }, - cdMapper: (nftTransferDetailsObject: INftTransferDetailsObject) => { + cdMapper: ( + nftTransferDetailsObject: INftTransferDetailsObject, + ): TezosClaimArgs => { return { - token_id: nftTransferDetailsObject.tokenId, + token_id: tas.nat(nftTransferDetailsObject.tokenId), source_chain: nftTransferDetailsObject.sourceChain, dest_chain: nftTransferDetailsObject.destinationChain, - dest_address: + dest_address: tas.address( nftTransferDetailsObject.destinationUserAddress, + ), source_nft_contract_address: nftTransferDetailsObject.sourceNftContractAddress, name: nftTransferDetailsObject.name, symbol: nftTransferDetailsObject.symbol, - royalty: nftTransferDetailsObject.royalty, - royalty_receiver: nftTransferDetailsObject.royaltyReceiver, + royalty: tas.nat(nftTransferDetailsObject.royalty), + royalty_receiver: tas.address( + nftTransferDetailsObject.royaltyReceiver, + ), metadata: nftTransferDetailsObject.metadata, transaction_hash: nftTransferDetailsObject.transactionHash, - token_amount: nftTransferDetailsObject.tokenAmount, + token_amount: tas.nat(nftTransferDetailsObject.tokenAmount), nft_type: nftTransferDetailsObject.nftType, - fee: nftTransferDetailsObject.fee, + fee: tas.mutez(nftTransferDetailsObject.fee), }; }, }, @@ -412,52 +424,29 @@ import { }; }, }, - // ton: { - // signer: WalletContractV4.create({ - // publicKey: Buffer.from(genWallets.tonWallet.publicKey, 'hex'), - // workchain: 0, - // }), - - // bridge: getTonBridgeContract({ - // tonChainConfig: configs.ton, - // tonWallet: genWallets.tonWallet, - // }), - // config: configs.ton, - // logDecoder: (_log: LogObject) => {}, - // signedNftDetails: getTonSignedNftDetails, - // address: genWallets.tonWallet.publicKey, - // extractLogFromTx: async (_hash: string): Promise => { - // const client = new TonClient({ - // endpoint: configs.ton.rpcURL, - // apiKey: 'f3f6ef64352ac53cdfca18a3ba5372983e4037182c2b510fc52de5a259ecf292', - // }); - // const latestTx = await client.getTransactions( - // Address.parseFriendly(configs.ton.contractAddress).address, - // { limit: 1 }, - // ); - // if (!latestTx.length) { - // throw new Error('No Transactions found'); - // } - // const tx = latestTx[0]; + ton: { + signer: WalletContractV4.create({ + publicKey: Buffer.from(genWallets.tonWallet.publicKey, 'hex'), + workchain: 0, + }), - // const handleLog = getTonLockListenerHandler({ - // config: testnetBridgeConfig, - // tonChainConfig: configs.ton, - // wallets: genWallets, - // }); - // for (let i = 0; i < tx.outMessages.size; i++) { - // await handleLog({ - // log: tx.outMessages.get(i)!, - // hash: tx.hash().toString('base64'), - // }); - // } - // }, - // cdMapper: ( - // _nftTransferDetailsObject: INftTransferDetailsObject, - // ): ClaimData => { - // throw new Error('Not Implemented'); - // }, - // }, + bridge: getTonBridgeContract({ + tonChainConfig: configs.ton, + tonWallet: genWallets.tonWallet, + }), + config: configs.ton, + logDecoder: () => { + throw new Error('Not Implemented'); + }, + signedNftDetails: getTonSignedNftDetails, + address: genWallets.tonWallet.publicKey, + extractLogFromTx: async () => { + throw new Error('Not Implemented'); + }, + cdMapper: (): ClaimData => { + throw new Error('Not Implemented'); + }, + }, }; // Create a NFT Contract @@ -620,13 +609,25 @@ import { console.log(signatures); - const claimTx = await tx.toChain.bridge.claimNFT721( - tx.toChain.cdMapper(nftTransferDetailsObject) as unknown as any, - signatureArray, - ); - await claimTx.wait(); - - return claimTx.hash; + let claimed = false; + while (!claimed) + try { + const claimTx = await tx.toChain.bridge.claimNFT721( + tx.toChain.cdMapper( + nftTransferDetailsObject, + ) as unknown as any, + signatureArray, + ); + await claimTx.wait(); + console.log( + `Claimed on ${tx.toChain.config.chain} at ${claimTx.hash}`, + ); + claimed = true; + return claimTx.hash; + } catch (e) { + console.log(e); + console.log(`Retrying Claiming`); + } } return ''; } @@ -640,7 +641,9 @@ import { nftType: 'singular', }, ]); -})(); +})().catch((e) => { + console.error(e); +}); async function createNftOnEvm(signer: Wallet) { const contract = await new ERC721Royalty__factory(signer).deploy( diff --git a/src/utils/functions/getMultiversXBridgeContract.ts b/src/utils/functions/getMultiversXBridgeContract.ts index a84a4193..85acf258 100644 --- a/src/utils/functions/getMultiversXBridgeContract.ts +++ b/src/utils/functions/getMultiversXBridgeContract.ts @@ -336,22 +336,28 @@ const getMultiversXBridgeContract = ({ ]); const data = [ claimDataArgs, - [ - sigs.map((item) => { - return { - public_key: new AddressValue( - new Address(Buffer.from(item.signer, 'hex')), - ), - sig: new BytesValue( - Buffer.from(item.signature, 'hex'), + + sigs.map((item) => { + return { + public_key: new AddressValue( + new Address(Buffer.from(item.signer, 'hex')), + ), + sig: new BytesValue( + Buffer.from( + item.signature.replace('0x', ''), + 'hex', ), - }; - }), - ], + ), + }; + }), + VariadicValue.fromItems( new BytesValue( Buffer.from(nftTransferDetailsObject.metadata, 'utf-8'), ), + new BytesValue( + Buffer.from(nftTransferDetailsObject.metadata, 'utf-8'), + ), ), ]; const transaction = multiversXBridgeContract.methods diff --git a/src/utils/functions/getTezosBridgeContract.ts b/src/utils/functions/getTezosBridgeContract.ts index 219ee3a7..ed8fb7c2 100644 --- a/src/utils/functions/getTezosBridgeContract.ts +++ b/src/utils/functions/getTezosBridgeContract.ts @@ -87,63 +87,26 @@ const getTezosBridgeContract = ({ }; const bridge = await getBridgeInstance(); - console.log({ - dest_address: data.dest_address, - dest_chain: data.dest_chain, - fee: data.fee, - metadata: data.metadata, - name: data.name, - nft_type: data.nft_type, - royalty: data.royalty, - royalty_receiver: data.royalty_receiver, - source_chain: data.source_chain, - symbol: data.symbol, - token_amount: data.token_amount, - token_id: data.token_id, - transaction_hash: data.transaction_hash, - source_nft_contract_address: sourceNftContractAddress, - sigs: sigs.map((e) => { - console.log(e); - const addr = tas.address( - b58cencode( - hash( - new Uint8Array( - b58cdecode(e.signer, prefix.edpk), - ), - 20, - ), - prefix.tz1, - ), - ); - return { - addr, - sig: tas.signature( - Buffer.from( - e.signature.replace('0x', ''), - 'hex', - ).toString(), - ), - signer: tas.key(e.signer), - }; - }), - }); - const tx = await bridge.methodsObject .claim_nft({ - dest_address: data.dest_address, - dest_chain: data.dest_chain, - fee: data.fee, - metadata: data.metadata, - name: data.name, - nft_type: data.nft_type, - royalty: data.royalty, - royalty_receiver: data.royalty_receiver, - source_chain: data.source_chain, - symbol: data.symbol, - token_amount: data.token_amount, - token_id: data.token_id, - transaction_hash: data.transaction_hash, - source_nft_contract_address: sourceNftContractAddress, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + data: { + dest_address: data.dest_address, + dest_chain: data.dest_chain, + fee: data.fee, + metadata: data.metadata, + name: data.name, + nft_type: data.nft_type, + royalty: data.royalty, + royalty_receiver: data.royalty_receiver, + source_chain: data.source_chain, + symbol: data.symbol, + token_amount: data.token_amount, + token_id: tas.nat(data.token_id), + transaction_hash: data.transaction_hash, + source_nft_contract_address: sourceNftContractAddress, + }, sigs: sigs.map((e) => { console.log(e); const addr = tas.address( @@ -169,7 +132,11 @@ const getTezosBridgeContract = ({ }; }), }) - .send(); + .send({ + amount: data.fee.toNumber(), + mutez: true, + fee: data.fee.toNumber(), + }); return { hash: tx.hash, wait: async () => { From ddb577b5fd65ddf4f12879c05d6e707599e6fa4c Mon Sep 17 00:00:00 2001 From: imsk17 Date: Tue, 30 Jan 2024 18:06:49 +0530 Subject: [PATCH 15/19] Tests: Fix Ton Chain --- src/config/chainSpecs.ts | 2 +- src/generic-test.ts | 206 +++++++++++++++++++- src/utils/functions/getTonBridgeContract.ts | 16 +- 3 files changed, 208 insertions(+), 16 deletions(-) diff --git a/src/config/chainSpecs.ts b/src/config/chainSpecs.ts index cf5862c6..d4a96f2b 100644 --- a/src/config/chainSpecs.ts +++ b/src/config/chainSpecs.ts @@ -26,7 +26,7 @@ export const bridgeTestChains = [ intialFund: '50000000000000000', contractAddress: '0x3EC2839EcEAfa2Ce9e419718364B070563Db516e', chainType: 'evm', - lastBlock: 37274133, + lastBlock: 37302441, }, { chain: 'ETH', diff --git a/src/generic-test.ts b/src/generic-test.ts index 072f5cc9..410b9463 100644 --- a/src/generic-test.ts +++ b/src/generic-test.ts @@ -5,7 +5,7 @@ import { SecretNetworkClient, Wallet as SecretWallet } from 'secretjs'; import { InMemorySigner } from '@taquito/signer'; import { UserSigner } from '@multiversx/sdk-wallet/out'; import { keyPairFromSecretKey } from 'ton-crypto'; - +import { ClaimData as TonClaimData } from '@src/contractsTypes/contracts/tonBridge'; import { SupportedChains, bridgeTestChains, @@ -69,10 +69,15 @@ import { TezosClaimArgs } from './utils/functions/getTezosBridgeContract'; import { tas } from './contractsTypes/tezosContractTypes/type-aliases'; import { WalletContractV4 } from 'ton'; +import { Address, TonClient, beginCell } from '@ton/ton'; +import { loadLockedEvent } from './contractsTypes/contracts/tonBridge'; +import TonWeb from 'tonweb'; +import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePriceToGetTotalRoyalityPercentage'; (async () => { const genWallets = await generateWalletsForChains(); // Assuming we have enough funds on the validator accounts itself. + const signers = { bsc: new Wallet(genWallets.evmWallet.privateKey), eth: new Wallet(genWallets.evmWallet.privateKey), @@ -109,6 +114,21 @@ import { WalletContractV4 } from 'ton'; (e) => e.chain === 'TON', )! as ITonChainConfig, }; + const tonweb = new TonWeb(new TonWeb.HttpProvider(configs.ton.rpcURL)); + + const walletClass = tonweb.wallet.all['v4R2']; + + const wallet = new walletClass(tonweb.provider, { + publicKey: TonWeb.utils.hexToBytes(genWallets.tonWallet.publicKey), + }); + console.log((await wallet.getAddress()).toString(true)); + // await new Wallet( + // '1f74ccfcfa2387a2a9a3fd65034d39fcbae72a59e366b48f437fa1822fce6d0d', + // new JsonRpcProvider(configs.bsc.rpcURL), + // ).sendTransaction({ + // to: genWallets.evmWallet.address, + // value: '500000000000000000', + // }); const storage = getStorageContract({ evmChainConfig: testnetBridgeConfig.storageConfig, evmWallet: genWallets.evmWallet, @@ -435,16 +455,167 @@ import { WalletContractV4 } from 'ton'; tonWallet: genWallets.tonWallet, }), config: configs.ton, - logDecoder: () => { - throw new Error('Not Implemented'); + logDecoder: (data: any) => { + const { + token_id: tokenId, // Unique ID for the NFT transfer + dest_chain: destinationChain, // Chain to where the NFT is being transferred + dest_address: destinationUserAddress, // User's address in the destination chain + token_amount: tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) + nft_type: nftType, // Sigular or multiple ( 721 / 1155) + source_chain: sourceChain, // Source chain of NFT + transaction_hash: transactionHash, + source_nft_address: sourceNftContractAddress, + } = data; + return { + tokenId, + destinationChain, + destinationUserAddress, + tokenAmount, + nftType, + sourceChain, + transactionHash, + sourceNftContractAddress, + }; }, signedNftDetails: getTonSignedNftDetails, address: genWallets.tonWallet.publicKey, extractLogFromTx: async () => { - throw new Error('Not Implemented'); + const client = new TonClient({ + endpoint: configs.ton.rpcURL, + apiKey: 'f3f6ef64352ac53cdfca18a3ba5372983e4037182c2b510fc52de5a259ecf292', + }); + const latestTx = await client.getTransactions( + Address.parseFriendly(configs.ton.contractAddress).address, + { limit: 1 }, + ); + for (const tx of latestTx) { + for (let i = 0; i < tx.outMessages.size; i++) { + const log = tx.outMessages.get(i)!; + const hash = tx.hash().toString('base64'); + if (log.body.asSlice().loadUint(32) !== 3571773646) { + return; + } + const { + tokenId, // Unique ID for the NFT transfer + destinationChain, // Chain to where the NFT is being transferred + destinationUserAddress, // User's address in the destination chain + sourceNftContractAddress, // Address of the NFT contract in the source chain + tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) + nftType, // Sigular or multiple ( 721 / 1155) + sourceChain, // Source chain of NFT + } = loadLockedEvent(log.body.asSlice()); + const getSourceNftContractAddress = () => { + try { + return sourceNftContractAddress + .asSlice() + .loadAddress() + .toString(); + } catch (e) { + return sourceNftContractAddress + .asSlice() + .loadStringTail(); + } + }; + + const nftTransferDetailsObject = { + tokenId: tokenId.toString(), + sourceChain, + destinationChain, + destinationUserAddress, + sourceNftContractAddress: + getSourceNftContractAddress(), + tokenAmount: tokenAmount.toString(), + nftType, + transactionHash: hash, + }; + return nftTransferDetailsObject! as LogObject; + } + } + throw new Error(`No Log Found`); }, - cdMapper: (): ClaimData => { - throw new Error('Not Implemented'); + cdMapper: (d: INftTransferDetailsObject): ClaimData => { + // Mitigation if destination user address is invalid + let destinationAddress: Address; + try { + destinationAddress = Address.parseFriendly( + d.destinationUserAddress, + ).address; + } catch (e) { + destinationAddress = Address.parseFriendly( + d.royaltyReceiver, + ).address; + } + + // off chain condition to store sourceNftContractAddress as string if not native, and address if native + let sourceNftContractAddress_ = beginCell() + .storeSlice( + beginCell() + .storeStringTail(d.sourceNftContractAddress) + .endCell() + .asSlice(), + ) + .endCell(); + try { + sourceNftContractAddress_ = beginCell() + .storeSlice( + beginCell() + .storeAddress( + Address.parseFriendly( + d.sourceNftContractAddress, + ).address, + ) + .endCell() + .asSlice(), + ) + .endCell(); + } catch (e) { + console.log('Not Native TON Address'); + } + const data = { + $$type: 'ClaimData', + data1: { + $$type: 'ClaimData1', + destinationChain: d.destinationChain, + destinationUserAddress: destinationAddress, + tokenId: BigInt(d.tokenId), + sourceChain: d.sourceChain, + tokenAmount: BigInt(d.tokenAmount), + }, + data2: { + $$type: 'ClaimData2', + name: d.name, + symbol: d.symbol, + nftType: d.nftType, + }, + data3: { + $$type: 'ClaimData3', + fee: BigInt(d.fee), + metadata: d.metadata, + royaltyReceiver: Address.parseFriendly( + d.royaltyReceiver, + ).address, + sourceNftContractAddress: sourceNftContractAddress_, + }, + data4: { + $$type: 'ClaimData4', + royalty: { + $$type: 'RoyaltyParams', + numerator: BigInt( + SalePriceToGetTotalRoyalityPercentage, + ), + denominator: BigInt(d.royalty), + destination: Address.parseFriendly( + d.royaltyReceiver, + ).address, + }, + transactionHash: d.transactionHash, + newContent: beginCell() + .storeInt(0x01, 8) + .storeStringRefTail(d.metadata) + .endCell(), + }, + } satisfies TonClaimData; + return data as any; }, }, }; @@ -523,8 +694,25 @@ import { WalletContractV4 } from 'ton'; ], ) { for (const tx of args) { + let wallet: any; + if (tx.toChain.config.chain === 'TON') { + const tonweb = new TonWeb( + new TonWeb.HttpProvider(configs.ton.rpcURL), + ); + + const walletClass = tonweb.wallet.all['v4R2']; + + wallet = new walletClass(tonweb.provider, { + publicKey: TonWeb.utils.hexToBytes( + genWallets.tonWallet.publicKey, + ), + }); + } const from = await tx.fromChain.bridge.lock721({ - address: tx.toChain.address, + address: + tx.toChain.config.chain === 'TON' + ? (await wallet.getAddress()).toString() + : tx.toChain.address, destinationChain: tx.toChain.config.chain as SupportedChains, sourceNftContractAddress: tx.contractAddress, tokenId: tx.tokenId, @@ -546,7 +734,7 @@ import { WalletContractV4 } from 'ton'; nftType, // Sigular or multiple ( 721 / 1155) sourceChain, // Source chain of NFT } = tx.fromChain.logDecoder({ - log: log, + log: log!, })!; // if user gives a destination chain which is not registered with us, we early return @@ -635,7 +823,7 @@ import { WalletContractV4 } from 'ton'; await transfer([ { fromChain: data.bsc, - toChain: data.tezos, + toChain: data.ton, contractAddress: await contract!.getAddress(), tokenId: '1', nftType: 'singular', diff --git a/src/utils/functions/getTonBridgeContract.ts b/src/utils/functions/getTonBridgeContract.ts index e6f2a222..f61fd3da 100644 --- a/src/utils/functions/getTonBridgeContract.ts +++ b/src/utils/functions/getTonBridgeContract.ts @@ -72,24 +72,28 @@ const getTonBridgeContract = ({ const sigs: SignerAndSignature[] = sigsA.map((e) => { return { $$type: 'SignerAndSignature', - key: BigInt(e.signer), + key: BigInt(`0x${e.signer}`), signature: beginCell() - .storeBuffer(Buffer.from(e.signature, 'hex')) + .storeBuffer( + Buffer.from(e.signature.replace('0x', ''), 'hex'), + ) .endCell(), }; }); - const dictA = Dictionary.empty(); - sigs.forEach((item, index) => dictA.set(BigInt(index), item)); + let dictA = Dictionary.empty(); + sigs.forEach( + (item, index) => (dictA = dictA.set(BigInt(index), item)), + ); await bridge.send( walletSender, { - value: toNano('0.8'), + value: toNano(claimData.data3.fee), }, { $$type: 'ClaimNFT721', data: claimData, - len: 1n, signatures: dictA, + len: BigInt(sigs.length), }, ); return { hash: 'No Tx Hash', wait: async () => {} }; From 00a3c1a8c7545024615a7f51b9858422d2df59b2 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Tue, 30 Jan 2024 21:05:01 +0530 Subject: [PATCH 16/19] Tests: Require money before running the tests --- src/generic-test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/generic-test.ts b/src/generic-test.ts index 410b9463..a4ee6bb7 100644 --- a/src/generic-test.ts +++ b/src/generic-test.ts @@ -73,9 +73,20 @@ import { Address, TonClient, beginCell } from '@ton/ton'; import { loadLockedEvent } from './contractsTypes/contracts/tonBridge'; import TonWeb from 'tonweb'; import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePriceToGetTotalRoyalityPercentage'; +import { promptToGetFunding } from './modules/setup/components/getInitialFunds/components'; (async () => { const genWallets = await generateWalletsForChains(); + + let result = false; + + while (!result) { + result = await promptToGetFunding({ + wallets: genWallets, + config: testnetBridgeConfig, + }); + } + // Assuming we have enough funds on the validator accounts itself. const signers = { @@ -107,6 +118,7 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri multiversx: bridgeTestChains.find( (e) => e.chain === 'MULTIVERSX', )! as IMultiversXChainConfig, + secret: bridgeTestChains.find( (e) => e.chain === 'SECRET', )! as ISecretChainConfig, From f2e48dc3b3afbc832eadb65c9325318f962677f3 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Wed, 31 Jan 2024 17:48:11 +0530 Subject: [PATCH 17/19] Tests: Secret Fixes --- package.json | 3 +- src/config/chainSpecs.ts | 8 +-- src/generic-test.ts | 31 ++++------ .../functions/getSecretBridgeContract.ts | 57 ++++++++++++++----- yarn.lock | 15 +++-- 5 files changed, 71 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index 6699b353..578dec4f 100644 --- a/package.json +++ b/package.json @@ -59,11 +59,12 @@ "libsodium-wrappers-sumo": "^0.7.13", "mocha": "^10.2.0", "reflect-metadata": "^0.1.13", - "secretjs": "^1.12.3", + "secretjs": "=1.12.3", "sinon": "^17.0.0", "sqlite": "^5.0.1", "sqlite3": "^5.1.6", "ton": "^13.9.0", + "ton-core": "^0.53.0", "ton-crypto": "^3.2.0", "tonweb": "^0.0.62", "tsconfig-paths": "^4.2.0", diff --git a/src/config/chainSpecs.ts b/src/config/chainSpecs.ts index d4a96f2b..96799034 100644 --- a/src/config/chainSpecs.ts +++ b/src/config/chainSpecs.ts @@ -26,7 +26,7 @@ export const bridgeTestChains = [ intialFund: '50000000000000000', contractAddress: '0x3EC2839EcEAfa2Ce9e419718364B070563Db516e', chainType: 'evm', - lastBlock: 37302441, + lastBlock: 37330160, }, { chain: 'ETH', @@ -69,13 +69,13 @@ export const bridgeTestChains = [ }, { chain: 'SECRET', - rpcURL: 'https://pulsar.api.trivium.network:1317', + rpcURL: 'https://lcd.pulsar-3.secretsaturn.net', nativeCoinSymbol: 'USCRT', intialFund: '50000', - contractAddress: 'secret1jcfm9ct9jdy9uugcnfnjzpv4eydaj620kuvulp', + contractAddress: 'secret1uxthnjt74cny9wnwx8czmgrc8taz0r8yfas565', chainType: 'scrt', chainId: 'pulsar-3', - lastBlock: 50883, + lastBlock: 3223704, }, { chain: 'TEZOS', diff --git a/src/generic-test.ts b/src/generic-test.ts index a4ee6bb7..c1716bd1 100644 --- a/src/generic-test.ts +++ b/src/generic-test.ts @@ -45,7 +45,7 @@ import { } from './modules/validator/components/nftLockListener/utils'; import getSecretBridgeContract, { - ClaimData, + SecretClaimData, CodeInfo, } from './utils/functions/getSecretBridgeContract'; import { getLockEventDecodedLog as getMxLockEventDecodedLog } from './modules/validator/components/nftLockListener/components/multiversXLockListener/utils'; @@ -73,19 +73,19 @@ import { Address, TonClient, beginCell } from '@ton/ton'; import { loadLockedEvent } from './contractsTypes/contracts/tonBridge'; import TonWeb from 'tonweb'; import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePriceToGetTotalRoyalityPercentage'; -import { promptToGetFunding } from './modules/setup/components/getInitialFunds/components'; +// import { promptToGetFunding } from './modules/setup/components/getInitialFunds/components'; (async () => { const genWallets = await generateWalletsForChains(); - let result = false; + // let result = false; - while (!result) { - result = await promptToGetFunding({ - wallets: genWallets, - config: testnetBridgeConfig, - }); - } + // while (!result) { + // result = await promptToGetFunding({ + // wallets: genWallets, + // config: testnetBridgeConfig, + // }); + // } // Assuming we have enough funds on the validator accounts itself. @@ -134,13 +134,6 @@ import { promptToGetFunding } from './modules/setup/components/getInitialFunds/c publicKey: TonWeb.utils.hexToBytes(genWallets.tonWallet.publicKey), }); console.log((await wallet.getAddress()).toString(true)); - // await new Wallet( - // '1f74ccfcfa2387a2a9a3fd65034d39fcbae72a59e366b48f437fa1822fce6d0d', - // new JsonRpcProvider(configs.bsc.rpcURL), - // ).sendTransaction({ - // to: genWallets.evmWallet.address, - // value: '500000000000000000', - // }); const storage = getStorageContract({ evmChainConfig: testnetBridgeConfig.storageConfig, evmWallet: genWallets.evmWallet, @@ -434,7 +427,7 @@ import { promptToGetFunding } from './modules/setup/components/getInitialFunds/c }, cdMapper: ( nftTransferDetailsObject: INftTransferDetailsObject, - ): ClaimData => { + ): SecretClaimData => { return { token_id: nftTransferDetailsObject.tokenId, source_chain: nftTransferDetailsObject.sourceChain, @@ -545,7 +538,7 @@ import { promptToGetFunding } from './modules/setup/components/getInitialFunds/c } throw new Error(`No Log Found`); }, - cdMapper: (d: INftTransferDetailsObject): ClaimData => { + cdMapper: (d: INftTransferDetailsObject): TonClaimData => { // Mitigation if destination user address is invalid let destinationAddress: Address; try { @@ -835,7 +828,7 @@ import { promptToGetFunding } from './modules/setup/components/getInitialFunds/c await transfer([ { fromChain: data.bsc, - toChain: data.ton, + toChain: data.secret, contractAddress: await contract!.getAddress(), tokenId: '1', nftType: 'singular', diff --git a/src/utils/functions/getSecretBridgeContract.ts b/src/utils/functions/getSecretBridgeContract.ts index cb48cc6c..9280473c 100644 --- a/src/utils/functions/getSecretBridgeContract.ts +++ b/src/utils/functions/getSecretBridgeContract.ts @@ -1,8 +1,11 @@ import { SupportedChains } from '@src/config/chainSpecs'; import { AddValidatorType } from '@src/contractsTypes/contracts/secretBridge'; import { IBridge, ISecretChainConfigAndSecretWallet } from '@src/types'; -import { SecretNetworkClient, pubkeyToAddress } from 'secretjs'; -import { encodeSecp256k1Pubkey } from 'secretjs/dist/wallet_amino'; +import { SecretNetworkClient, Wallet, pubkeyToAddress } from 'secretjs'; +import { + encodeSecp256k1Pubkey, + encodeSecp256k1Signature, +} from 'secretjs/dist/wallet_amino'; export type CodeInfo = { code_id: number; @@ -17,7 +20,7 @@ export type SecretLockArgs = { tokenId: string; }; -export type ClaimData = { +export type SecretClaimData = { token_id: string; source_chain: string; destination_chain: string; @@ -37,13 +40,22 @@ export type ClaimData = { const getSecretBridgeContract = ({ secretChainConfig, secretWallet, -}: ISecretChainConfigAndSecretWallet): IBridge => { - const bridgeContractCodeHash = - 'dbccb5a7abf668d050d720cd01ea39d556492456ceb870dcae80dc4ff8572575'; +}: ISecretChainConfigAndSecretWallet): IBridge< + SecretLockArgs, + SecretClaimData +> => { + const wallet = new Wallet(secretWallet.privateKey); const secretjs = new SecretNetworkClient({ url: secretChainConfig.rpcURL, chainId: secretChainConfig.chainId, + wallet: wallet, + walletAddress: wallet.address, }); + console.log(wallet.address); + const bridgeContractCodeHash = + secretjs.query.compute.codeHashByContractAddress({ + contract_address: secretChainConfig.contractAddress, + }); return { lock721: async ({ @@ -68,7 +80,7 @@ const getSecretBridgeContract = ({ }, }, }, - code_hash: bridgeContractCodeHash, + code_hash: (await bridgeContractCodeHash).code_hash, sender: secretjs.address, }, { @@ -77,20 +89,34 @@ const getSecretBridgeContract = ({ ); return { hash: tx.transactionHash, wait: async () => {} }; }, - claimNFT721: async (data, sigs) => { + claimNFT721: async (data, signatures) => { const claim721 = { claim721: { data: { data, - signatures: sigs, + signatures: signatures.map((e) => { + return { + signature: encodeSecp256k1Signature( + Buffer.from(secretWallet.publicKey, 'hex'), + Buffer.from( + e.signature.replace('0x', ''), + 'hex', + ), + ).signature, + signer_address: encodeSecp256k1Pubkey( + Buffer.from(secretWallet.publicKey, 'hex'), + ).value, + }; + }), }, }, }; + console.log(JSON.stringify(claim721)); const tx = await secretjs.tx.compute.executeContract( { contract_address: secretChainConfig.contractAddress, msg: claim721, - code_hash: bridgeContractCodeHash, + code_hash: (await bridgeContractCodeHash).code_hash, sender: secretjs.address, sent_funds: [ { amount: data.fee.toString(), denom: 'uscrt' }, @@ -100,6 +126,7 @@ const getSecretBridgeContract = ({ gasLimit: 300_000, }, ); + console.log(tx); return { hash: tx.transactionHash, wait: async () => {} }; }, async lock1155({ @@ -121,7 +148,7 @@ const getSecretBridgeContract = ({ token_id: tokenId, token_amount: amt.toString(), }, - code_hash: bridgeContractCodeHash, + code_hash: (await bridgeContractCodeHash).code_hash, sender: secretjs.address, }, { @@ -144,7 +171,7 @@ const getSecretBridgeContract = ({ { contract_address: secretChainConfig.contractAddress, msg: claim721, - code_hash: bridgeContractCodeHash, + code_hash: (await bridgeContractCodeHash).code_hash, sender: secretjs.address, sent_funds: [{ amount: '1', denom: 'uscrt' }], }, @@ -157,7 +184,7 @@ const getSecretBridgeContract = ({ validators: async (address: string) => { const res = (await secretjs.query.compute.queryContract({ contract_address: secretChainConfig.contractAddress, - code_hash: bridgeContractCodeHash, + code_hash: (await bridgeContractCodeHash).code_hash, query: { get_validator: { address: Buffer.from(address, 'hex').toString('base64'), @@ -169,7 +196,7 @@ const getSecretBridgeContract = ({ validatorsCount: async () => { const res = (await secretjs.query.compute.queryContract({ contract_address: secretChainConfig.contractAddress, - code_hash: bridgeContractCodeHash, + code_hash: (await bridgeContractCodeHash).code_hash, query: { get_validators_count: {}, }, @@ -212,7 +239,7 @@ const getSecretBridgeContract = ({ { contract_address: secretChainConfig.contractAddress, msg, - code_hash: bridgeContractCodeHash, + code_hash: (await bridgeContractCodeHash).code_hash, sender: pubkeyToAddress( Buffer.from(secretWallet.publicKey, 'hex'), ), diff --git a/yarn.lock b/yarn.lock index d5c32ad2..f1236ec4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5834,10 +5834,10 @@ secp256k1@^4.0.1: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -secretjs@^1.12.3: - version "1.12.4" - resolved "https://registry.yarnpkg.com/secretjs/-/secretjs-1.12.4.tgz#0bc1930137a936246e976481808b129d12d7af9d" - integrity sha512-DH16hYTPa4NNxo1T/tY2GyJRte7rgp5kRy8k1pwaPK59WtbQdTBdPQQsEI2L5T7NDVEUXbdbTqyQkt5usN4KcQ== +secretjs@=1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/secretjs/-/secretjs-1.12.3.tgz#45bdbfe7c37f59e02aba4d9c88b9bcb5a212d34d" + integrity sha512-zvvllDGU4f/nrgYCqDFahZHlzPqwaNW1GWkvSaedidWDvOI9TB4/WEbz6ODLIM/OQnqD4K8sp5HVgDxP7Cl+nQ== dependencies: "@cosmjs/encoding" "0.27.1" "@cosmjs/math" "0.27.1" @@ -6325,6 +6325,13 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +ton-core@^0.53.0: + version "0.53.0" + resolved "https://registry.yarnpkg.com/ton-core/-/ton-core-0.53.0.tgz#88ce0c0dbdbb548cd46f1984639c4738b06f38dd" + integrity sha512-uO/U1oVLdEliWWbwfNQQK+61C+KM0ehcTdHQ6cN0WSEH2UzGfdVFpC4Wb0ph+wUYe/5njl7TA0uL9nif9Q6qwA== + dependencies: + symbol.inspect "1.0.1" + ton-crypto-primitives@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ton-crypto-primitives/-/ton-crypto-primitives-2.0.0.tgz#e85cd68c0d523f6bdf3f306201a76e51b7e9312e" From 9ad03622779534c735b4f1560e708af29acdb2f6 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Mon, 12 Feb 2024 19:53:11 +0530 Subject: [PATCH 18/19] Generic-Test: Use XP Sdk for claiming and locking --- package.json | 3 +- src/config/chainSpecs.ts | 22 +- src/generic-test.ts | 262 +++++++++++++---------- yarn.lock | 440 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 597 insertions(+), 130 deletions(-) diff --git a/package.json b/package.json index 578dec4f..64d73e9c 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "tsconfig-paths": "^4.2.0", "typeorm": "0.3.17", "web3": "^4.1.2", - "web3-core": "^4.2.0" + "web3-core": "^4.2.0", + "xp-decentralized-sdk": "git+https://github.com/XP-NETWORK/xp-decentralized-client-library#bleeding-edge" } } diff --git a/src/config/chainSpecs.ts b/src/config/chainSpecs.ts index 96799034..2540e8b0 100644 --- a/src/config/chainSpecs.ts +++ b/src/config/chainSpecs.ts @@ -26,7 +26,7 @@ export const bridgeTestChains = [ intialFund: '50000000000000000', contractAddress: '0x3EC2839EcEAfa2Ce9e419718364B070563Db516e', chainType: 'evm', - lastBlock: 37330160, + lastBlock: 37679066, }, { chain: 'ETH', @@ -87,16 +87,16 @@ export const bridgeTestChains = [ nativeCoinSymbol: 'XTZ', chainType: 'tezos', }, - { - chain: 'HEDERA', - rpcURL: 'https://testnet.hashio.io/api', - nativeCoinSymbol: 'HBAR', - intialFund: '50000000000000000', - contractAddress: '0x742f68F53583Be22a62338e916eB8DE90D07daB1', - chainType: 'hedera', - lastBlock: 7095475, - royaltyInfoProxyAddress: '0x870f7b68c0a64733dcF4D95E5C06aa34387B98BF', - }, + // { + // chain: 'HEDERA', + // rpcURL: 'https://testnet.hashio.io/api', + // nativeCoinSymbol: 'HBAR', + // intialFund: '50000000000000000', + // contractAddress: '0x742f68F53583Be22a62338e916eB8DE90D07daB1', + // chainType: 'hedera', + // lastBlock: 7095475, + // royaltyInfoProxyAddress: '0x870f7b68c0a64733dcF4D95E5C06aa34387B98BF', + // }, ] as const satisfies readonly TChain[]; const stakingTestChain: IStakingConfig = { diff --git a/src/generic-test.ts b/src/generic-test.ts index c1716bd1..36b21bac 100644 --- a/src/generic-test.ts +++ b/src/generic-test.ts @@ -6,11 +6,7 @@ import { InMemorySigner } from '@taquito/signer'; import { UserSigner } from '@multiversx/sdk-wallet/out'; import { keyPairFromSecretKey } from 'ton-crypto'; import { ClaimData as TonClaimData } from '@src/contractsTypes/contracts/tonBridge'; -import { - SupportedChains, - bridgeTestChains, - testnetBridgeConfig, -} from './config/chainSpecs'; +import { bridgeTestChains, testnetBridgeConfig } from './config/chainSpecs'; import { Bridge__factory, ERC721Royalty, @@ -19,7 +15,7 @@ import { import { getEvmBridgeContract, getEvmSingleNftContract, - getHederaBridgeContract, + // getHederaBridgeContract, getMultiversXBridgeContract, getStorageContract, getTezosBridgeContract, @@ -28,7 +24,7 @@ import { } from './utils'; import { IEvmChainConfig, - IHederaChainConfig, + // IHederaChainConfig, IMultiversXChainConfig, ISecretChainConfig, ITezosChainConfig, @@ -38,7 +34,6 @@ import { import { getEvmSignedNftDetails, getMultiversXSignedNftDetails, - getNftDetails, getSecretSignedNftDetails, getTezosSignedNftDetails, getTonSignedNftDetails, @@ -61,6 +56,11 @@ import { TezosToolkit } from '@taquito/taquito'; import { INftTransferDetailsObject } from './modules/validator/components/nftLockListener/components/types'; import { ClaimStruct } from './utils/functions/getMultiversXBridgeContract'; import axios from 'axios'; +import { + ChainFactory, + ChainFactoryConfigs, + MetaMap, +} from 'xp-decentralized-sdk'; import { IMultiverseXLogEvent, IMultiverseXLogs, @@ -77,6 +77,7 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri (async () => { const genWallets = await generateWalletsForChains(); + const factory = ChainFactory(ChainFactoryConfigs.TestNet()); // let result = false; @@ -109,9 +110,9 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri eth: bridgeTestChains.find( (e) => e.chain === 'ETH', )! as IEvmChainConfig, - hedera: bridgeTestChains.find( - (e) => e.chain === 'HEDERA', - )! as IHederaChainConfig, + // hedera: bridgeTestChains.find( + // (e) => e.chain === 'HEDERA', + // )! as IHederaChainConfig, tezos: bridgeTestChains.find( (e) => e.chain === 'TEZOS', )! as ITezosChainConfig, @@ -141,7 +142,10 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri const data = { bsc: { - signer: new Wallet(genWallets.evmWallet.privateKey), + signer: new Wallet( + genWallets.evmWallet.privateKey, + new JsonRpcProvider(configs.bsc.rpcURL), + ), bridge: getEvmBridgeContract({ evmChainConfig: configs.bsc, evmWallet: genWallets.evmWallet, @@ -165,31 +169,31 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri return cd; }, }, - hedera: { - signer: new Wallet(genWallets.evmWallet.privateKey), - bridge: getHederaBridgeContract({ - hederaChainConfig: configs.hedera, - evmWallet: genWallets.evmWallet, - }), - config: configs.hedera, - logDecoder: getLockEventDecodedLog, - signedNftDetails: getEvmSignedNftDetails, - address: genWallets.evmWallet.address, - extractLogFromTx: async (hash: string): Promise => { - const { topicHash } = - Bridge__factory.createInterface().getEvent('Locked'); - const provider = new JsonRpcProvider(configs.bsc.rpcURL); - const receipt = await provider.getTransactionReceipt(hash)!; - - return (receipt?.logs.filter( - (e) => e.topics.includes(topicHash), - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ) ?? [])[0] as unknown as any; - }, - cdMapper: (cd: INftTransferDetailsObject) => { - return cd; - }, - }, + // hedera: { + // signer: new Wallet(genWallets.evmWallet.privateKey), + // bridge: getHederaBridgeContract({ + // hederaChainConfig: configs.hedera, + // evmWallet: genWallets.evmWallet, + // }), + // config: configs.hedera, + // logDecoder: getLockEventDecodedLog, + // signedNftDetails: getEvmSignedNftDetails, + // address: genWallets.evmWallet.address, + // extractLogFromTx: async (hash: string): Promise => { + // const { topicHash } = + // Bridge__factory.createInterface().getEvent('Locked'); + // const provider = new JsonRpcProvider(configs.bsc.rpcURL); + // const receipt = await provider.getTransactionReceipt(hash)!; + + // return (receipt?.logs.filter( + // (e) => e.topics.includes(topicHash), + // // eslint-disable-next-line @typescript-eslint/no-explicit-any + // ) ?? [])[0] as unknown as any; + // }, + // cdMapper: (cd: INftTransferDetailsObject) => { + // return cd; + // }, + // }, multiversx: { signer: UserSigner.fromWallet( genWallets.multiversXWallet.userWallet, @@ -258,7 +262,10 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri }, }, eth: { - signer: new Wallet(genWallets.evmWallet.privateKey), + signer: new Wallet( + genWallets.evmWallet.privateKey, + new JsonRpcProvider(configs.eth.rpcURL), + ), bridge: getEvmBridgeContract({ evmChainConfig: configs.eth, evmWallet: genWallets.evmWallet, @@ -644,7 +651,7 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri } // Mint 5 NFT on the contract - for (let i = 0; i < 2; i++) { + for (let i = 0; i < 1; i++) { let minted = false; while (!minted) { try { @@ -661,7 +668,7 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri } } } - console.log('Minted 2 NFTs ON BSC'); + console.log('Minted 1 NFTs ON BSC'); // Approve the contract to spend the NFTs const nftC = getEvmSingleNftContract( @@ -671,14 +678,17 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri }, data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), ); - for (let i = 0; i < 2; i++) { + for (let i = 0; i < 1; i++) { let approved = false; while (!approved) { try { await nftC.approve(BigInt(i), data.bsc.config.contractAddress); approved = true; - } catch (e) { - console.log(`Retrying to approve NFT on BSC`); + } catch (e: any) { + console.log( + `Retrying to approve NFT on BSC`, + console.log(e.shortMessage), + ); } } } @@ -713,68 +723,94 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri ), }); } - const from = await tx.fromChain.bridge.lock721({ - address: - tx.toChain.config.chain === 'TON' - ? (await wallet.getAddress()).toString() - : tx.toChain.address, - destinationChain: tx.toChain.config.chain as SupportedChains, - sourceNftContractAddress: tx.contractAddress, - tokenId: tx.tokenId, - nonce: tx.nonce!, - collectionCodeInfo: tx.codeInfo!, - }); - await from.wait(); - console.log(`Locked on ${tx.fromChain.config.chain} ${from.hash}`); - - await new Promise((e) => setTimeout(e, 10000)); - - const log = await tx.fromChain.extractLogFromTx(from.hash); - const { - tokenId, // Unique ID for the NFT transfer - destinationChain, // Chain to where the NFT is being transferred - destinationUserAddress, // User's address in the destination chain - sourceNftContractAddress, // Address of the NFT contract in the source chain - tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) - nftType, // Sigular or multiple ( 721 / 1155) - sourceChain, // Source chain of NFT - } = tx.fromChain.logDecoder({ - log: log!, - })!; - - // if user gives a destination chain which is not registered with us, we early return - const sourceChain_ = tx.fromChain.config; - - const fee = String(await storage.chainFee(tx.toChain.config.chain)); // Required fee for claming nft on target chain - const royaltyReceiver = String( - await storage.chainRoyalty(tx.toChain.config.chain), + + const chain = await factory.inner( + tx.fromChain.config.chain as keyof MetaMap, ); + let locked = false; + let lockHash: string = ''; + while (!locked) { + try { + const lock = await chain.lockNft( + tx.fromChain.signer as any, + tx.contractAddress, + tx.toChain.config.chain as keyof MetaMap, + tx.toChain.config.chain === 'TON' + ? (await wallet.getAddress()).toString() + : tx.toChain.address, + BigInt(tx.tokenId), + { gasLimit: 1000000 }, + ); + console.log(`Lock Hash:`, lock.hash()); + await (lock.tx as any).wait(); + locked = true; + lockHash = lock.hash(); + } catch (e: any) { + console.log( + `Retrying to lock NFT on ${tx.fromChain.config.chain}`, + e.shortMessage, + ); + } + } - const { royalty, name, symbol, metadata } = await getNftDetails({ - sourceNftContractAddress, - sourceChain: sourceChain_, - tokenId, - nftType, - }); + // console.log(`Locked on ${tx.fromChain.config.chain} ${lock.hash()}`); + + // await new Promise((e) => setTimeout(e, 10000)); + + // const log = await tx.fromChain.extractLogFromTx(lock.hash()); + // const { + // tokenId, // Unique ID for the NFT transfer + // destinationChain, // Chain to where the NFT is being transferred + // destinationUserAddress, // User's address in the destination chain + // sourceNftContractAddress, // Address of the NFT contract in the source chain + // tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) + // nftType, // Sigular or multiple ( 721 / 1155) + // sourceChain, // Source chain of NFT + // } = tx.fromChain.logDecoder({ + // log: log!, + // })!; + + // // if user gives a destination chain which is not registered with us, we early return + // const sourceChain_ = tx.fromChain.config; + + // const fee = String(await storage.chainFee(tx.toChain.config.chain)); // Required fee for claming nft on target chain + // const royaltyReceiver = String( + // await storage.chainRoyalty(tx.toChain.config.chain), + // ); + + // const { royalty, name, symbol, metadata } = await getNftDetails({ + // sourceNftContractAddress, + // sourceChain: sourceChain_, + // tokenId, + // nftType, + // }); + + // const nftTransferDetailsObject = { + // tokenId, + // sourceChain, + // destinationChain, + // destinationUserAddress, + // sourceNftContractAddress, + // name, + // symbol, + // royalty, + // royaltyReceiver, + // metadata, + // transactionHash: lock.hash(), + // tokenAmount, + // nftType, + // fee, + // }; + console.log(`Finding Claim Data for Lock Hash: ${lockHash}`); + + const nftDetails = await factory.getClaimData(chain, lockHash); + console.log(nftDetails); + console.log(`Got Claim Data`); + + console.log(`Fetching Signatures`); - const nftTransferDetailsObject = { - tokenId, - sourceChain, - destinationChain, - destinationUserAddress, - sourceNftContractAddress, - name, - symbol, - royalty, - royaltyReceiver, - metadata, - transactionHash: from.hash, - tokenAmount, - nftType, - fee, - }; let signatures = await storage.getLockNftSignatures( - from.hash, + lockHash, tx.fromChain.config.chain, ); const neededSignatures = @@ -787,7 +823,7 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri `waiting for signatures, ${signatures.length}`, ); signatures = await storage.getLockNftSignatures( - from.hash, + lockHash, tx.fromChain.config.chain, ); } @@ -805,18 +841,20 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri let claimed = false; while (!claimed) try { - const claimTx = await tx.toChain.bridge.claimNFT721( - tx.toChain.cdMapper( - nftTransferDetailsObject, - ) as unknown as any, + const tc = await factory.inner( + tx.toChain.config.chain as keyof MetaMap, + ); + const claim = await tc.claimNft( + tx.toChain.signer as any, + tc.transform(nftDetails) as any, + {}, signatureArray, ); - await claimTx.wait(); console.log( - `Claimed on ${tx.toChain.config.chain} at ${claimTx.hash}`, + `Claimed on ${tx.toChain.config.chain} at ${claim}`, ); claimed = true; - return claimTx.hash; + return ''; } catch (e) { console.log(e); console.log(`Retrying Claiming`); @@ -828,9 +866,9 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri await transfer([ { fromChain: data.bsc, - toChain: data.secret, + toChain: data.eth, contractAddress: await contract!.getAddress(), - tokenId: '1', + tokenId: '0', nftType: 'singular', }, ]); @@ -838,7 +876,7 @@ import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePri console.error(e); }); -async function createNftOnEvm(signer: Wallet) { +export async function createNftOnEvm(signer: Wallet) { const contract = await new ERC721Royalty__factory(signer).deploy( 'TestContract', 'TC', diff --git a/yarn.lock b/yarn.lock index f1236ec4..17bd51e2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,6 +12,43 @@ resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + +"@apidevtools/json-schema-ref-parser@9.0.6": + version "9.0.6" + resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz#5d9000a3ac1fd25404da886da6b266adcd99cf1c" + integrity sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg== + dependencies: + "@jsdevtools/ono" "^7.1.3" + call-me-maybe "^1.0.1" + js-yaml "^3.13.1" + +"@apidevtools/openapi-schemas@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz#9fa08017fb59d80538812f03fc7cac5992caaa17" + integrity sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ== + +"@apidevtools/swagger-methods@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz#b789a362e055b0340d04712eafe7027ddc1ac267" + integrity sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg== + +"@apidevtools/swagger-parser@^10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-10.1.0.tgz#a987d71e5be61feb623203be0c96e5985b192ab6" + integrity sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw== + dependencies: + "@apidevtools/json-schema-ref-parser" "9.0.6" + "@apidevtools/openapi-schemas" "^2.1.0" + "@apidevtools/swagger-methods" "^3.0.2" + "@jsdevtools/ono" "^7.1.3" + ajv "^8.6.3" + ajv-draft-04 "^1.0.0" + call-me-maybe "^1.0.1" + "@babel/code-frame@^7.12.13": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" @@ -484,6 +521,11 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" +"@exodus/schemasafe@^1.0.0-rc.2": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.3.0.tgz#731656abe21e8e769a7f70a4d833e6312fe59b7f" + integrity sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw== + "@fastify/busboy@^2.0.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.0.tgz#0709e9f4cb252351c609c6e6d8d6779a8d25edff" @@ -544,6 +586,11 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" +"@jsdevtools/ono@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" + integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== + "@ledgerhq/devices@^5.48.0", "@ledgerhq/devices@^5.51.1": version "5.51.1" resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-5.51.1.tgz#d741a4a5d8f17c2f9d282fd27147e6fe1999edb7" @@ -650,7 +697,7 @@ resolved "https://registry.yarnpkg.com/@multiversx/sdk-bls-wasm/-/sdk-bls-wasm-0.3.5.tgz#2e83308fdc7a0928c6d5a7f910d796fd8eb2d90b" integrity sha512-c0tIdQUnbBLSt6NYU+OpeGPYdL0+GV547HeHT8Xc0BKQ7Cj0v82QUoA2QRtWrR1G4MNZmLsIacZSsf6DrIS2Bw== -"@multiversx/sdk-core@^12.12.0": +"@multiversx/sdk-core@^12.12.0", "@multiversx/sdk-core@^12.18.0": version "12.18.0" resolved "https://registry.yarnpkg.com/@multiversx/sdk-core/-/sdk-core-12.18.0.tgz#ae99665f9afb2bd4f1e325cb7daabb1dbcc55ca6" integrity sha512-F+xGslPMkkZ0S/Q8UJZsMYl0mgHIuK/GdVsNFPiMKxQsKkxA2LTjNdPxVxjwgvRmN7WfdsTtQvmlsA5O1NYhBg== @@ -664,7 +711,7 @@ keccak "3.0.2" protobufjs "7.2.4" -"@multiversx/sdk-network-providers@^2.0.0": +"@multiversx/sdk-network-providers@^2.0.0", "@multiversx/sdk-network-providers@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@multiversx/sdk-network-providers/-/sdk-network-providers-2.2.1.tgz#6018c30a039182e221f945ab0492eb596d79064d" integrity sha512-JsGznvyZSIBLpQ9bRjyv0EWfstaqDyFRBzokNZSbwk5z+3LjQFZxPTU3iv95BvW/rPQh8L0zD8Xwjw05pjTLyA== @@ -700,6 +747,24 @@ tweetnacl "1.0.3" uuid "8.3.2" +"@multiversx/sdk-wallet@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@multiversx/sdk-wallet/-/sdk-wallet-4.3.0.tgz#0d9a268f68b32d5590d827d5e5c991a5c23b6d93" + integrity sha512-ggyyvsQMiT1Hy9C6LlhQ3u+E0leO4V3q5Jh/U/eIRaj9b9xkPCjh2W5nOiaYDD0vYHrMVcrqMBSXE8MzU/2H7A== + dependencies: + "@multiversx/sdk-bls-wasm" "0.3.5" + "@noble/ed25519" "1.7.3" + "@noble/hashes" "1.3.0" + bech32 "1.1.4" + bip39 "3.0.2" + blake2b "2.1.3" + ed25519-hd-key "1.1.2" + ed2curve "0.3.0" + keccak "3.0.1" + scryptsy "2.1.0" + tweetnacl "1.0.3" + uuid "8.3.2" + "@noble/curves@1.1.0", "@noble/curves@~1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" @@ -1382,6 +1447,13 @@ dependencies: json-stringify-safe "^5.0.1" +"@taquito/core@^19.0.1": + version "19.0.1" + resolved "https://registry.yarnpkg.com/@taquito/core/-/core-19.0.1.tgz#6fd39f993603ee2f2770108643256c766e9c2a55" + integrity sha512-uYtp5fiJDZ5GCbNyyTA50aBJykJtvrViVFGECT6KR/MUYJ+EXQRKgCql+yGLhRo8yyHIa8T5zFiBZR8l82nEsA== + dependencies: + json-stringify-safe "^5.0.1" + "@taquito/http-utils@^17.5.2": version "17.5.2" resolved "https://registry.yarnpkg.com/@taquito/http-utils/-/http-utils-17.5.2.tgz#2fa1ac5fd4d2e02603eafe052d27b9c39938d7fc" @@ -1390,6 +1462,14 @@ "@taquito/core" "^17.5.2" node-fetch "^2.7.0" +"@taquito/http-utils@^19.0.1": + version "19.0.1" + resolved "https://registry.yarnpkg.com/@taquito/http-utils/-/http-utils-19.0.1.tgz#b4d2807c5bef0a073a8fcfae880903c63b22fdf7" + integrity sha512-O5kWpXmcjEpf3vvmWdqjvdlNQe8Ar44dC+xLuWpwtsHTAhXgfxhq/ugjeBvBE3ryjnVgCmNrqovx6cUCejSjyg== + dependencies: + "@taquito/core" "^19.0.1" + node-fetch "^2.7.0" + "@taquito/local-forging@^17.5.2": version "17.5.2" resolved "https://registry.yarnpkg.com/@taquito/local-forging/-/local-forging-17.5.2.tgz#64481358d2421c1363c022203f0d362667ca5d18" @@ -1399,6 +1479,15 @@ "@taquito/utils" "^17.5.2" bignumber.js "^9.1.2" +"@taquito/local-forging@^19.0.1": + version "19.0.1" + resolved "https://registry.yarnpkg.com/@taquito/local-forging/-/local-forging-19.0.1.tgz#341cd23e6fa0d5ac70f606650c622010a7fe3df3" + integrity sha512-r10ZD+cgXbjdxU+k6Y3GYJ/GjkDW1FTWs+SJlA98plRsr4CsLZxf21ZyUWM/LcRbpMETJz4aXLTHxUN8oPj8jA== + dependencies: + "@taquito/core" "^19.0.1" + "@taquito/utils" "^19.0.1" + bignumber.js "^9.1.2" + "@taquito/michel-codec@^17.5.2": version "17.5.2" resolved "https://registry.yarnpkg.com/@taquito/michel-codec/-/michel-codec-17.5.2.tgz#63482340c580c18e4baca165f78142d9e71063a5" @@ -1406,6 +1495,13 @@ dependencies: "@taquito/core" "^17.5.2" +"@taquito/michel-codec@^19.0.1": + version "19.0.1" + resolved "https://registry.yarnpkg.com/@taquito/michel-codec/-/michel-codec-19.0.1.tgz#fde16f776aca4f45088067be2024ebf0aaf53feb" + integrity sha512-LwYq9gExJB0fEdEMBHg0yWsaunaUTmv1ZLXY4hbyQO8Yz0B9SGgLTeuKOxWpgYrTefQuZ9OYZ4ZZ5RqbbVhj8g== + dependencies: + "@taquito/core" "^19.0.1" + "@taquito/michelson-encoder@^17.5.2": version "17.5.2" resolved "https://registry.yarnpkg.com/@taquito/michelson-encoder/-/michelson-encoder-17.5.2.tgz#ed97b6b13c18f15af6c703065cbb79d18b1fb6d0" @@ -1417,6 +1513,17 @@ bignumber.js "^9.1.2" fast-json-stable-stringify "^2.1.0" +"@taquito/michelson-encoder@^19.0.1": + version "19.0.1" + resolved "https://registry.yarnpkg.com/@taquito/michelson-encoder/-/michelson-encoder-19.0.1.tgz#cb20f18aefc05de0bbac8531408774839155df8e" + integrity sha512-z7BPPJyVgaY4H9EmoIeVPpH43NGT6NiKvBEWDsYMgqnOsdpT3VTmINKjpSK7OdPNG4TnEOKyW1MEkaHKKy5RRQ== + dependencies: + "@taquito/core" "^19.0.1" + "@taquito/rpc" "^19.0.1" + "@taquito/utils" "^19.0.1" + bignumber.js "^9.1.2" + fast-json-stable-stringify "^2.1.0" + "@taquito/rpc@^17.5.2": version "17.5.2" resolved "https://registry.yarnpkg.com/@taquito/rpc/-/rpc-17.5.2.tgz#06d2fe708cd6395afc4b665ac87e54b2945cbc9f" @@ -1427,6 +1534,16 @@ "@taquito/utils" "^17.5.2" bignumber.js "^9.1.2" +"@taquito/rpc@^19.0.1": + version "19.0.1" + resolved "https://registry.yarnpkg.com/@taquito/rpc/-/rpc-19.0.1.tgz#0617a96acf2b120a5c868bc195716d5381eb6185" + integrity sha512-wpxxHP/Xx/QJJlT391Vz2KNWCrJOtI7ZWZJdo9C2oAr2gH53OThUcTxnh60drC8Zod7nuUlDTsEIxxUjTfExgA== + dependencies: + "@taquito/core" "^19.0.1" + "@taquito/http-utils" "^19.0.1" + "@taquito/utils" "^19.0.1" + bignumber.js "^9.1.2" + "@taquito/signer@^17.5.0": version "17.5.2" resolved "https://registry.yarnpkg.com/@taquito/signer/-/signer-17.5.2.tgz#90cc042fc06aca2b6c35ac33fcfd5ff4b2c417f8" @@ -1462,6 +1579,21 @@ bignumber.js "^9.1.2" rxjs "^7.8.1" +"@taquito/taquito@^19.0.0", "@taquito/taquito@^19.0.1": + version "19.0.1" + resolved "https://registry.yarnpkg.com/@taquito/taquito/-/taquito-19.0.1.tgz#7531844118fc0b05080f5fd10382549428673153" + integrity sha512-OUhvF7QaqZ3joqTd/SzvGp1PCThZNyh798I2+8VrWZ128oDWWaUxb1jyAhR7AAHrUv5suB6aF3YOwuQcy6tIsg== + dependencies: + "@taquito/core" "^19.0.1" + "@taquito/http-utils" "^19.0.1" + "@taquito/local-forging" "^19.0.1" + "@taquito/michel-codec" "^19.0.1" + "@taquito/michelson-encoder" "^19.0.1" + "@taquito/rpc" "^19.0.1" + "@taquito/utils" "^19.0.1" + bignumber.js "^9.1.2" + rxjs "^7.8.1" + "@taquito/tzip16@^17.5.0": version "17.5.2" resolved "https://registry.yarnpkg.com/@taquito/tzip16/-/tzip16-17.5.2.tgz#8846dd2572a2338d71a32b92449076e8351bab83" @@ -1476,6 +1608,20 @@ bignumber.js "^9.1.2" crypto-js "^4.2.0" +"@taquito/tzip16@^19.0.0": + version "19.0.1" + resolved "https://registry.yarnpkg.com/@taquito/tzip16/-/tzip16-19.0.1.tgz#302504875dfd6a0c069a4143b958acc6fef90140" + integrity sha512-Y3aMp+c/eCZMhReR//10IiEc+ZEg/R7nlw8dZaGdD1xd+jhAQqD2An8HAyOeA78yESa4MC4blM8rATlEnnvFHA== + dependencies: + "@taquito/core" "^19.0.1" + "@taquito/http-utils" "^19.0.1" + "@taquito/michelson-encoder" "^19.0.1" + "@taquito/rpc" "^19.0.1" + "@taquito/taquito" "^19.0.1" + "@taquito/utils" "^19.0.1" + bignumber.js "^9.1.2" + crypto-js "^4.2.0" + "@taquito/utils@^17.5.2": version "17.5.2" resolved "https://registry.yarnpkg.com/@taquito/utils/-/utils-17.5.2.tgz#9a1305dc06843963f7b542b5598b9c206bebaf82" @@ -1492,6 +1638,22 @@ elliptic "^6.5.4" typedarray-to-buffer "^4.0.0" +"@taquito/utils@^19.0.0", "@taquito/utils@^19.0.1": + version "19.0.1" + resolved "https://registry.yarnpkg.com/@taquito/utils/-/utils-19.0.1.tgz#b3091a73efa856ed87ce679a7b218986dcb6eda8" + integrity sha512-1mld2MXbJfbG/+QLFV6tlJ5gPzHNBsM2yMXWYE9CapbpwoBg4dqMJMjmYeqyvPKRjyf+Vy579r7qi/5yBExKkQ== + dependencies: + "@stablelib/blake2b" "^1.0.1" + "@stablelib/ed25519" "^1.0.3" + "@taquito/core" "^19.0.1" + "@types/bs58check" "^2.1.0" + bignumber.js "^9.1.2" + blakejs "^1.2.1" + bs58check "^3.0.1" + buffer "^6.0.3" + elliptic "^6.5.4" + typedarray-to-buffer "^4.0.0" + "@ton/core@^0.53.0": version "0.53.0" resolved "https://registry.yarnpkg.com/@ton/core/-/core-0.53.0.tgz#9a2c101c4d2f48d0c9ec0e889b067da72d914df1" @@ -1499,6 +1661,13 @@ dependencies: symbol.inspect "1.0.1" +"@ton/core@^0.54.0": + version "0.54.0" + resolved "https://registry.yarnpkg.com/@ton/core/-/core-0.54.0.tgz#811495859102d9868ac7a412b540df14eae15795" + integrity sha512-ry3sCDq3jdjZuo7+egZ827/Y0/ajPbtrozvJryNMefUGfZQ/zYLVCmw9zBtxVsY2EX2zW7QhHQUs76/3y6HCwQ== + dependencies: + symbol.inspect "1.0.1" + "@ton/crypto-primitives@2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@ton/crypto-primitives/-/crypto-primitives-2.0.0.tgz#446256146d64fcec6e3f21d9f40b5148640329cc" @@ -1807,6 +1976,24 @@ "@typescript-eslint/types" "6.19.0" eslint-visitor-keys "^3.4.1" +"@tzkt/oazapfts@^4.5.2": + version "4.5.2" + resolved "https://registry.yarnpkg.com/@tzkt/oazapfts/-/oazapfts-4.5.2.tgz#4ede4ad497d2827c211e5498f74c01120fd16236" + integrity sha512-swGzinGddQL6S40CY5X7OC5B1zYZLSKsDXnqI1YIgOQ9iXA91OT/jaB1HpQ2BHaExG24h5SaxckDL/WnlwM00w== + dependencies: + "@apidevtools/swagger-parser" "^10.1.0" + lodash "^4.17.21" + minimist "^1.2.7" + swagger2openapi "^7.0.8" + typescript "^4.9.3" + +"@tzkt/sdk-api@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@tzkt/sdk-api/-/sdk-api-2.2.1.tgz#7f0743d3e8d36a18ffe013098c1ae34b9da0bfe0" + integrity sha512-WV4Dw6x1dSDC4PvdUi6lnQCxaeDsuzCkCMiLD5+fPufEB6GhQ1c5l2xN49boy/CJn4Ghr4VSh5/2eCKItEkPqQ== + dependencies: + "@tzkt/oazapfts" "^4.5.2" + "@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" @@ -1902,6 +2089,11 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv-draft-04@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" + integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1912,6 +2104,16 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.6.3: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -2006,6 +2208,13 @@ arg@^4.1.0: resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -2129,6 +2338,15 @@ axios@^0.25.0: dependencies: follow-redirects "^1.14.7" +axios@^1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" + integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA== + dependencies: + follow-redirects "^1.15.4" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + b64-lite@^1.3.1, b64-lite@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/b64-lite/-/b64-lite-1.4.0.tgz#e62442de11f1f21c60e38b74f111ac0242283d3d" @@ -2492,6 +2710,11 @@ call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: get-intrinsic "^1.2.1" set-function-length "^1.1.1" +call-me-maybe@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" + integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -3102,6 +3325,11 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es6-promise@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" + integrity sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg== + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -3286,6 +3514,11 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + esquery@^1.4.2: version "1.5.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" @@ -3408,6 +3641,19 @@ ethers@^5.7.1: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" +ethers@^6.10.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.11.0.tgz#6d3e884ad36454c29d4662ae49439d5d04556c66" + integrity sha512-kPHNTnhVWiWU6AVo6CAeTjXEK24SpCXyZvwG9ROFjT0Vlux0EOhWKBAeC+45iDj80QNJTYaT1SDEmeunT0vDNw== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + ethers@^6.8.0: version "6.10.0" resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.10.0.tgz#20f3c63c60d59a993f8090ad423d8a3854b3b1cd" @@ -3530,6 +3776,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-safe-stringify@^2.0.7: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + fastq@^1.6.0: version "1.16.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" @@ -4025,6 +4276,11 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" +http2-client@^1.2.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/http2-client/-/http2-client-1.3.5.tgz#20c9dc909e3cc98284dd20af2432c524086df181" + integrity sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA== + https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -4466,6 +4722,14 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + json-bigint@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" @@ -4490,6 +4754,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -4904,7 +5173,7 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.6: +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.6, minimist@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -5140,6 +5409,13 @@ node-addon-api@^7.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.0.0.tgz#8136add2f510997b3b94814f4af1cce0b0e3962e" integrity sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA== +node-fetch-h2@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz#c6188325f9bd3d834020bf0f2d6dc17ced2241ac" + integrity sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg== + dependencies: + http2-client "^1.2.5" + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -5147,7 +5423,7 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^2.6.12, node-fetch@^2.7.0: +node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -5180,6 +5456,13 @@ node-gyp@8.x: tar "^6.1.2" which "^2.0.2" +node-readfiles@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/node-readfiles/-/node-readfiles-0.2.0.tgz#dbbd4af12134e2e635c245ef93ffcf6f60673a5d" + integrity sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA== + dependencies: + es6-promise "^3.2.1" + nopt@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" @@ -5217,6 +5500,52 @@ number-to-bn@1.7.0: bn.js "4.11.6" strip-hex-prefix "1.0.0" +oas-kit-common@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/oas-kit-common/-/oas-kit-common-1.0.8.tgz#6d8cacf6e9097967a4c7ea8bcbcbd77018e1f535" + integrity sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ== + dependencies: + fast-safe-stringify "^2.0.7" + +oas-linter@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/oas-linter/-/oas-linter-3.2.2.tgz#ab6a33736313490659035ca6802dc4b35d48aa1e" + integrity sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ== + dependencies: + "@exodus/schemasafe" "^1.0.0-rc.2" + should "^13.2.1" + yaml "^1.10.0" + +oas-resolver@^2.5.6: + version "2.5.6" + resolved "https://registry.yarnpkg.com/oas-resolver/-/oas-resolver-2.5.6.tgz#10430569cb7daca56115c915e611ebc5515c561b" + integrity sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ== + dependencies: + node-fetch-h2 "^2.3.0" + oas-kit-common "^1.0.8" + reftools "^1.1.9" + yaml "^1.10.0" + yargs "^17.0.1" + +oas-schema-walker@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz#74c3cd47b70ff8e0b19adada14455b5d3ac38a22" + integrity sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ== + +oas-validator@^5.0.8: + version "5.0.8" + resolved "https://registry.yarnpkg.com/oas-validator/-/oas-validator-5.0.8.tgz#387e90df7cafa2d3ffc83b5fb976052b87e73c28" + integrity sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw== + dependencies: + call-me-maybe "^1.0.1" + oas-kit-common "^1.0.8" + oas-linter "^3.2.2" + oas-resolver "^2.5.6" + oas-schema-walker "^1.1.5" + reftools "^1.1.9" + should "^13.2.1" + yaml "^1.10.0" + object-assign@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -5646,6 +5975,11 @@ reflect-metadata@^0.1.13: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.14.tgz#24cf721fe60677146bb77eeb0e1f9dece3d65859" integrity sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A== +reftools@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/reftools/-/reftools-1.1.9.tgz#e16e19f662ccd4648605312c06d34e5da3a2b77e" + integrity sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w== + regenerator-runtime@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" @@ -5665,7 +5999,7 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-from-string@^2.0.0: +require-from-string@^2.0.0, require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== @@ -5940,6 +6274,50 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +should-equal@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" + integrity sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA== + dependencies: + should-type "^1.4.0" + +should-format@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/should-format/-/should-format-3.0.3.tgz#9bfc8f74fa39205c53d38c34d717303e277124f1" + integrity sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q== + dependencies: + should-type "^1.3.0" + should-type-adaptors "^1.0.1" + +should-type-adaptors@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz#401e7f33b5533033944d5cd8bf2b65027792e27a" + integrity sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA== + dependencies: + should-type "^1.3.0" + should-util "^1.0.0" + +should-type@^1.3.0, should-type@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/should-type/-/should-type-1.4.0.tgz#0756d8ce846dfd09843a6947719dfa0d4cff5cf3" + integrity sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ== + +should-util@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/should-util/-/should-util-1.0.1.tgz#fb0d71338f532a3a149213639e2d32cbea8bcb28" + integrity sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g== + +should@^13.2.1: + version "13.2.3" + resolved "https://registry.yarnpkg.com/should/-/should-13.2.3.tgz#96d8e5acf3e97b49d89b51feaa5ae8d07ef58f10" + integrity sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ== + dependencies: + should-equal "^2.0.0" + should-format "^3.0.3" + should-type "^1.4.0" + should-type-adaptors "^1.0.1" + should-util "^1.0.0" + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -6056,6 +6434,11 @@ source-map@^0.6.0: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + sqlite3@^5.1.6: version "5.1.7" resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.7.tgz#59ca1053c1ab38647396586edad019b1551041b7" @@ -6233,6 +6616,23 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +swagger2openapi@^7.0.8: + version "7.0.8" + resolved "https://registry.yarnpkg.com/swagger2openapi/-/swagger2openapi-7.0.8.tgz#12c88d5de776cb1cbba758994930f40ad0afac59" + integrity sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g== + dependencies: + call-me-maybe "^1.0.1" + node-fetch "^2.6.1" + node-fetch-h2 "^2.3.0" + node-readfiles "^0.2.0" + oas-kit-common "^1.0.8" + oas-resolver "^2.5.6" + oas-schema-walker "^1.1.5" + oas-validator "^5.0.8" + reftools "^1.1.9" + yaml "^1.10.0" + yargs "^17.0.1" + symbol.inspect@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/symbol.inspect/-/symbol.inspect-1.0.1.tgz#e13125b8038c4996eb0dfa1567332ad4dcd0763f" @@ -6565,6 +6965,11 @@ typescript@5.1.3: resolved "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz" integrity sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw== +typescript@^4.9.3: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -6986,6 +7391,24 @@ ws@^8.8.1: resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== +"xp-decentralized-sdk@git+https://github.com/XP-NETWORK/xp-decentralized-client-library#bleeding-edge": + version "1.0.0" + resolved "git+https://github.com/XP-NETWORK/xp-decentralized-client-library#5b1a40323e9ef9cebe862974e6942f8a3aa9e2f0" + dependencies: + "@multiversx/sdk-core" "^12.18.0" + "@multiversx/sdk-network-providers" "^2.2.1" + "@multiversx/sdk-wallet" "^4.3.0" + "@taquito/taquito" "^19.0.0" + "@taquito/tzip16" "^19.0.0" + "@taquito/utils" "^19.0.0" + "@ton/core" "^0.54.0" + "@ton/crypto" "^3.2.0" + "@ton/ton" "^13.9.0" + "@tzkt/sdk-api" "^2.2.1" + axios "^1.6.7" + ethers "^6.10.0" + secretjs "=1.12.3" + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -7006,6 +7429,11 @@ yaml@2.3.4: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" @@ -7044,7 +7472,7 @@ yargs@16.2.0, yargs@^16.0.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.6.2: +yargs@^17.0.1, yargs@^17.6.2: version "17.7.2" resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From 5a271232e059c1503eaf0946185fe139ae686730 Mon Sep 17 00:00:00 2001 From: imsk17 Date: Tue, 13 Feb 2024 17:52:52 +0530 Subject: [PATCH 19/19] Tests: Remove Redundant Tests and Modify Generic Test --- src/config/chainSpecs.ts | 20 +- src/generic-test.ts | 887 ------------------ src/test/evm-to-evm.ts | 149 --- src/test/mockData.ts | 92 -- .../handleEvmValidatorAddition.test.ts | 118 --- .../components/addSelfInBridges/index.test.ts | 55 -- .../generateWalletsForChains/index.test.ts | 73 -- .../components/isEvmChainFunded.test.ts | 95 -- .../components/isStakingCoinFunded.test.ts | 85 -- .../promptToGetFunding/index.test.ts | 100 -- .../components/getInitialFunds/index.test.ts | 59 -- .../setup/components/isStaked/index.test.ts | 50 - .../promptDisplayHelp/index.test.ts | 51 - .../setup/components/stakeToken/index.test.ts | 237 ----- src/test/modules/setup/index.test.ts | 101 -- .../typesGuardRuntime/isEvmWallet.test.ts | 83 -- .../isGeneratedWallets.test.ts | 67 -- .../approveEvmDestinationLock/index.test.ts | 102 -- .../components/evmLockListener/index.test.ts | 42 - .../utils/getEvmLockListenerHandler.test.ts | 157 ---- .../utils/getLockEventDecodedLog.test.ts | 32 - .../utils/getNftDetails.test.ts | 273 ------ .../components/nftLockListener/index.test.ts | 41 - .../components/stakingListener/index.test.ts | 31 - .../components/approveStake/index.test.ts | 97 -- .../stakingListenerJob/index.test.ts | 46 - .../utils/getStakeEventDecodedLog.test.ts | 25 - .../getStakingListenerLogHandler.test.ts | 59 -- .../utils/createJobWithWorker/index.test.ts | 1 - .../utils/evmContractListener/index.test.ts | 149 --- src/tests/configs.ts | 35 + src/tests/data.ts | 73 ++ src/tests/generic-test.ts | 210 +++++ src/tests/mint.ts | 43 + src/tests/signers.ts | 22 + yarn.lock | 2 +- 36 files changed, 394 insertions(+), 3368 deletions(-) delete mode 100644 src/generic-test.ts delete mode 100644 src/test/evm-to-evm.ts delete mode 100644 src/test/mockData.ts delete mode 100644 src/test/modules/setup/components/addSelfInBridges/components/handleEvmValidatorAddition.test.ts delete mode 100644 src/test/modules/setup/components/addSelfInBridges/index.test.ts delete mode 100644 src/test/modules/setup/components/generateWalletsForChains/index.test.ts delete mode 100644 src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/components/isEvmChainFunded.test.ts delete mode 100644 src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/components/isStakingCoinFunded.test.ts delete mode 100644 src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/index.test.ts delete mode 100644 src/test/modules/setup/components/getInitialFunds/index.test.ts delete mode 100644 src/test/modules/setup/components/isStaked/index.test.ts delete mode 100644 src/test/modules/setup/components/promptDisplayHelp/index.test.ts delete mode 100644 src/test/modules/setup/components/stakeToken/index.test.ts delete mode 100644 src/test/modules/setup/index.test.ts delete mode 100644 src/test/modules/setup/typesGuardRuntime/isEvmWallet.test.ts delete mode 100644 src/test/modules/setup/typesGuardRuntime/isGeneratedWallets.test.ts delete mode 100644 src/test/modules/validator/components/nftLockListener/components/evmLockListener/components/approveEvmDestinationLock/index.test.ts delete mode 100644 src/test/modules/validator/components/nftLockListener/components/evmLockListener/index.test.ts delete mode 100644 src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getEvmLockListenerHandler.test.ts delete mode 100644 src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getLockEventDecodedLog.test.ts delete mode 100644 src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getNftDetails.test.ts delete mode 100644 src/test/modules/validator/components/nftLockListener/index.test.ts delete mode 100644 src/test/modules/validator/components/stakingListener/index.test.ts delete mode 100644 src/test/modules/validator/components/stakingListener/stakingListenerJob/components/approveStake/index.test.ts delete mode 100644 src/test/modules/validator/components/stakingListener/stakingListenerJob/index.test.ts delete mode 100644 src/test/modules/validator/components/stakingListener/utils/getStakeEventDecodedLog.test.ts delete mode 100644 src/test/modules/validator/components/stakingListener/utils/getStakingListenerLogHandler.test.ts delete mode 100644 src/test/modules/validator/utils/createJobWithWorker/index.test.ts delete mode 100644 src/test/modules/validator/utils/evmContractListener/index.test.ts create mode 100644 src/tests/configs.ts create mode 100644 src/tests/data.ts create mode 100644 src/tests/generic-test.ts create mode 100644 src/tests/mint.ts create mode 100644 src/tests/signers.ts diff --git a/src/config/chainSpecs.ts b/src/config/chainSpecs.ts index 2540e8b0..70f2fdd1 100644 --- a/src/config/chainSpecs.ts +++ b/src/config/chainSpecs.ts @@ -87,16 +87,16 @@ export const bridgeTestChains = [ nativeCoinSymbol: 'XTZ', chainType: 'tezos', }, - // { - // chain: 'HEDERA', - // rpcURL: 'https://testnet.hashio.io/api', - // nativeCoinSymbol: 'HBAR', - // intialFund: '50000000000000000', - // contractAddress: '0x742f68F53583Be22a62338e916eB8DE90D07daB1', - // chainType: 'hedera', - // lastBlock: 7095475, - // royaltyInfoProxyAddress: '0x870f7b68c0a64733dcF4D95E5C06aa34387B98BF', - // }, + { + chain: 'HEDERA', + rpcURL: 'https://testnet.hashio.io/api', + nativeCoinSymbol: 'HBAR', + intialFund: '50000000000000000', + contractAddress: '0x742f68F53583Be22a62338e916eB8DE90D07daB1', + chainType: 'hedera', + lastBlock: 7095475, + royaltyInfoProxyAddress: '0x870f7b68c0a64733dcF4D95E5C06aa34387B98BF', + }, ] as const satisfies readonly TChain[]; const stakingTestChain: IStakingConfig = { diff --git a/src/generic-test.ts b/src/generic-test.ts deleted file mode 100644 index 36b21bac..00000000 --- a/src/generic-test.ts +++ /dev/null @@ -1,887 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { JsonRpcProvider, Wallet } from 'ethers'; -import { generateWalletsForChains } from './modules/setup/components'; -import { SecretNetworkClient, Wallet as SecretWallet } from 'secretjs'; -import { InMemorySigner } from '@taquito/signer'; -import { UserSigner } from '@multiversx/sdk-wallet/out'; -import { keyPairFromSecretKey } from 'ton-crypto'; -import { ClaimData as TonClaimData } from '@src/contractsTypes/contracts/tonBridge'; -import { bridgeTestChains, testnetBridgeConfig } from './config/chainSpecs'; -import { - Bridge__factory, - ERC721Royalty, - ERC721Royalty__factory, -} from './contractsTypes'; -import { - getEvmBridgeContract, - getEvmSingleNftContract, - // getHederaBridgeContract, - getMultiversXBridgeContract, - getStorageContract, - getTezosBridgeContract, - getTonBridgeContract, - waitForMSWithMsg, -} from './utils'; -import { - IEvmChainConfig, - // IHederaChainConfig, - IMultiversXChainConfig, - ISecretChainConfig, - ITezosChainConfig, - ITonChainConfig, - SignerAndSignature, -} from './types'; -import { - getEvmSignedNftDetails, - getMultiversXSignedNftDetails, - getSecretSignedNftDetails, - getTezosSignedNftDetails, - getTonSignedNftDetails, -} from './modules/validator/components/nftLockListener/utils'; - -import getSecretBridgeContract, { - SecretClaimData, - CodeInfo, -} from './utils/functions/getSecretBridgeContract'; -import { getLockEventDecodedLog as getMxLockEventDecodedLog } from './modules/validator/components/nftLockListener/components/multiversXLockListener/utils'; -import getLockEventDecodedLog from './modules/validator/components/nftLockListener/components/evmLockListener/utils/getLockEventDecodedLog'; -import { LogObject } from '@src/modules/validator/utils/evmContractListener/types'; -import { getContractOperations } from './modules/validator/utils/tezosContractListener'; -import { - ILog, - ITransactions, -} from './modules/validator/utils/tezosContractListener/types'; -import { extractStrOrAddr } from './modules/validator/components/nftLockListener/components/tezosLockListener/utils/getTezosLockListenerHandler'; -import { TezosToolkit } from '@taquito/taquito'; -import { INftTransferDetailsObject } from './modules/validator/components/nftLockListener/components/types'; -import { ClaimStruct } from './utils/functions/getMultiversXBridgeContract'; -import axios from 'axios'; -import { - ChainFactory, - ChainFactoryConfigs, - MetaMap, -} from 'xp-decentralized-sdk'; -import { - IMultiverseXLogEvent, - IMultiverseXLogs, -} from './modules/validator/utils/multiversXContractListener/utils/types'; -import { TezosClaimArgs } from './utils/functions/getTezosBridgeContract'; -import { tas } from './contractsTypes/tezosContractTypes/type-aliases'; - -import { WalletContractV4 } from 'ton'; -import { Address, TonClient, beginCell } from '@ton/ton'; -import { loadLockedEvent } from './contractsTypes/contracts/tonBridge'; -import TonWeb from 'tonweb'; -import { SalePriceToGetTotalRoyalityPercentage } from './utils/constants/salePriceToGetTotalRoyalityPercentage'; -// import { promptToGetFunding } from './modules/setup/components/getInitialFunds/components'; - -(async () => { - const genWallets = await generateWalletsForChains(); - const factory = ChainFactory(ChainFactoryConfigs.TestNet()); - - // let result = false; - - // while (!result) { - // result = await promptToGetFunding({ - // wallets: genWallets, - // config: testnetBridgeConfig, - // }); - // } - - // Assuming we have enough funds on the validator accounts itself. - - const signers = { - bsc: new Wallet(genWallets.evmWallet.privateKey), - eth: new Wallet(genWallets.evmWallet.privateKey), - tezos: new InMemorySigner(genWallets.tezosWallet.secretKey), - multiversx: UserSigner.fromWallet( - genWallets.multiversXWallet.userWallet, - genWallets.multiversXWallet.password, - ), - secret: new SecretWallet(genWallets.secretWallet.privateKey), - ton: keyPairFromSecretKey( - Buffer.from(genWallets.tonWallet.secretKey, 'hex'), - ), - }; - const configs = { - bsc: bridgeTestChains.find( - (e) => e.chain === 'BSC', - )! as IEvmChainConfig, - eth: bridgeTestChains.find( - (e) => e.chain === 'ETH', - )! as IEvmChainConfig, - // hedera: bridgeTestChains.find( - // (e) => e.chain === 'HEDERA', - // )! as IHederaChainConfig, - tezos: bridgeTestChains.find( - (e) => e.chain === 'TEZOS', - )! as ITezosChainConfig, - multiversx: bridgeTestChains.find( - (e) => e.chain === 'MULTIVERSX', - )! as IMultiversXChainConfig, - - secret: bridgeTestChains.find( - (e) => e.chain === 'SECRET', - )! as ISecretChainConfig, - ton: bridgeTestChains.find( - (e) => e.chain === 'TON', - )! as ITonChainConfig, - }; - const tonweb = new TonWeb(new TonWeb.HttpProvider(configs.ton.rpcURL)); - - const walletClass = tonweb.wallet.all['v4R2']; - - const wallet = new walletClass(tonweb.provider, { - publicKey: TonWeb.utils.hexToBytes(genWallets.tonWallet.publicKey), - }); - console.log((await wallet.getAddress()).toString(true)); - const storage = getStorageContract({ - evmChainConfig: testnetBridgeConfig.storageConfig, - evmWallet: genWallets.evmWallet, - }); - - const data = { - bsc: { - signer: new Wallet( - genWallets.evmWallet.privateKey, - new JsonRpcProvider(configs.bsc.rpcURL), - ), - bridge: getEvmBridgeContract({ - evmChainConfig: configs.bsc, - evmWallet: genWallets.evmWallet, - }), - config: configs.bsc, - logDecoder: getLockEventDecodedLog, - signedNftDetails: getEvmSignedNftDetails, - address: genWallets.evmWallet.address, - extractLogFromTx: async (hash: string): Promise => { - const { topicHash } = - Bridge__factory.createInterface().getEvent('Locked'); - const provider = new JsonRpcProvider(configs.bsc.rpcURL); - const receipt = await provider.getTransactionReceipt(hash)!; - - return (receipt?.logs.filter( - (e) => e.topics.includes(topicHash), - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ) ?? [])[0] as unknown as any; - }, - cdMapper: (cd: INftTransferDetailsObject) => { - return cd; - }, - }, - // hedera: { - // signer: new Wallet(genWallets.evmWallet.privateKey), - // bridge: getHederaBridgeContract({ - // hederaChainConfig: configs.hedera, - // evmWallet: genWallets.evmWallet, - // }), - // config: configs.hedera, - // logDecoder: getLockEventDecodedLog, - // signedNftDetails: getEvmSignedNftDetails, - // address: genWallets.evmWallet.address, - // extractLogFromTx: async (hash: string): Promise => { - // const { topicHash } = - // Bridge__factory.createInterface().getEvent('Locked'); - // const provider = new JsonRpcProvider(configs.bsc.rpcURL); - // const receipt = await provider.getTransactionReceipt(hash)!; - - // return (receipt?.logs.filter( - // (e) => e.topics.includes(topicHash), - // // eslint-disable-next-line @typescript-eslint/no-explicit-any - // ) ?? [])[0] as unknown as any; - // }, - // cdMapper: (cd: INftTransferDetailsObject) => { - // return cd; - // }, - // }, - multiversx: { - signer: UserSigner.fromWallet( - genWallets.multiversXWallet.userWallet, - genWallets.multiversXWallet.password, - ), - config: configs.multiversx, - address: genWallets.multiversXWallet.userWallet.address, - bridge: getMultiversXBridgeContract({ - multiversXChainConfig: configs.multiversx, - multiversXWallet: genWallets.multiversXWallet, - }), - signedNftDetails: getMultiversXSignedNftDetails, - cdMapper: (cd: INftTransferDetailsObject): ClaimStruct => { - return { ...cd, attrs: cd.metadata }; - }, - extractLogFromTx: async (hash: string): Promise => { - const eventIdentifier = ['lock721', 'lock1155']; - const resultantLogs: (IMultiverseXLogEvent & { - txHash: string; - })[] = []; - const incompleteTx: { [txHash: string]: boolean } = {}; - - const getResultantLogs = ( - logs: IMultiverseXLogs, - txHash: string, - ) => { - const eventLog = logs.events.find((_event) => { - return eventIdentifier.includes(_event.identifier); - }); - const isCompletedTx = logs.events.find( - (_event) => _event.identifier === 'completedTxEvent', - ); - if (eventLog && isCompletedTx) { - resultantLogs.push({ ...eventLog, txHash }); - } else if (eventLog && !isCompletedTx) { - incompleteTx[txHash] = true; - } - }; - const response = ( - await axios.get( - `${configs.multiversx.gatewayURL.replace('gateway', 'api')}/transactions/${hash}`, - ) - ).data; - - if (response?.logs) getResultantLogs(response.logs, hash); - if (response?.results?.logs) - getResultantLogs(response.results.log, hash); - if (response?.results.length > 0) { - for (const i of response.results) { - if (i?.logs) { - getResultantLogs(i.logs, hash); - } - } - } - return resultantLogs as any; - }, - logDecoder: (log: LogObject) => { - const data = log as (IMultiverseXLogEvent & { - txHash: string; - })[]; - for (const log of data) { - const decodedLog = getMxLockEventDecodedLog({ log: log }); - return decodedLog; - } - throw new Error(`No Log Found`); - }, - }, - eth: { - signer: new Wallet( - genWallets.evmWallet.privateKey, - new JsonRpcProvider(configs.eth.rpcURL), - ), - bridge: getEvmBridgeContract({ - evmChainConfig: configs.eth, - evmWallet: genWallets.evmWallet, - }), - config: configs.eth, - logDecoder: getLockEventDecodedLog, - signedNftDetails: getEvmSignedNftDetails, - address: genWallets.evmWallet.address, - extractLogFromTx: async (hash: string): Promise => { - const { topicHash } = - Bridge__factory.createInterface().getEvent('Locked'); - const provider = new JsonRpcProvider(configs.bsc.rpcURL); - const receipt = await provider.getTransactionReceipt(hash)!; - - return (receipt?.logs.filter( - (e) => e.topics.includes(topicHash), - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ) ?? [])[0] as unknown as any; - }, - cdMapper: (cd: INftTransferDetailsObject) => { - return cd; - }, - }, - tezos: { - signer: new InMemorySigner(genWallets.tezosWallet.secretKey), - bridge: getTezosBridgeContract({ - tezosChainConfig: configs.tezos, - tezosWallet: genWallets.tezosWallet, - }), - config: configs.tezos, - logDecoder: (log: LogObject) => { - const data = log as ILog & { transaction_hash: string }; - const sourceNftContractAddress = extractStrOrAddr( - data.source_nft_address, - ); - const { - token_id: tokenId, // Unique ID for the NFT transfer - dest_chain: destinationChain, // Chain to where the NFT is being transferred - dest_address: destinationUserAddress, // User's address in the destination chain - token_amount: tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) - nft_type: nftType, // Sigular or multiple ( 721 / 1155) - source_chain: sourceChain, // Source chain of NFT - transaction_hash: transactionHash, - } = data; - return { - tokenId, - destinationChain, - destinationUserAddress, - tokenAmount, - nftType, - sourceChain, - transactionHash, - sourceNftContractAddress, - }; - }, - signedNftDetails: getTezosSignedNftDetails, - address: await new InMemorySigner( - genWallets.tezosWallet.secretKey, - ).publicKeyHash(), - extractLogFromTx: async (block: string): Promise => { - const Tezos = new TezosToolkit(configs.tezos.rpcURL); - const logs: ITransactions[] = await getContractOperations({ - contractAddress: configs.tezos.contractAddress, - fromLevel: parseInt(block) - 1, - toLevel: (await Tezos.rpc.getBlockHeader()).level, - restApiURL: configs.tezos.restApiURL, - }); - let payload = undefined; - for (const log of logs) { - payload = log.payload; - } - return payload! as LogObject; - }, - cdMapper: ( - nftTransferDetailsObject: INftTransferDetailsObject, - ): TezosClaimArgs => { - return { - token_id: tas.nat(nftTransferDetailsObject.tokenId), - source_chain: nftTransferDetailsObject.sourceChain, - dest_chain: nftTransferDetailsObject.destinationChain, - dest_address: tas.address( - nftTransferDetailsObject.destinationUserAddress, - ), - source_nft_contract_address: - nftTransferDetailsObject.sourceNftContractAddress, - name: nftTransferDetailsObject.name, - symbol: nftTransferDetailsObject.symbol, - royalty: tas.nat(nftTransferDetailsObject.royalty), - royalty_receiver: tas.address( - nftTransferDetailsObject.royaltyReceiver, - ), - metadata: nftTransferDetailsObject.metadata, - transaction_hash: nftTransferDetailsObject.transactionHash, - token_amount: tas.nat(nftTransferDetailsObject.tokenAmount), - nft_type: nftTransferDetailsObject.nftType, - fee: tas.mutez(nftTransferDetailsObject.fee), - }; - }, - }, - secret: { - signer: new SecretWallet(genWallets.secretWallet.privateKey), - bridge: getSecretBridgeContract({ - secretChainConfig: configs.secret, - secretWallet: genWallets.secretWallet, - }), - config: configs.secret, - logDecoder: (log: LogObject) => { - const data = log as ILog & { transaction_hash: string }; - const sourceNftContractAddress = extractStrOrAddr( - data.source_nft_address, - ); - const { - token_id: tokenId, // Unique ID for the NFT transfer - dest_chain: destinationChain, // Chain to where the NFT is being transferred - dest_address: destinationUserAddress, // User's address in the destination chain - token_amount: tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) - nft_type: nftType, // Sigular or multiple ( 721 / 1155) - source_chain: sourceChain, // Source chain of NFT - transaction_hash: transactionHash, - } = data; - return { - tokenId, - destinationChain, - destinationUserAddress, - tokenAmount, - nftType, - sourceChain, - transactionHash, - sourceNftContractAddress, - }; - }, - signedNftDetails: getSecretSignedNftDetails, - address: genWallets.secretWallet.publicKey, - extractLogFromTx: async (hash: string): Promise => { - const eventId = 'LockedEventInfo'; - const secretjs = new SecretNetworkClient({ - url: configs.secret.rpcURL, - chainId: configs.secret.chainId, - }); - const tx = await secretjs.query.getTx(hash)!; - if (!tx) { - throw new Error('Tx not found'); - } - const log = tx.jsonLog - ?.at(0) - ?.events.find((item) => item.type === 'wasm') - ?.attributes.find((item) => item.key === eventId); - const { - token_id: tokenId, // Unique ID for the NFT transfer - destination_chain: destinationChain, // Chain to where the NFT is being transferred - destination_user_address: destinationUserAddress, // User's address in the destination chain - source_nft_contract_address: sourceNftContractAddress, // Address of the NFT contract in the source chain - token_amount: tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) - nft_type: nftType, // Sigular or multiple ( 721 / 1155) - source_chain: sourceChain, // Source chain of NFT - } = JSON.parse(log!.value); - return { - tokenId, - destinationChain, - destinationUserAddress, - sourceNftContractAddress, - tokenAmount, - nftType, - sourceChain, - } as LogObject; - }, - cdMapper: ( - nftTransferDetailsObject: INftTransferDetailsObject, - ): SecretClaimData => { - return { - token_id: nftTransferDetailsObject.tokenId, - source_chain: nftTransferDetailsObject.sourceChain, - destination_chain: - nftTransferDetailsObject.destinationChain, - destination_user_address: - nftTransferDetailsObject.destinationUserAddress, - source_nft_contract_address: - nftTransferDetailsObject.sourceNftContractAddress, - name: nftTransferDetailsObject.name, - symbol: nftTransferDetailsObject.symbol, - royalty: parseInt(nftTransferDetailsObject.royalty), - royalty_receiver: nftTransferDetailsObject.royaltyReceiver, - metadata: nftTransferDetailsObject.metadata, - transaction_hash: nftTransferDetailsObject.transactionHash, - token_amount: nftTransferDetailsObject.tokenAmount, - nft_type: nftTransferDetailsObject.nftType, - fee: nftTransferDetailsObject.fee, - }; - }, - }, - ton: { - signer: WalletContractV4.create({ - publicKey: Buffer.from(genWallets.tonWallet.publicKey, 'hex'), - workchain: 0, - }), - - bridge: getTonBridgeContract({ - tonChainConfig: configs.ton, - tonWallet: genWallets.tonWallet, - }), - config: configs.ton, - logDecoder: (data: any) => { - const { - token_id: tokenId, // Unique ID for the NFT transfer - dest_chain: destinationChain, // Chain to where the NFT is being transferred - dest_address: destinationUserAddress, // User's address in the destination chain - token_amount: tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) - nft_type: nftType, // Sigular or multiple ( 721 / 1155) - source_chain: sourceChain, // Source chain of NFT - transaction_hash: transactionHash, - source_nft_address: sourceNftContractAddress, - } = data; - return { - tokenId, - destinationChain, - destinationUserAddress, - tokenAmount, - nftType, - sourceChain, - transactionHash, - sourceNftContractAddress, - }; - }, - signedNftDetails: getTonSignedNftDetails, - address: genWallets.tonWallet.publicKey, - extractLogFromTx: async () => { - const client = new TonClient({ - endpoint: configs.ton.rpcURL, - apiKey: 'f3f6ef64352ac53cdfca18a3ba5372983e4037182c2b510fc52de5a259ecf292', - }); - const latestTx = await client.getTransactions( - Address.parseFriendly(configs.ton.contractAddress).address, - { limit: 1 }, - ); - for (const tx of latestTx) { - for (let i = 0; i < tx.outMessages.size; i++) { - const log = tx.outMessages.get(i)!; - const hash = tx.hash().toString('base64'); - if (log.body.asSlice().loadUint(32) !== 3571773646) { - return; - } - const { - tokenId, // Unique ID for the NFT transfer - destinationChain, // Chain to where the NFT is being transferred - destinationUserAddress, // User's address in the destination chain - sourceNftContractAddress, // Address of the NFT contract in the source chain - tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) - nftType, // Sigular or multiple ( 721 / 1155) - sourceChain, // Source chain of NFT - } = loadLockedEvent(log.body.asSlice()); - const getSourceNftContractAddress = () => { - try { - return sourceNftContractAddress - .asSlice() - .loadAddress() - .toString(); - } catch (e) { - return sourceNftContractAddress - .asSlice() - .loadStringTail(); - } - }; - - const nftTransferDetailsObject = { - tokenId: tokenId.toString(), - sourceChain, - destinationChain, - destinationUserAddress, - sourceNftContractAddress: - getSourceNftContractAddress(), - tokenAmount: tokenAmount.toString(), - nftType, - transactionHash: hash, - }; - return nftTransferDetailsObject! as LogObject; - } - } - throw new Error(`No Log Found`); - }, - cdMapper: (d: INftTransferDetailsObject): TonClaimData => { - // Mitigation if destination user address is invalid - let destinationAddress: Address; - try { - destinationAddress = Address.parseFriendly( - d.destinationUserAddress, - ).address; - } catch (e) { - destinationAddress = Address.parseFriendly( - d.royaltyReceiver, - ).address; - } - - // off chain condition to store sourceNftContractAddress as string if not native, and address if native - let sourceNftContractAddress_ = beginCell() - .storeSlice( - beginCell() - .storeStringTail(d.sourceNftContractAddress) - .endCell() - .asSlice(), - ) - .endCell(); - try { - sourceNftContractAddress_ = beginCell() - .storeSlice( - beginCell() - .storeAddress( - Address.parseFriendly( - d.sourceNftContractAddress, - ).address, - ) - .endCell() - .asSlice(), - ) - .endCell(); - } catch (e) { - console.log('Not Native TON Address'); - } - const data = { - $$type: 'ClaimData', - data1: { - $$type: 'ClaimData1', - destinationChain: d.destinationChain, - destinationUserAddress: destinationAddress, - tokenId: BigInt(d.tokenId), - sourceChain: d.sourceChain, - tokenAmount: BigInt(d.tokenAmount), - }, - data2: { - $$type: 'ClaimData2', - name: d.name, - symbol: d.symbol, - nftType: d.nftType, - }, - data3: { - $$type: 'ClaimData3', - fee: BigInt(d.fee), - metadata: d.metadata, - royaltyReceiver: Address.parseFriendly( - d.royaltyReceiver, - ).address, - sourceNftContractAddress: sourceNftContractAddress_, - }, - data4: { - $$type: 'ClaimData4', - royalty: { - $$type: 'RoyaltyParams', - numerator: BigInt( - SalePriceToGetTotalRoyalityPercentage, - ), - denominator: BigInt(d.royalty), - destination: Address.parseFriendly( - d.royaltyReceiver, - ).address, - }, - transactionHash: d.transactionHash, - newContent: beginCell() - .storeInt(0x01, 8) - .storeStringRefTail(d.metadata) - .endCell(), - }, - } satisfies TonClaimData; - return data as any; - }, - }, - }; - - // Create a NFT Contract - console.log(`Deploying NFT Contract on BSC`); - let contract: ERC721Royalty; - let deployed = false; - - while (!deployed) { - try { - contract = await createNftOnEvm( - data.bsc.signer.connect( - new JsonRpcProvider(data.bsc.config.rpcURL), - ), - ); - deployed = true; - } catch (e) { - `Retrying to deploy NFT Contract on BSC`; - } - } - - // Mint 5 NFT on the contract - for (let i = 0; i < 1; i++) { - let minted = false; - while (!minted) { - try { - await contract!.mint( - signers.bsc.address, - i, - 10, - signers.bsc.address, - 'https://meta.polkamon.com/meta?id=10001852306', - ); - minted = true; - } catch (e) { - console.log(`Retrying to mint NFT on BSC`); - } - } - } - console.log('Minted 1 NFTs ON BSC'); - - // Approve the contract to spend the NFTs - const nftC = getEvmSingleNftContract( - { - contractAddress: await contract!.getAddress(), - rpcURL: configs.bsc.rpcURL, - }, - data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), - ); - for (let i = 0; i < 1; i++) { - let approved = false; - while (!approved) { - try { - await nftC.approve(BigInt(i), data.bsc.config.contractAddress); - approved = true; - } catch (e: any) { - console.log( - `Retrying to approve NFT on BSC`, - console.log(e.shortMessage), - ); - } - } - } - console.log(`Approved NFTs on BSC`); - - // Lock the NFTs - async function transfer( - args: [ - { - fromChain: (typeof data)[keyof typeof data]; - toChain: (typeof data)[keyof typeof data]; - tokenId: string; - contractAddress: string; - codeInfo?: CodeInfo; - nonce?: string; - nftType: 'singular' | 'multiple'; - }, - ], - ) { - for (const tx of args) { - let wallet: any; - if (tx.toChain.config.chain === 'TON') { - const tonweb = new TonWeb( - new TonWeb.HttpProvider(configs.ton.rpcURL), - ); - - const walletClass = tonweb.wallet.all['v4R2']; - - wallet = new walletClass(tonweb.provider, { - publicKey: TonWeb.utils.hexToBytes( - genWallets.tonWallet.publicKey, - ), - }); - } - - const chain = await factory.inner( - tx.fromChain.config.chain as keyof MetaMap, - ); - let locked = false; - let lockHash: string = ''; - while (!locked) { - try { - const lock = await chain.lockNft( - tx.fromChain.signer as any, - tx.contractAddress, - tx.toChain.config.chain as keyof MetaMap, - tx.toChain.config.chain === 'TON' - ? (await wallet.getAddress()).toString() - : tx.toChain.address, - BigInt(tx.tokenId), - { gasLimit: 1000000 }, - ); - console.log(`Lock Hash:`, lock.hash()); - await (lock.tx as any).wait(); - locked = true; - lockHash = lock.hash(); - } catch (e: any) { - console.log( - `Retrying to lock NFT on ${tx.fromChain.config.chain}`, - e.shortMessage, - ); - } - } - - // console.log(`Locked on ${tx.fromChain.config.chain} ${lock.hash()}`); - - // await new Promise((e) => setTimeout(e, 10000)); - - // const log = await tx.fromChain.extractLogFromTx(lock.hash()); - // const { - // tokenId, // Unique ID for the NFT transfer - // destinationChain, // Chain to where the NFT is being transferred - // destinationUserAddress, // User's address in the destination chain - // sourceNftContractAddress, // Address of the NFT contract in the source chain - // tokenAmount, // amount of nfts to be transfered ( 1 in 721 case ) - // nftType, // Sigular or multiple ( 721 / 1155) - // sourceChain, // Source chain of NFT - // } = tx.fromChain.logDecoder({ - // log: log!, - // })!; - - // // if user gives a destination chain which is not registered with us, we early return - // const sourceChain_ = tx.fromChain.config; - - // const fee = String(await storage.chainFee(tx.toChain.config.chain)); // Required fee for claming nft on target chain - // const royaltyReceiver = String( - // await storage.chainRoyalty(tx.toChain.config.chain), - // ); - - // const { royalty, name, symbol, metadata } = await getNftDetails({ - // sourceNftContractAddress, - // sourceChain: sourceChain_, - // tokenId, - // nftType, - // }); - - // const nftTransferDetailsObject = { - // tokenId, - // sourceChain, - // destinationChain, - // destinationUserAddress, - // sourceNftContractAddress, - // name, - // symbol, - // royalty, - // royaltyReceiver, - // metadata, - // transactionHash: lock.hash(), - // tokenAmount, - // nftType, - // fee, - // }; - console.log(`Finding Claim Data for Lock Hash: ${lockHash}`); - - const nftDetails = await factory.getClaimData(chain, lockHash); - console.log(nftDetails); - console.log(`Got Claim Data`); - - console.log(`Fetching Signatures`); - - let signatures = await storage.getLockNftSignatures( - lockHash, - tx.fromChain.config.chain, - ); - const neededSignatures = - Math.floor( - (2 / 3) * Number(await tx.toChain.bridge.validatorsCount()), - ) + 1; - while (signatures.length < neededSignatures) { - await waitForMSWithMsg( - 1000, - `waiting for signatures, ${signatures.length}`, - ); - signatures = await storage.getLockNftSignatures( - lockHash, - tx.fromChain.config.chain, - ); - } - - const signatureArray: SignerAndSignature[] = []; - signatures.forEach((item) => { - signatureArray.push({ - signer: item.signerAddress, - signature: item.signature, - }); - }); - - console.log(signatures); - - let claimed = false; - while (!claimed) - try { - const tc = await factory.inner( - tx.toChain.config.chain as keyof MetaMap, - ); - const claim = await tc.claimNft( - tx.toChain.signer as any, - tc.transform(nftDetails) as any, - {}, - signatureArray, - ); - console.log( - `Claimed on ${tx.toChain.config.chain} at ${claim}`, - ); - claimed = true; - return ''; - } catch (e) { - console.log(e); - console.log(`Retrying Claiming`); - } - } - return ''; - } - - await transfer([ - { - fromChain: data.bsc, - toChain: data.eth, - contractAddress: await contract!.getAddress(), - tokenId: '0', - nftType: 'singular', - }, - ]); -})().catch((e) => { - console.error(e); -}); - -export async function createNftOnEvm(signer: Wallet) { - const contract = await new ERC721Royalty__factory(signer).deploy( - 'TestContract', - 'TC', - signer.address, - ); - await contract.deploymentTransaction()?.wait(); - return contract; -} diff --git a/src/test/evm-to-evm.ts b/src/test/evm-to-evm.ts deleted file mode 100644 index 89a3ae0f..00000000 --- a/src/test/evm-to-evm.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { JsonRpcProvider, Wallet } from 'ethers'; -import { generateWalletsForChains } from '../modules/setup/components'; -import { Wallet as SecretWallet } from 'secretjs'; -import { InMemorySigner } from '@taquito/signer'; -import { UserSigner } from '@multiversx/sdk-wallet/out'; -import { keyPairFromSecretKey } from 'ton-crypto'; -import { bridgeTestChains, testnetBridgeConfig } from '../config/chainSpecs'; -import { ERC721Royalty__factory } from '../contractsTypes'; -import { - getEvmBridgeContract, - getEvmSingleNftContract, - getStorageContract, -} from '../utils'; -import { IEvmChainConfig } from '../types'; - -(async () => { - const genWallets = await generateWalletsForChains(); - // Assuming we have enough funds on the validator accounts itself. - const signers = { - bsc: new Wallet(genWallets.evmWallet.privateKey), - eth: new Wallet(genWallets.evmWallet.privateKey), - tezos: new InMemorySigner(genWallets.tezosWallet.secretKey), - multiversx: UserSigner.fromWallet( - genWallets.multiversXWallet.userWallet, - genWallets.multiversXWallet.password, - ), - secret: new SecretWallet(genWallets.secretWallet.privateKey), - ton: keyPairFromSecretKey( - Buffer.from(genWallets.tonWallet.secretKey, 'hex'), - ), - }; - const configs = { - bsc: bridgeTestChains.find( - (e) => e.chain === 'BSC', - )! as IEvmChainConfig, - eth: bridgeTestChains.find( - (e) => e.chain === 'ETH', - )! as IEvmChainConfig, - }; - - const data = { - storage: getStorageContract({ - evmChainConfig: testnetBridgeConfig.storageConfig, - evmWallet: genWallets.evmWallet, - }), - bsc: { - signer: new Wallet(genWallets.evmWallet.privateKey), - bridge: getEvmBridgeContract({ - evmChainConfig: configs.bsc, - evmWallet: genWallets.evmWallet, - }), - config: configs.bsc, - }, - eth: { - signer: new Wallet(genWallets.evmWallet.privateKey), - bridge: getEvmBridgeContract({ - evmChainConfig: configs.eth, - evmWallet: genWallets.evmWallet, - }), - config: configs.eth, - }, - }; - - // Create a NFT Contract - - const contract = await createNftOnEvm( - data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), - ); - - // Mint 5 NFT on the contract - for (let i = 0; i < 5; i++) { - await contract.mint( - signers.bsc.address, - i, - 10, - signers.bsc.address, - 'https://meta.polkamon.com/meta?id=10001852306', - ); - } - console.log('Minted 5 NFTs ON BSC'); - - // Approve the contract to spend the NFTs - const nftC = getEvmSingleNftContract( - { - contractAddress: await contract.getAddress(), - rpcURL: configs.bsc.rpcURL, - }, - data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), - ); - for (let i = 0; i < 5; i++) { - await nftC.approve(BigInt(i), data.bsc.config.contractAddress); - } - - // Lock the NFTs - const lockTx = await data.bsc.bridge.lock721( - await contract.getAddress(), - '0', - 'ETH', - signers.eth.address, - ); - - // Wait for the NFTs to be locked - await new Promise((resolve) => setTimeout(resolve, 10000)); - - // Fetch the signatures - const signatures = await data.storage.getLockNftSignatures( - lockTx.hash, - 'BSC', - ); - - const signatureArray: string[] = []; - signatures.forEach((item) => { - signatureArray.push(item[1]); - }); - - const claimData = { - tokenId: '0', - sourceChain: 'BSC', - destinationChain: 'ETH', - destinationUserAddress: signers.eth.address, - sourceNftContractAddress: await contract.getAddress(), - name: 'TestContract', - symbol: 'TC', - royalty: '10', - royaltyReceiver: signers.bsc.address, - metadata: 'https://meta.polkamon.com/meta?id=10001852306', - transactionHash: lockTx.hash, - tokenAmount: '1', - nftType: 'singular', - fee: '100000000000000', - }; - - // Unlock it on the destination chain - const claimed = await data.eth.bridge.claimNFT721( - claimData, - signatureArray, - ); - - console.log(claimed); -})(); - -async function createNftOnEvm(signer: Wallet) { - const contract = await new ERC721Royalty__factory(signer).deploy( - 'TestContract', - 'TC', - signer.address, - ); - return contract; -} diff --git a/src/test/mockData.ts b/src/test/mockData.ts deleted file mode 100644 index 4ce1f303..00000000 --- a/src/test/mockData.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { IBridgeConfig } from '@src/types'; - -const mockBridgeConfig: IBridgeConfig = { - storageConfig: { - chain: 'storageChainMock', - rpcURL: 'rpcURLMock', - nativeCoinSymbol: 'nativeCoinSymbolMock', - intialFund: 'intialFundMock', - contractAddress: 'contractAddressMock', - lastBlock: 3214, - chainType: 'evm', - }, - bridgeChains: [ - { - chain: 'BSC', - rpcURL: 'rpcURLMock', - nativeCoinSymbol: 'nativeCoinSymbolMock', - intialFund: 'intialFundMock ETH', - contractAddress: 'contractAddressMock', - lastBlock: 12345, - chainType: 'evm', - }, - { - chain: 'ETH', - rpcURL: 'rpcURLMock', - nativeCoinSymbol: 'nativeCoinSymbolMock', - intialFund: 'intialFundMock', - contractAddress: 'contractAddressMock', - lastBlock: 54321, - chainType: 'evm', - }, - { - chain: 'nonEvmChainMock', - nativeCoinSymbol: 'nativeCoinSymbolMock', - intialFund: 'intialFundMock', - contractAddress: 'contractAddressMock', - lastBlock: 54321, - chainType: 'multiversX', - elasticSearchURL: 'https://devnet-index.multiversx.com', - gatewayURL: 'https://devnet-gateway.multiversx.com', - chainID: 'D', - }, - ], - stakingConfig: { - chain: 'stakingChainMock', - rpcURL: 'rpcURLMock', - nativeCoinSymbol: 'nativeCoinSymbolMock', - intialFund: 'intialFundMock', - contractAddress: 'contractAddressMock', - lastBlock: 12345, - coinAddress: 'coinAddressMock', - coinSymbol: 'coinSymbolMock', - chainType: 'evm', - }, -}; - -const mockWallets = { - evmWallet: { - address: '0x1234567890abcdef1234567890abcdef12345678', - privateKey: - '0x8a6a4e9e3865814dc8f1e4fca103051162921715d1e517ba638ba05656f320b0', - }, - multiversXWallet: { - userWallet: { - version: 4, - kind: 'secretKey', - id: '139565e9-5d7c-44cc-9d95-adc6ae8372a7', - address: - 'f8e2792233ab260d7f1e19290bf8d53070919edf0c1108804d0976884a91b877', - bech32: 'erd1lr38jg3n4vnq6lc7ry5sh7x4xpcfr8klpsgs3qzdp9mgsj53hpmsf3jg65', - crypto: { - ciphertext: - '9bbbd14512984095242fa13517dd96164143683b29dc5a791b2af4224b315326a7f1dc0a6393e1391866851941517d67bdb4c8f89ef941f2bce9c65f891f3167', - cipherparams: { - iv: '2850cfea9ac07da97b364facadf64251', - }, - cipher: 'aes-128-ctr', - kdf: 'scrypt', - kdfparams: { - dklen: 32, - salt: 'bf474285cd209b102e23ab115879e52b64dbce9d9d880e80df371c2e5da714a9', - n: 4096, - r: 8, - p: 1, - }, - mac: 'e8dd25b15d61a176456f733f5d61c4728d23f633151eea44172bdff3028d68a3', - }, - }, - password: 'ycria4ygubr', - }, -}; -export { mockBridgeConfig, mockWallets }; diff --git a/src/test/modules/setup/components/addSelfInBridges/components/handleEvmValidatorAddition.test.ts b/src/test/modules/setup/components/addSelfInBridges/components/handleEvmValidatorAddition.test.ts deleted file mode 100644 index 6577b350..00000000 --- a/src/test/modules/setup/components/addSelfInBridges/components/handleEvmValidatorAddition.test.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import { handleValidatorAddition } from '@src/modules/setup/components/addSelfInBridges/components'; // Import the function to test -import * as promts from '@src/modules/setup/components/getInitialFunds/components/promptToGetFunding/components'; -import * as utils from '@src/utils/functions'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -describe('handleValidatorAddition', () => { - beforeEach(() => { - console.info = () => {}; - }); - - afterEach(() => { - sinon.restore(); - }); - - const testCases = [ - { - description: 'should handle not adding validator if already exists', - isAlreadyAdded: true, - totalExistingValidators: 1, - signatures: [{ signature: 'signature' }], - addValidatorCalled: false, - }, - { - description: - 'should handle adding a validator when not already added; total validator count:11, signature count:11', - isAlreadyAdded: false, - totalExistingValidators: 11, - signatures: new Array(11).fill({ - signature: 'signature', - signerAddress: 'test', - }), - addValidatorCalled: true, - }, - { - description: - 'should handle adding a validator when not already added; total validator count:11, signature count:8', - isAlreadyAdded: false, - totalExistingValidators: 11, - signatures: new Array(8).fill({ - signature: 'signature', - signerAddress: 'test', - }), - addValidatorCalled: true, - }, - ]; - - testCases.forEach( - ({ - description, - isAlreadyAdded, - totalExistingValidators, - signatures, - addValidatorCalled, - }) => { - it(description, async () => { - const hash = 'some unique hash'; - - const bridgeContractStub = { - validators: sinon - .stub() - .resolves({ added: isAlreadyAdded }), - validatorsCount: sinon - .stub() - .resolves(BigInt(totalExistingValidators)), - addValidator: sinon - .stub() - .resolves({ hash, wait: sinon.stub().resolves() }), // Mock adding validator - }; - - const storageContractStub = { - getStakingSignaturesCount: sinon - .stub() - .resolves(signatures.length), // Mock signature count - getStakingSignatures: sinon.stub().resolves(signatures), // Mock signatures - }; - - const getEvmBridgeContractStub = sinon.stub( - utils, - 'getEvmBridgeContract', - ); - getEvmBridgeContractStub.returns({ - ...getEvmBridgeContractStub[1], - ...bridgeContractStub, - }); - - const getStorageContractStub = sinon - .stub(utils, 'getStorageContract') - .resolves(storageContractStub); - getStorageContractStub.returns({ - ...getStorageContractStub[1], - ...storageContractStub, - }); - - // overriding; wallets already funded - sinon.stub(promts, 'isEvmChainFunded').resolves(true); - - // Call the function - await handleValidatorAddition({ - storageChainConfig: mockBridgeConfig.storageConfig, - chainConfig: mockBridgeConfig.bridgeChains.find( - (item) => item.chainType === 'evm', - ), - wallets: mockWallets, - }); - - expect( - bridgeContractStub.addValidator.calledOnceWith( - mockWallets.evmWallet.address, - signatures.map((item) => { - return { ...item }; - }), - ), - ).equals(addValidatorCalled); - }); - }, - ); -}); diff --git a/src/test/modules/setup/components/addSelfInBridges/index.test.ts b/src/test/modules/setup/components/addSelfInBridges/index.test.ts deleted file mode 100644 index 12e9d821..00000000 --- a/src/test/modules/setup/components/addSelfInBridges/index.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import { addSelfInBridges } from '@src/modules/setup/components'; -import * as addSelfInBridgesComponents from '@src/modules/setup/components/addSelfInBridges/components'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; - -describe('addSelfInBridges', () => { - afterEach(() => { - sinon.restore(); - }); - beforeEach(() => { - console.info = () => {}; - }); - - it('should call handleValidatorAddition for each chain', async () => { - const handleValidatorAdditionStub = sinon.stub( - addSelfInBridgesComponents, - 'handleValidatorAddition', - ); - handleValidatorAdditionStub.resolves(); - - await addSelfInBridges({ - config: mockBridgeConfig, - wallets: mockWallets, - }); - - // Ensure handleValidatorAddition is called twice for chains - expect(handleValidatorAdditionStub.calledThrice).to.be.true; - - // Ensure it's called with the correct arguments - expect( - handleValidatorAdditionStub.calledWithExactly({ - storageChainConfig: mockBridgeConfig.storageConfig, - chainConfig: mockBridgeConfig.bridgeChains[0], // First EVM chain - wallets: mockWallets, - }), - ).to.be.true; - - expect( - handleValidatorAdditionStub.calledWithExactly({ - storageChainConfig: mockBridgeConfig.storageConfig, - chainConfig: mockBridgeConfig.bridgeChains[1], // Second EVM chain - wallets: mockWallets, - }), - ).to.be.true; - - expect( - handleValidatorAdditionStub.calledWithExactly({ - storageChainConfig: mockBridgeConfig.storageConfig, - chainConfig: mockBridgeConfig.bridgeChains[2], // Second EVM chain - wallets: mockWallets, - }), - ).to.be.true; - }); -}); diff --git a/src/test/modules/setup/components/generateWalletsForChains/index.test.ts b/src/test/modules/setup/components/generateWalletsForChains/index.test.ts deleted file mode 100644 index df0dda05..00000000 --- a/src/test/modules/setup/components/generateWalletsForChains/index.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import { HDNodeWallet, ethers } from 'ethers'; -import { promises as fs } from 'fs'; -import { generateWalletsForChains } from '@src/modules/setup/components'; -import * as utils from '@src/utils/functions'; -import { mockWallets } from '@src/test/mockData'; - -describe('generateWalletsForChains', () => { - beforeEach(() => { - console.info = () => {}; // Override console.info to do nothing - }); - - afterEach(() => { - sinon.restore(); - }); - - const testCases = [ - { - description: 'should return existing secrets if they are valid', - readJsonFileStubResolves: mockWallets, - expectedWriteFileCalled: false, - }, - { - description: - 'should generate new secrets if existing secrets are invalid', - readJsonFileStubResolves: { invalid: 'data' }, - expectedWriteFileCalled: true, - }, - { - description: - 'should generate new secrets if no secrets file is found', - readJsonFileStubRejects: new Error('File not found'), - expectedWriteFileCalled: true, - }, - ]; - - testCases.forEach( - ({ - description, - readJsonFileStubResolves, - readJsonFileStubRejects, - expectedWriteFileCalled, - }) => { - it(description, async () => { - const readJsonFileStub = sinon.stub(utils, 'readJsonFile'); - if (readJsonFileStubResolves) { - readJsonFileStub.resolves(readJsonFileStubResolves); - } else if (readJsonFileStubRejects) { - readJsonFileStub.rejects(readJsonFileStubRejects); - } - - const writeFileStub = sinon.stub(fs, 'writeFile').resolves(); - - sinon.stub(ethers.Wallet, 'createRandom').returns({ - address: - '0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - privateKey: - '0x1234567890123456789012345678901234567890123456789012345678901234', - } as unknown as HDNodeWallet); - - const result = await generateWalletsForChains(); - expect(writeFileStub.calledOnce).to.equal( - expectedWriteFileCalled, - ); - if (expectedWriteFileCalled) { - expect(result.evmWallet).to.have.property('address'); - expect(result.evmWallet).to.have.property('privateKey'); - } - }); - }, - ); -}); diff --git a/src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/components/isEvmChainFunded.test.ts b/src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/components/isEvmChainFunded.test.ts deleted file mode 100644 index 39d04d0d..00000000 --- a/src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/components/isEvmChainFunded.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import { isEvmChainFunded } from '@src/modules/setup/components/getInitialFunds/components/promptToGetFunding/components'; -import * as utils from '@src/utils/functions'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import { IEvmChainConfig } from '@src/types'; - -describe('isEvmChainFunded', () => { - const testCases = [ - { - description: 'should return true if the chain is funded', - evmChainConfig_: { - intialFund: '10', - }, - balance: BigInt('10'), // Balance greater than initial fund - expected: true, - }, - { - description: - 'should return true if the chain is funded more then asked intialFund', - evmChainConfig_: { - intialFund: '10', - }, - balance: BigInt('1000'), // Balance greater than initial fund - expected: true, - }, - { - description: 'should return false if the chain is not funded', - evmChainConfig_: { - intialFund: '10', - }, - balance: BigInt('9'), // Balance less than initial fund - expected: false, - }, - { - description: 'should throw an error on exception', - evmChainConfig_: { - intialFund: '10', - }, - balance: BigInt('5'), // Any balance - throwError: true, - }, - ]; - - afterEach(() => { - sinon.restore(); - }); - beforeEach(() => { - console.info = () => {}; - }); - - testCases.forEach( - ({ description, evmChainConfig_, balance, expected, throwError }) => { - it(description, async () => { - const { evmWallet } = mockWallets; - const evmChainConfig = { - ...(mockBridgeConfig.bridgeChains.find( - (item) => item.chain === 'evm', - ) as IEvmChainConfig), - ...evmChainConfig_, - }; - - if (throwError) { - // Stub getCurrentEvmBalance to throw an error - sinon - .stub(utils, 'getCurrentEvmBalance') - .rejects(new Error('Balance fetch failed')); - } else { - // Stub getCurrentEvmBalance to return a balance - sinon.stub(utils, 'getCurrentEvmBalance').resolves(balance); - } - - try { - const result = await isEvmChainFunded({ - evmChainConfig, - evmWallet, - }); - expect(result).to.equal(expected); - } catch (error) { - if (!throwError) { - // Ensure the function doesn't throw an error when not expected - throw error; - } - console.info( - error, - '---------------------------------------', - ); - expect(error).to.equal( - 'Error while isEvmChainFunded, orignal error: Error: Balance fetch failed', - ); - } - }); - }, - ); -}); diff --git a/src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/components/isStakingCoinFunded.test.ts b/src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/components/isStakingCoinFunded.test.ts deleted file mode 100644 index 144a64a3..00000000 --- a/src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/components/isStakingCoinFunded.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import { isStakingCoinFunded } from '@src/modules/setup/components/getInitialFunds/components/promptToGetFunding/components'; -import * as utils from '@src/utils/functions'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; - -describe('isStakingCoinFunded', () => { - const testCases = [ - { - description: 'should return true if the staking coin is funded', - stakingChainConfig_: { - intialFund: '10', - }, - balance: BigInt('11'), // Balance greater than initial fund - expected: true, - }, - { - description: - 'should return false if the staking coin is not funded', - stakingChainConfig_: { - intialFund: '10', - }, - balance: BigInt('9'), // Balance less than initial fund - expected: false, - }, - { - description: 'should throw an error on exception', - stakingChainConfig_: { - intialFund: '10', - }, - balance: BigInt('5'), // Any balancea - throwError: true, - }, - ]; - - afterEach(() => { - sinon.restore(); - }); - beforeEach(() => { - console.info = () => {}; - }); - - testCases.forEach( - ({ - description, - stakingChainConfig_, - balance, - expected, - throwError, - }) => { - it(description, async () => { - const { evmWallet } = mockWallets; - const stakingChainConfig = { - ...mockBridgeConfig.stakingConfig, - ...stakingChainConfig_, - }; - if (throwError) { - // Stub getCurrentEvmBalance to throw an error - sinon - .stub(utils, 'getCurrentEvmBalance') - .rejects(new Error('Balance fetch failed')); - } else { - // Stub getCurrentEvmBalance to return a balance - sinon.stub(utils, 'getCurrentEvmBalance').resolves(balance); - } - - try { - const result = await isStakingCoinFunded({ - stakingChainConfig, - evmWallet, - }); - expect(result).to.equal(expected); - } catch (error) { - if (!throwError) { - // Ensure the function doesn't throw an error when not expected - throw error; - } - expect(error).to.equal( - 'Error while isStakingCoinFunded, orignal error: Error: Balance fetch failed', - ); - } - }); - }, - ); -}); diff --git a/src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/index.test.ts b/src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/index.test.ts deleted file mode 100644 index cdc3039a..00000000 --- a/src/test/modules/setup/components/getInitialFunds/components/promptToGetFunding/index.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import { promptToGetFunding } from '@src/modules/setup/components/getInitialFunds/components'; -import * as utils from '@src/modules/setup/components/getInitialFunds/components/promptToGetFunding/components'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; - -describe('promptToGetFunding', () => { - const testCases = [ - { - description: 'should return true if the all chains are funded', - fundedChains: [ - ...mockBridgeConfig.bridgeChains.map((item) => item.chain), - mockBridgeConfig.stakingConfig.chain, - mockBridgeConfig.storageConfig.chain, - ], - expected: true, - }, - { - description: 'should return false one bridge chain not funded', - fundedChains: [ - ...[ - ...mockBridgeConfig.bridgeChains.map((item) => item.chain), - ].slice(1), - mockBridgeConfig.stakingConfig.chain, - mockBridgeConfig.storageConfig.chain, - ], - expected: false, - }, - { - description: 'should return false no bridge chains are funded', - fundedChains: [ - mockBridgeConfig.stakingConfig.chain, - mockBridgeConfig.storageConfig.chain, - ], - expected: false, - }, - { - description: 'should return false if staking chain is not funded', - fundedChains: [ - ...mockBridgeConfig.bridgeChains.map((item) => item.chain), - mockBridgeConfig.storageConfig.chain, - ], - expected: false, - }, - { - description: 'should return false if storage chain is not funded', - fundedChains: [ - ...mockBridgeConfig.bridgeChains.map((item) => item.chain), - mockBridgeConfig.stakingConfig.chain, - ], - expected: false, - }, - { - description: 'should return false if none of the chains are funded', - fundedChains: [], - expected: false, - }, - ]; - - afterEach(() => { - sinon.restore(); - }); - beforeEach(() => { - console.info = () => {}; - }); - - testCases.forEach(({ description, fundedChains, expected }) => { - it(description, async () => { - sinon - .stub(utils, 'isEvmChainFunded') - .callsFake(({ evmChainConfig }) => { - return Promise.resolve( - fundedChains.includes(evmChainConfig.chain), - ); // Resolve with true for funded chains - }); - - sinon - .stub(utils, 'isMultiversXChainFunded') - .callsFake(({ multiversXChainConfig }) => { - return Promise.resolve( - fundedChains.includes(multiversXChainConfig.chain), - ); // Resolve with true for funded chains - }); - - sinon - .stub(utils, 'isStakingCoinFunded') - .callsFake(({ stakingChainConfig }) => { - return Promise.resolve( - fundedChains.includes(stakingChainConfig.chain), - ); // Resolve with true if staking coin is funded - }); - - const result = await promptToGetFunding({ - config: mockBridgeConfig, - wallets: mockWallets, - }); - expect(result).to.equal(expected); - }); - }); -}); diff --git a/src/test/modules/setup/components/getInitialFunds/index.test.ts b/src/test/modules/setup/components/getInitialFunds/index.test.ts deleted file mode 100644 index ee85a294..00000000 --- a/src/test/modules/setup/components/getInitialFunds/index.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import * as utils from '@src/utils/functions'; -import * as prompts from '@src/modules/setup/components/getInitialFunds/components'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import { getInitialFunds } from '@src/modules/setup/components'; - -describe('getInitialFunds', () => { - const testCases = [ - { - description: 'should run the loop until funds are obtained', - promptResults: [false, false, true], // Simulate promptToGetFunding returning false, false, and then true - }, - { - description: - 'should run the loop once if funds are obtained immediately', - promptResults: [true], // Simulate promptToGetFunding returning true immediately - }, - { - description: - 'should handle errors and retry if funds are not obtained', - promptResults: [false, false, false, true], // Simulate promptToGetFunding returning false multiple times and then true - }, - ]; - - afterEach(() => { - sinon.restore(); - }); - beforeEach(() => { - console.info = () => {}; - }); - - testCases.forEach(({ description, promptResults }) => { - it(description, async () => { - const config = mockBridgeConfig; - const wallets = mockWallets; - - // Stub the functions used in getInitialFunds - sinon.stub(utils, 'waitForMSWithMsg').resolves(); // Stub waitForMSWithMsg - sinon.stub(utils, 'waitForKeyPress').resolves(); // Stub waitForKeyPress - - const promptToGetFundingStub = sinon.stub(); - promptResults.forEach((result, index) => { - promptToGetFundingStub.onCall(index).resolves(result); - }); - - sinon - .stub(prompts, 'promptToGetFunding') - .callsFake(promptToGetFundingStub); - - await getInitialFunds({ config, wallets }); - - // Check if promptToGetFunding was called the expected number of times - expect(promptToGetFundingStub.callCount).to.equal( - promptResults.length, - ); - }); - }); -}); diff --git a/src/test/modules/setup/components/isStaked/index.test.ts b/src/test/modules/setup/components/isStaked/index.test.ts deleted file mode 100644 index 819ae574..00000000 --- a/src/test/modules/setup/components/isStaked/index.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import { isStaked } from '@src/modules/setup/components'; -import * as utils from '@src/utils/functions'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; - -describe('isStaked', () => { - const testCases = [ - { - stakedAmount: BigInt(100), - expected: true, - description: - 'should return true if stakedAmount is greater than zero', - }, - { - stakedAmount: BigInt(0), - expected: false, - description: 'should return false if stakedAmount is zero', - }, - ]; - - afterEach(() => { - sinon.restore(); - }); - beforeEach(() => { - console.info = () => {}; - }); - - testCases.forEach(({ stakedAmount, expected, description }) => { - it(description, async () => { - const stakingContractStub = { - stakingBalances: sinon.stub().resolves(stakedAmount), - }; - const getStakingContractStub = sinon.stub( - utils, - 'getStakingContract', - ); - getStakingContractStub.returns({ - ...getStakingContractStub[1], - ...stakingContractStub, - }); - - const result = await isStaked({ - stakingChainConfig: mockBridgeConfig.stakingConfig, - evmWallet: mockWallets.evmWallet, - }); - expect(result).to.equal(expected); - }); - }); -}); diff --git a/src/test/modules/setup/components/promptDisplayHelp/index.test.ts b/src/test/modules/setup/components/promptDisplayHelp/index.test.ts deleted file mode 100644 index 279e88fe..00000000 --- a/src/test/modules/setup/components/promptDisplayHelp/index.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import promtDisplayHelp, { - PromtDisplayHelpStatements, -} from '@src/modules/setup/components/promtDisplayHelp'; - -describe('promtDisplayHelp', () => { - it('should display help information', () => { - const consoleInfoStub = sinon.stub(console, 'info'); - - try { - promtDisplayHelp(); - - // Check if console.info was called with the expected messages - expect(consoleInfoStub.callCount).to.equal(6); - expect( - consoleInfoStub - .getCall(0) - .calledWithExactly(PromtDisplayHelpStatements.statement1), - ).to.be.true; - expect( - consoleInfoStub - .getCall(1) - .calledWithExactly(PromtDisplayHelpStatements.statement2), - ).to.be.true; - expect( - consoleInfoStub - .getCall(2) - .calledWithExactly(PromtDisplayHelpStatements.statement3), - ).to.be.true; - expect( - consoleInfoStub - .getCall(3) - .calledWithExactly(PromtDisplayHelpStatements.statement4), - ).to.be.true; - expect( - consoleInfoStub - .getCall(4) - .calledWithExactly(PromtDisplayHelpStatements.statement5), - ).to.be.true; - expect( - consoleInfoStub - .getCall(5) - .calledWithExactly(PromtDisplayHelpStatements.statement6), - ).to.be.true; - } finally { - // Restore the stubbed console.info function - consoleInfoStub.restore(); - } - }); -}); diff --git a/src/test/modules/setup/components/stakeToken/index.test.ts b/src/test/modules/setup/components/stakeToken/index.test.ts deleted file mode 100644 index b0676f3c..00000000 --- a/src/test/modules/setup/components/stakeToken/index.test.ts +++ /dev/null @@ -1,237 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import * as utils from '@src/utils/functions'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import * as setupComponents from '@src/modules/setup/components'; -import { RetryPriority } from '@src/utils/constants/retries'; - -describe('stakeTokens', () => { - beforeEach(() => { - console.info = () => {}; - }); - - afterEach(() => { - sinon.restore(); - }); - - const testCases = [ - { - description: 'should not try to restake if already staked', - isStaked: true, - isStakedThrows: [{ throws: false }], - approveThrows: [{ throws: false }], - stakeERC20Throws: [{ throws: false }], - callCountApprove: 0, - callCountStake: 0, - callIsStaked: 1, - }, - { - description: 'should not try to restake if already staked', - isStaked: true, - isStakedThrows: [{ throws: false }], - approveThrows: [{ throws: false }], - stakeERC20Throws: [{ throws: false }], - callCountApprove: 0, - callCountStake: 0, - callIsStaked: 1, - }, - { - description: 'should retry threshold times if isStaked throws', - isStaked: false, - isStakedThrows: Array.from({ length: 20 }, () => ({ - throws: true, - })), - approveThrows: [{ throws: false }], - stakeERC20Throws: [{ throws: false }], - callCountApprove: 0, - callCountStake: 0, - callIsStaked: RetryPriority.HIGH, - }, - { - description: - 'should try to restake if not already staked & approve throws', - isStaked: false, - isStakedThrows: [{ throws: false }], - approveThrows: [ - { - throws: true, - reason: { - shortMessage: 'execution reverted: "Approve Failed"', - }, - }, - { throws: false }, - ], - stakeERC20Throws: [{ throws: false }], - callCountApprove: 2, - callCountStake: 1, - callIsStaked: 2, - }, - { - description: - 'should not try to restake on race condtion; isStaked returns true, stakeERC20Throws throws "You can only stake once"', - isStaked: false, - isStakedThrows: [{ throws: false }], - approveThrows: [{ throws: false }], - stakeERC20Throws: [ - { - throws: true, - reason: { - shortMessage: - 'execution reverted: "You can only stake once"', - }, - }, - ], - callCountApprove: 1, - callCountStake: 1, - callIsStaked: 1, - }, - { - description: - 'should try to restake if not able to stake in first try"', - isStaked: false, - isStakedThrows: [{ throws: false }], - approveThrows: [{ throws: false }, { throws: false }], - stakeERC20Throws: [ - { - throws: true, - reason: { - shortMessage: - 'execution reverted: "Gas Fee estimate issue"', - }, - }, - { throw: false }, - ], - callCountApprove: 2, - callCountStake: 2, - callIsStaked: 2, - }, - { - description: 'should break after retries threshold reached"', - isStaked: false, - isStakedThrows: [{ throws: false }], - approveThrows: Array.from({ length: 20 }, () => ({ - throws: false, - })), - stakeERC20Throws: Array.from({ length: 20 }, () => { - return { - throws: true, - reason: { - shortMessage: - 'execution reverted: "Gas Fee estimate issue"', - }, - }; - }), - callCountApprove: RetryPriority.HIGH, - callCountStake: RetryPriority.HIGH, - callIsStaked: RetryPriority.HIGH, - }, - ]; - - testCases.forEach( - ({ - description, - isStaked, - isStakedThrows, - stakeERC20Throws, - approveThrows, - callCountApprove, - callCountStake, - callIsStaked, - }) => { - it(description, async () => { - const hash = 'some unique hash'; - const { stakingConfig } = mockBridgeConfig; - - sinon.stub(utils, 'waitForMSWithMsg').resolves(); - - const stakeERC20Stub = sinon.stub(); - - stakeERC20Throws.forEach((shouldThrow, index) => { - if (shouldThrow.throws) { - stakeERC20Stub - .onCall(index) - .rejects( - 'reason' in shouldThrow - ? shouldThrow.reason - : '', - ); - } else { - stakeERC20Stub - .onCall(index) - .resolves({ hash, wait: sinon.stub().resolves() }); - } - }); - - const stakingContractStub = { - stakeERC20: sinon.stub().callsFake(stakeERC20Stub), - }; - - const approveStub = sinon.stub(); - - approveThrows.forEach((shouldThrow, index) => { - if (shouldThrow.throws) - approveStub - .onCall(index) - .rejects( - 'reason' in shouldThrow - ? shouldThrow.reason - : '', - ); - else - approveStub - .onCall(index) - .resolves({ hash, wait: sinon.stub().resolves() }); - }); - - const tokenContractStub = { - approve: sinon.stub().callsFake(approveStub), - }; - - const getStakingContractStub = sinon.stub( - utils, - 'getStakingContract', - ); - getStakingContractStub.returns({ - ...getStakingContractStub[1], - ...stakingContractStub, - }); - - const getEvmFungibleContractStub = sinon.stub( - utils, - 'getEvmFungibleContract', - ); - getEvmFungibleContractStub.returns({ - ...getEvmFungibleContractStub[1], - ...tokenContractStub, - }); - - const isStakedStub = sinon.stub(setupComponents, 'isStaked'); - - isStakedThrows.forEach((shouldThrow, index) => { - if (shouldThrow.throws) { - isStakedStub.onCall(index).throws(); - } else { - isStakedStub.resolves(isStaked); - } - }); - - // Call the function - await setupComponents.stakeTokens({ - stakingChainConfig: stakingConfig, - wallets: mockWallets, - }); - - expect(stakingContractStub.stakeERC20.callCount).to.equal( - callCountStake, - ); - expect(tokenContractStub.approve.callCount).to.equal( - callCountApprove, - ); - - if (isStakedThrows[0].throws) { - expect(isStakedStub.callCount).to.be.eq(callIsStaked); - } - }); - }, - ); -}); diff --git a/src/test/modules/setup/index.test.ts b/src/test/modules/setup/index.test.ts deleted file mode 100644 index be4b0400..00000000 --- a/src/test/modules/setup/index.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import * as setupComponents from '@src/modules/setup/components'; -import * as utilsFunctions from '@src/utils/functions'; -import * as dataSource from '@src/db/data-source'; -import * as validatorFunction from '@src/modules/validator'; -import { setup } from '@src/modules/setup'; - -describe('stakeTokens', () => { - before(() => {}); - afterEach(() => { - sinon.restore(); - }); - - const testCases = [ - { - description: - 'should not call getInitialFunds & stakeTokens if already staked', - isStaked: true, - getInitialFundCalled: false, - stakeTokensCalled: false, - processArgv: [], - }, - { - description: - 'should call getInitialFunds & stakeTokens if not already staked', - isStaked: false, - getInitialFundCalled: true, - stakeTokensCalled: true, - processArgv: [], - }, - { - description: - 'should run for testnet if --testnet args are provided', - isStaked: false, - getInitialFundCalled: true, - stakeTokensCalled: true, - processArgv: ['--testnet'], - }, - ]; - - testCases.forEach( - ({ - description, - isStaked, - getInitialFundCalled, - stakeTokensCalled, - processArgv, - }) => { - it(description, async () => { - const consoleInfoStub = sinon.stub(console, 'info'); - - const AppDataSourceStub = sinon - .stub(dataSource.AppDataSource, 'initialize') - .resolves(); - const isStakedStub = sinon - .stub(setupComponents, 'isStaked') - .resolves(isStaked); - const getInitialFundsStub = sinon - .stub(setupComponents, 'getInitialFunds') - .resolves(); - const stakeTokensStub = sinon - .stub(setupComponents, 'stakeTokens') - .resolves(); - const addSelfInBridgesStub = sinon - .stub(setupComponents, 'addSelfInBridges') - .resolves(); - const runValidatorsStub = sinon - .stub(validatorFunction, 'runValidators') - .resolves(); - - let getRedisConnectionStub = sinon.stub( - utilsFunctions, - 'getRedisConnection', - ); - getRedisConnectionStub = getRedisConnectionStub.returns({ - ...getRedisConnectionStub[1], - flushall: sinon.stub().resolves(), - }); - - process.argv = processArgv; - await setup(); - - expect(AppDataSourceStub.calledOnce).to.be.true; - expect(getRedisConnectionStub.calledOnce).to.be.true; - expect(isStakedStub.calledOnce).to.be.true; - - expect(getInitialFundsStub.calledOnce).to.equal( - getInitialFundCalled, - ); - expect(stakeTokensStub.calledOnce).to.equal(stakeTokensCalled); - - expect(addSelfInBridgesStub.calledOnce).to.be.true; - expect(runValidatorsStub.calledOnce).to.be.true; - expect(consoleInfoStub.calledWith('TESTNET_INITIATED')).equals( - processArgv.length > 0, - ); - }); - }, - ); -}); diff --git a/src/test/modules/setup/typesGuardRuntime/isEvmWallet.test.ts b/src/test/modules/setup/typesGuardRuntime/isEvmWallet.test.ts deleted file mode 100644 index 61831dbc..00000000 --- a/src/test/modules/setup/typesGuardRuntime/isEvmWallet.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { expect } from 'chai'; -import { isEvmWallet } from '@src/modules/setup/typesGuardRuntime'; - -describe('isEvmWallet', () => { - const testCases = [ - { - input: { - address: '0x1234567890abcdef1234567890abcdef12345678', - privateKey: - '0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - }, - expected: true, - description: 'should return true for valid EVM wallets', - }, - { - input: { - privateKey: - '0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - }, - expected: false, - description: 'should return false for missing address', - }, - { - input: { - address: '0x1234567890abcdef1234567890abcdef12345678', - }, - expected: false, - description: 'should return false for missing privateKey', - }, - { - input: { - address: 12345, - privateKey: - '0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef', - }, - expected: false, - description: 'should return false for invalid address', - }, - { - input: { - address: '0x1234567890abcdef1234567890abcdef12345678', - privateKey: 12345, - }, - expected: false, - description: 'should return false for invalid privateKey', - }, - { - input: null, - expected: false, - description: 'should return false for null input', - }, - { - input: 12345, - expected: false, - description: 'should return false for non-object input', - }, - { - input: '0x1234567890abcdef1234567890abcdef12345678', - expected: false, - description: 'should return false for non-object input', - }, - { - input: {}, - expected: false, - description: 'should return false for empty object input', - }, - { - input: [], - expected: false, - description: 'should return false for empty array input', - }, - ]; - - beforeEach(() => { - console.info = () => {}; - }); - - testCases.forEach(({ input, expected, description }) => { - it(description, () => { - expect(isEvmWallet(input)).to.equal(expected); - }); - }); -}); diff --git a/src/test/modules/setup/typesGuardRuntime/isGeneratedWallets.test.ts b/src/test/modules/setup/typesGuardRuntime/isGeneratedWallets.test.ts deleted file mode 100644 index 1bdc6199..00000000 --- a/src/test/modules/setup/typesGuardRuntime/isGeneratedWallets.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { expect } from 'chai'; -import { isGeneratedWallets } from '@src/modules/setup/typesGuardRuntime'; -import { mockWallets } from '@src/test/mockData'; - -describe('isGeneratedWallets', () => { - const testCases = [ - { - input: null, - expected: false, - description: 'should return false for null input', - }, - { - input: undefined, - expected: false, - description: 'should return false for undefined input', - }, - { - input: 123, - expected: false, - description: 'should return false for number input', - }, - { - input: 'string', - expected: false, - description: 'should return false for string input', - }, - { - input: {}, - expected: false, - description: 'should return false for empty object input', - }, - { - input: { randomProp: 'value' }, - expected: false, - description: - 'should return false for objects without evmWallet property', - }, - { - input: { evmWallet: {} }, - expected: false, - description: - 'should return false for objects with invalid evmWallet structure', - }, - { - input: { evmWallet: { address: '0x1234' } }, - expected: false, - description: - 'should return false for objects with invalid evmWallet structure', - }, - { - input: mockWallets, - expected: true, - description: - 'should return true for valid IGeneratedWallets structure', - }, - ]; - - beforeEach(() => { - console.info = () => {}; - }); - - testCases.forEach(({ input, expected, description }) => { - it(description, () => { - expect(isGeneratedWallets(input)).to.equal(expected); - }); - }); -}); diff --git a/src/test/modules/validator/components/nftLockListener/components/evmLockListener/components/approveEvmDestinationLock/index.test.ts b/src/test/modules/validator/components/nftLockListener/components/evmLockListener/components/approveEvmDestinationLock/index.test.ts deleted file mode 100644 index 011c0952..00000000 --- a/src/test/modules/validator/components/nftLockListener/components/evmLockListener/components/approveEvmDestinationLock/index.test.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import * as utils from '@src/utils/functions'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import { approveLock } from '@src/modules/validator/components/nftLockListener/components'; - -describe('approveLock', () => { - const nftTransferDetailsObject = { - tokenId: '1', - sourceChain: 'BSC', - destinationChain: 'ETH', - destinationUserAddress: '0x0000000000000000000000000000000000000000', - sourceNftContractAddress: '0x0000000000000000000000000000000000000000', - name: 'nameMock', - symbol: 'symbolMock', - royalty: '500', - royaltyReceiver: '0x0000000000000000000000000000000000000000', - metadata: 'metadataMock', - transactionHash: 'transactionHashMock', - tokenAmount: '1', - nftType: 'nftTypeMock', - fee: '500', - }; - - const { evmWallet } = mockWallets; - const { storageConfig } = mockBridgeConfig; - - const testCases = [ - { - approveLockNft: sinon.stub().resolves({ - wait: sinon.stub().resolves(), - hash: 'some unique hash', - }), - expectedToThrow: false, - description: 'should approveLock if no errors', - }, - { - approveLockNft: sinon.stub().rejects({ - shortMessage: `execution reverted: "Signature already used"`, - }), - expectedToThrow: false, - description: 'should not throw approveLock if already approved', - }, - { - approveLockNft: sinon.stub().rejects('Some other error'), - expectedToThrow: true, - description: - "should throw error if error is not 'Signature already used'", - }, - ]; - - afterEach(() => { - sinon.restore(); - }); - beforeEach(() => { - console.info = () => {}; - }); - - testCases.forEach(({ approveLockNft, expectedToThrow, description }) => { - it(description, async () => { - const txChain = 'BSC'; - const storageContractStub = { - approveLockNft, - }; - const getStorageContractStub = sinon.stub( - utils, - 'getStorageContract', - ); - getStorageContractStub.returns({ - ...getStorageContractStub[1], - ...storageContractStub, - }); - const storageContract = getStorageContractStub({ - evmChainConfig: storageConfig, - evmWallet, - }); - if (expectedToThrow) { - try { - await approveLock({ - nftTransferDetailsObject, - wallets: mockWallets, - destinationChainObject: storageConfig, - storageContract, - txChain, - }); - } catch (error) { - expect(error).to.exist; - expect(error.message).to.equal( - 'Error while processing log', - ); - } - } else - await approveLock({ - nftTransferDetailsObject, - wallets: mockWallets, - destinationChainObject: storageConfig, - storageContract, - txChain, - }); - }); - }); -}); diff --git a/src/test/modules/validator/components/nftLockListener/components/evmLockListener/index.test.ts b/src/test/modules/validator/components/nftLockListener/components/evmLockListener/index.test.ts deleted file mode 100644 index 1e896353..00000000 --- a/src/test/modules/validator/components/nftLockListener/components/evmLockListener/index.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import * as validatorUtils from '@src/modules/validator/utils'; -import { evmLockListener } from '@src/modules/validator/components/nftLockListener/components'; -import * as evmLockListenerUtils from '@src/modules/validator/components/nftLockListener/components/evmLockListener/utils'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import { IEvmChainConfig } from '@src/types'; -import { LogEntry } from '@src/modules/validator/utils/evmContractListener/types'; - -describe('evmLockListener', () => { - afterEach(() => { - sinon.restore(); - }); - - it('should call evmContractListener with the correct arguments', async () => { - const config = mockBridgeConfig; - const evmChainConfig = mockBridgeConfig - .bridgeChains[1] as IEvmChainConfig; - const wallets = mockWallets; - const evmContractListenerStub = sinon - .stub(validatorUtils, 'evmContractListener') - .resolves(); - const handleLogFunctionMock = async ({ log }: { log: LogEntry }) => { - console.info(log); - }; - sinon - .stub(evmLockListenerUtils, 'getEvmLockListenerHandler') - .returns(handleLogFunctionMock); - - await evmLockListener({ config, evmChainConfig, wallets }); - - // Assertions - expect(evmContractListenerStub.calledOnce).to.be.true; - expect(evmContractListenerStub.args[0][0]).to.deep.equal({ - contractAddress: evmChainConfig.contractAddress, - rpcURL: evmChainConfig.rpcURL, - lastBlock_: evmChainConfig.lastBlock, - chain: evmChainConfig.chain, - handleLog: handleLogFunctionMock, - }); - }); -}); diff --git a/src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getEvmLockListenerHandler.test.ts b/src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getEvmLockListenerHandler.test.ts deleted file mode 100644 index 1ea38c74..00000000 --- a/src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getEvmLockListenerHandler.test.ts +++ /dev/null @@ -1,157 +0,0 @@ -import sinon from 'sinon'; -import * as utils from '@src/utils/functions'; -import * as lockEventComponents from '@src/modules/validator/components/nftLockListener/components'; -import { expect } from 'chai'; -import * as evmLockEventUtils from '@src/modules/validator/components/nftLockListener/components/evmLockListener/utils'; -import * as lockEventUtils from '@src/modules/validator/components/nftLockListener/utils'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import { IEvmChainConfig } from '@src/types'; - -describe('getEvmLockListenerHandler', () => { - beforeEach(() => { - console.info = () => {}; - }); - - afterEach(() => { - sinon.restore(); - }); - - const testCases = [ - { - description: - 'should approve locking of nft if destination chain is correct', - approveLockCalled: true, - chainFeeStubCalled: true, - decodedLogs: { - tokenId: '1', // Unique ID for the NFT transfer - destinationChain: 'ETH', // Chain to where the NFT is being transferred - destinationUserAddress: '', // User's address in the destination chain - sourceNftContractAddress: - '0x0000000000000000000000000000000000000000', // Address of the NFT contract in the source chain - tokenAmount: '1', // amount of nfts to be transfered ( 1 in 721 case ) - nftType: 'single', // Sigular or multiple ( 721 / 1155) - sourceChain: 'BSC', // Source chain of NFT - }, - nftDetails: { - royalty: '500', - royaltyReceiver: '0x0000000000000000000000000000000000000000', - name: 'Dummy NFT', - symbol: 'DUM', - metadata: 'uri/1', - }, - }, - { - description: - 'should return early if destination chain is incorrect', - approveLockCalled: false, - chainFeeStubCalled: false, - decodedLogs: { - tokenId: '1', // Unique ID for the NFT transfer - destinationChain: 'SOME_NON_EXISTANT_CHAIN', // Chain to where the NFT is being transferred - destinationUserAddress: '', // User's address in the destination chain - sourceNftContractAddress: - '0x0000000000000000000000000000000000000000', // Address of the NFT contract in the source chain - tokenAmount: '1', // amount of nfts to be transfered ( 1 in 721 case ) - nftType: 'single', // Sigular or multiple ( 721 / 1155) - sourceChain: 'BSC', // Source chain of NFT - }, - nftDetails: { - royalty: '500', - royaltyReceiver: '0x0000000000000000000000000000000000000000', - name: 'Dummy NFT', - symbol: 'DUM', - metadata: 'uri/1', - }, - }, - { - description: - 'should not call approveLock of nft if destination chain is non-evm', - approveLockCalled: false, - chainFeeStubCalled: true, - decodedLogs: { - tokenId: '1', // Unique ID for the NFT transfer - destinationChain: 'nonEvmChainMock', // Chain to where the NFT is being transferred - destinationUserAddress: '', // User's address in the destination chain - sourceNftContractAddress: - '0x0000000000000000000000000000000000000000', // Address of the NFT contract in the source chain - tokenAmount: '1', // amount of nfts to be transfered ( 1 in 721 case ) - nftType: 'single', // Sigular or multiple ( 721 / 1155) - sourceChain: 'BSC', // Source chain of NFT - }, - nftDetails: { - royalty: '500', - royaltyReceiver: '0x0000000000000000000000000000000000000000', - name: 'Dummy NFT', - symbol: 'DUM', - metadata: 'uri/1', - }, - }, - ]; - - testCases.forEach( - ({ - description, - approveLockCalled, - chainFeeStubCalled, - decodedLogs, - nftDetails, - }) => { - it(description, async () => { - const chainFeeStub = sinon.stub().resolves(BigInt(100)); - const storageContractStub = { - chainFee: chainFeeStub, - }; - - const getStorageContractStub = sinon.stub( - utils, - 'getStorageContract', - ); - getStorageContractStub.returns({ - ...getStorageContractStub[1], - ...storageContractStub, - }); - - const approveLockStub = sinon - .stub(lockEventComponents, 'approveLock') - .resolves(); - sinon - .stub(evmLockEventUtils, 'getLockEventDecodedLog') - .returns(decodedLogs); - sinon - .stub(lockEventUtils, 'getNftDetails') - .resolves(nftDetails); - - const handleLog = evmLockEventUtils.getEvmLockListenerHandler({ - config: mockBridgeConfig, - evmChainConfig: mockBridgeConfig - .bridgeChains[1] as IEvmChainConfig, - wallets: mockWallets, - }); - - await handleLog({ - log: { - address: '0x5ab1fbd625cc8e343d08b0cdac9ee88e7f8f9022', - topics: [ - '0xecb797147b1fe2e559c12a8239cb04eee1f842ccc98a5b136ebd7c983ffd4854', - ], - data: '0x', - blockNumber: BigInt('4545299'), - transactionHash: - '0xe5b4bdec1c246501953bac722a748ab8ca42fdb7b000b725664561987e7e75db', - transactionIndex: BigInt('2'), - blockHash: - '0x9342d7544aa0e973fcac8fcadf6e1acf2709020a0d8f4e7666b63b71b84e059f', - logIndex: BigInt('2'), - removed: false, - }, - }); - expect(chainFeeStub.calledOnce).to.be.equals( - chainFeeStubCalled, - ); - expect(approveLockStub.calledOnce).to.be.equals( - approveLockCalled, - ); - }); - }, - ); -}); diff --git a/src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getLockEventDecodedLog.test.ts b/src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getLockEventDecodedLog.test.ts deleted file mode 100644 index a05fabd8..00000000 --- a/src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getLockEventDecodedLog.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { getLockEventDecodedLog } from '@src/modules/validator/components/nftLockListener/components/evmLockListener/utils'; -import { expect } from 'chai'; - -describe('getLockEventDecodedLog', () => { - const testCases = [ - { - description: 'should decode a Lock event log correctly', - log: { - data: '0x000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000bd9592ce5d639cd0a50b03bf024cbcad81dc91250000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000034253430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a30783637303831624438353665323964374437423330323843333441666233333166613662333138364500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000873696e67756c617200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034554480000000000000000000000000000000000000000000000000000000000', - topics: [], - }, - expectedDecodedLog: { - tokenId: '69', - destinationChain: 'BSC', - destinationUserAddress: - '0x67081bD856e29d7D7B3028C34Afb331fa6b3186E', - sourceNftContractAddress: - '0xbd9592cE5D639cD0A50b03Bf024CBCAd81dC9125', - tokenAmount: '1', - nftType: 'singular', - sourceChain: 'ETH', - }, - }, - ]; - - testCases.forEach(({ description, log, expectedDecodedLog }) => { - it(description, () => { - const decodedLog = getLockEventDecodedLog({ log }); - expect(decodedLog).to.deep.equal(expectedDecodedLog); - }); - }); -}); diff --git a/src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getNftDetails.test.ts b/src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getNftDetails.test.ts deleted file mode 100644 index b5b394fa..00000000 --- a/src/test/modules/validator/components/nftLockListener/components/evmLockListener/utils/getNftDetails.test.ts +++ /dev/null @@ -1,273 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import * as utils from '@src/utils/functions'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import { getNftDetails } from '@src/modules/validator/components/nftLockListener/utils'; - -describe('getNftDetails', () => { - const sourceNftContractAddress = '0xDummySource'; - const { evmWallet } = mockWallets; - const tokenId = '1'; - - const royalty = '500'; - const royaltyReceiver = '0xRoyaltyReceiverAddress'; - const name = 'Dummy NFT name'; - const symbol = 'DUM'; - const metadata = 'uri/1'; - - const testCases = [ - { - description: - 'should get nft details if everything resolves; singular', - name: sinon.stub().resolves(name), - symbol: sinon.stub().resolves(symbol), - royaltyInfo: sinon.stub().resolves([royaltyReceiver, royalty]), - tokenURI: sinon.stub().resolves(metadata), - nftType: 'singular', - expected: { - royalty, - royaltyReceiver, - name, - symbol, - metadata, - }, - }, - { - description: - 'should get other details if only name is rejected; singular', - name: sinon.stub().rejects(), - symbol: sinon.stub().resolves(symbol), - royaltyInfo: sinon.stub().resolves([royaltyReceiver, royalty]), - tokenURI: sinon.stub().resolves(metadata), - nftType: 'singular', - expected: { - royalty, - royaltyReceiver, - name: '', - symbol, - metadata, - }, - }, - { - description: - 'should get other details if only symbol is rejected; singular', - name: sinon.stub().resolves(name), - symbol: sinon.stub().rejects(), - royaltyInfo: sinon.stub().resolves([royaltyReceiver, royalty]), - tokenURI: sinon.stub().resolves(metadata), - nftType: 'singular', - expected: { - royalty, - royaltyReceiver, - name, - symbol: '', - metadata, - }, - }, - { - description: - 'should get other details if only royalty info is rejected; singular', - name: sinon.stub().resolves(name), - symbol: sinon.stub().resolves(symbol), - royaltyInfo: sinon.stub().rejects(), - tokenURI: sinon.stub().resolves(metadata), - nftType: 'singular', - expected: { - royalty: '0', - royaltyReceiver: '0x0000000000000000000000000000000000000000', - name, - symbol, - metadata, - }, - }, - { - description: - 'should get other details if only meta data is rejected; singular', - name: sinon.stub().resolves(name), - symbol: sinon.stub().resolves(symbol), - royaltyInfo: sinon.stub().resolves([royaltyReceiver, royalty]), - tokenURI: sinon.stub().rejects(), - nftType: 'singular', - expected: { - royalty, - royaltyReceiver, - name, - symbol, - metadata: '', - }, - }, - { - description: - 'should get empty nft details if everything rejects; singular', - name: sinon.stub().rejects(), - symbol: sinon.stub().rejects(), - royaltyInfo: sinon.stub().rejects(), - tokenURI: sinon.stub().rejects(), - nftType: 'singular', - expected: { - royalty: '0', - royaltyReceiver: '0x0000000000000000000000000000000000000000', - name: '', - symbol: '', - metadata: '', - }, - }, - - // Multiple nft testcases - { - description: - 'should get nft details if everything resolves; multiple', - name: sinon.stub().resolves(name), - symbol: sinon.stub().resolves(symbol), - royaltyInfo: sinon.stub().resolves([royaltyReceiver, royalty]), - tokenURI: sinon.stub().resolves(metadata), - nftType: 'multiple', - expected: { - royalty, - royaltyReceiver, - name, - symbol, - metadata, - }, - }, - { - description: - 'should get other details if only name is rejected; multiple', - name: sinon.stub().rejects(), - symbol: sinon.stub().resolves(symbol), - royaltyInfo: sinon.stub().resolves([royaltyReceiver, royalty]), - tokenURI: sinon.stub().resolves(metadata), - nftType: 'multiple', - expected: { - royalty, - royaltyReceiver, - name: '', - symbol, - metadata, - }, - }, - { - description: - 'should get other details if only symbol is rejected; multiple', - name: sinon.stub().resolves(name), - symbol: sinon.stub().rejects(), - royaltyInfo: sinon.stub().resolves([royaltyReceiver, royalty]), - tokenURI: sinon.stub().resolves(metadata), - nftType: 'multiple', - expected: { - royalty, - royaltyReceiver, - name, - symbol: '', - metadata, - }, - }, - { - description: - 'should get other details if only royalty info is rejected; multiple', - name: sinon.stub().resolves(name), - symbol: sinon.stub().resolves(symbol), - royaltyInfo: sinon.stub().rejects(), - tokenURI: sinon.stub().resolves(metadata), - nftType: 'multiple', - expected: { - royalty: '0', - royaltyReceiver: '0x0000000000000000000000000000000000000000', - name, - symbol, - metadata, - }, - }, - { - description: - 'should get other details if only meta data is rejected; multiple', - name: sinon.stub().resolves(name), - symbol: sinon.stub().resolves(symbol), - royaltyInfo: sinon.stub().resolves([royaltyReceiver, royalty]), - tokenURI: sinon.stub().rejects(), - nftType: 'multiple', - expected: { - royalty, - royaltyReceiver, - name, - symbol, - metadata: '', - }, - }, - { - description: - 'should get empty nft details if everything rejects; multiple', - name: sinon.stub().rejects(), - symbol: sinon.stub().rejects(), - royaltyInfo: sinon.stub().rejects(), - tokenURI: sinon.stub().rejects(), - nftType: 'multiple', - expected: { - royalty: '0', - royaltyReceiver: '0x0000000000000000000000000000000000000000', - name: '', - symbol: '', - metadata: '', - }, - }, - ]; - - afterEach(() => { - sinon.restore(); - }); - beforeEach(() => { - console.info = () => {}; - }); - - testCases.forEach( - ({ - name, - symbol, - royaltyInfo, - tokenURI, - nftType, - expected, - description, - }) => { - it(description, async () => { - const evmSingleNftContractStub = { - name, - symbol, - royaltyInfo, - tokenURI, - }; - const getEvmSingleNftContract = sinon.stub( - utils, - 'getEvmSingleNftContract', - ); - getEvmSingleNftContract.returns({ - ...getEvmSingleNftContract[1], - ...evmSingleNftContractStub, - }); - - const evmMultiNftContractStub = { - royaltyInfo, - uri: tokenURI, - }; - const getEvmMultiNftContract = sinon.stub( - utils, - 'getEvmMultiNftContract', - ); - getEvmMultiNftContract.returns({ - ...getEvmMultiNftContract[1], - ...evmMultiNftContractStub, - }); - - const result = await getNftDetails({ - sourceChain: mockBridgeConfig.bridgeChains[0], - sourceNftContractAddress, - tokenId, - evmWallet, - nftType, - chainType: 'evm', - }); - expect(result).to.deep.equal(expected); - }); - }, - ); -}); diff --git a/src/test/modules/validator/components/nftLockListener/index.test.ts b/src/test/modules/validator/components/nftLockListener/index.test.ts deleted file mode 100644 index fc341db1..00000000 --- a/src/test/modules/validator/components/nftLockListener/index.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { expect } from 'chai'; -import { nftLockListener } from '@src/modules/validator/components'; -import { evmLockListener } from '@src/modules/validator/components/nftLockListener/components'; -import * as validatorUtils from '@src/modules/validator/utils'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import sinon from 'sinon'; - -describe('nftLockListener', () => { - it('should create and enqueue jobs for EVM chains', async () => { - const createJobWithWorkerStub = sinon - .stub(validatorUtils, 'createJobWithWorker') - .resolves(); - - await nftLockListener({ - config: mockBridgeConfig, - wallets: mockWallets, - }); - - // Assert that createJobWithWorker was called for each EVM chain - mockBridgeConfig.bridgeChains.forEach((chainConfig) => { - if (chainConfig.chainType === 'evm') { - const expectedJobData = { - evmChainConfig: chainConfig, - config: mockBridgeConfig, - wallets: mockWallets, - }; - const expectedJobName = `evmLockedEventListener_${chainConfig.chain}`; - const expectedJobFunction = evmLockListener; - expect( - createJobWithWorkerStub.calledWithExactly({ - jobData: expectedJobData, - jobName: expectedJobName, - jobFunction: expectedJobFunction, - }), - ).to.be.true; - } - }); - - sinon.restore(); - }); -}); diff --git a/src/test/modules/validator/components/stakingListener/index.test.ts b/src/test/modules/validator/components/stakingListener/index.test.ts deleted file mode 100644 index 485e4921..00000000 --- a/src/test/modules/validator/components/stakingListener/index.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { expect } from 'chai'; -import * as validatorUtils from '@src/modules/validator/utils'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import sinon from 'sinon'; -import stakingListenerJob from '@src/modules/validator/components/stakingListener/stakingListenerJob'; -import { stakingListener } from '@src/modules/validator/components'; - -describe('stakingListener', () => { - it('should create and enqueue jobs for stakingListener', async () => { - const createJobWithWorkerStub = sinon - .stub(validatorUtils, 'createJobWithWorker') - .resolves(); - const expectedJobData = { - config: mockBridgeConfig, - wallets: mockWallets, - }; - await stakingListener(expectedJobData); - - const expectedJobName = `stakingApprover`; - const expectedJobFunction = stakingListenerJob; - expect( - createJobWithWorkerStub.calledWithExactly({ - jobData: expectedJobData, - jobName: expectedJobName, - jobFunction: expectedJobFunction, - }), - ).to.be.true; - - sinon.restore(); - }); -}); diff --git a/src/test/modules/validator/components/stakingListener/stakingListenerJob/components/approveStake/index.test.ts b/src/test/modules/validator/components/stakingListener/stakingListenerJob/components/approveStake/index.test.ts deleted file mode 100644 index f02c6289..00000000 --- a/src/test/modules/validator/components/stakingListener/stakingListenerJob/components/approveStake/index.test.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import * as utils from '@src/utils/functions'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import { approveStake } from '@src/modules/validator/components/stakingListener/stakingListenerJob/components'; - -describe('approveStake', () => { - beforeEach(() => { - console.info = () => {}; - }); - - afterEach(() => { - sinon.restore(); - }); - const testCases = [ - { - approveStakeStubFunction: sinon - .stub() - .resolves({ hash: 'some unique hash' }), - expectError: false, - description: 'should approve stake', - }, - { - approveStakeStubFunction: sinon.stub().rejects({ - shortMessage: `execution reverted: "Signature already used"`, - }), - expectError: false, - description: 'should not throw error if already approved stake', - }, - { - approveStakeStubFunction: sinon.stub().rejects({ - shortMessage: `execution reverted: "Some other error"`, - }), - expectError: true, - description: - 'should throw error if error is not of already approved stake', - }, - ]; - - testCases.forEach( - ({ approveStakeStubFunction, expectError, description }) => { - it(description, async () => { - const storageContractStub = { - approveStake: approveStakeStubFunction, - }; - - const getStorageContractStub = sinon.stub( - utils, - 'getStorageContract', - ); - getStorageContractStub.returns({ - ...getStorageContractStub[1], - ...storageContractStub, - }); - - const storageContract = getStorageContractStub({ - evmChainConfig: mockBridgeConfig[0], - evmWallet: mockWallets.evmWallet, - }); - if (expectError) { - try { - await approveStake({ - wallets: mockWallets, - validatorAddressAndChainType: [ - { - validatorAddress: - '0x0000000000000000000000000000000000000000', - chainType: 'evm', - }, - ], - storageContract, - }); - } catch (error) { - expect(error).to.exist; - expect(error.message).to.equals( - 'Error while processing log', - ); - } - } else { - await approveStake({ - wallets: mockWallets, - validatorAddressAndChainType: [ - { - validatorAddress: - '0x0000000000000000000000000000000000000000', - chainType: 'evm', - }, - ], - storageContract, - }); - } - - expect(approveStakeStubFunction.calledOnce).to.be.true; - }); - }, - ); -}); diff --git a/src/test/modules/validator/components/stakingListener/stakingListenerJob/index.test.ts b/src/test/modules/validator/components/stakingListener/stakingListenerJob/index.test.ts deleted file mode 100644 index 3e45d480..00000000 --- a/src/test/modules/validator/components/stakingListener/stakingListenerJob/index.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { expect } from 'chai'; -import * as validatorUtils from '@src/modules/validator/utils'; -import sinon from 'sinon'; -import stakingListenerJob from '@src/modules/validator/components/stakingListener/stakingListenerJob'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; -import { LogEntry } from '@src/modules/validator/utils/evmContractListener/types'; -import * as stakingUtils from '@src/modules/validator/components/stakingListener/utils'; - -describe('stakingListenerJob', () => { - it('should call evmContractListener with the correct arguments', async () => { - const evmContractListenerStub = sinon - .stub(validatorUtils, 'evmContractListener') - .resolves(); - - const handleLogFunctionMock = async ({ log }: { log: LogEntry }) => { - console.info(log); - }; - const getStakingListenerLogHandlerStub = sinon - .stub(stakingUtils, 'getStakingListenerLogHandler') - .returns(handleLogFunctionMock); - - await stakingListenerJob({ - config: mockBridgeConfig, - wallets: mockWallets, - }); - - const { contractAddress, rpcURL, lastBlock, chain } = - mockBridgeConfig.stakingConfig; - const handleLog = getStakingListenerLogHandlerStub({ - config: mockBridgeConfig, - wallets: mockWallets, - }); - - expect( - evmContractListenerStub.calledWithExactly({ - contractAddress, - rpcURL, - lastBlock_: lastBlock, - chain, - handleLog, - }), - ).to.be.true; - - sinon.restore(); - }); -}); diff --git a/src/test/modules/validator/components/stakingListener/utils/getStakeEventDecodedLog.test.ts b/src/test/modules/validator/components/stakingListener/utils/getStakeEventDecodedLog.test.ts deleted file mode 100644 index 247bed90..00000000 --- a/src/test/modules/validator/components/stakingListener/utils/getStakeEventDecodedLog.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { getStakeEventDecodedLog } from '@src/modules/validator/components/stakingListener/utils'; -import { expect } from 'chai'; - -describe('getLockEventDecodedLog', () => { - const testCases = [ - { - description: 'should decode a stake event log correctly', - log: { - data: '0x0000000000000000000000000000000000000000000000056bc75e2d63100000', - topics: [ - '0x9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d', - '0x00000000000000000000000067081bd856e29d7d7b3028c34afb331fa6b3186e', - ], - }, - expectedDecodedLog: '0x67081bD856e29d7D7B3028C34Afb331fa6b3186E', - }, - ]; - - testCases.forEach(({ description, log, expectedDecodedLog }) => { - it(description, () => { - const decodedLog = getStakeEventDecodedLog({ log }); - expect(decodedLog).to.deep.equal(expectedDecodedLog); - }); - }); -}); diff --git a/src/test/modules/validator/components/stakingListener/utils/getStakingListenerLogHandler.test.ts b/src/test/modules/validator/components/stakingListener/utils/getStakingListenerLogHandler.test.ts deleted file mode 100644 index 12e4cfb7..00000000 --- a/src/test/modules/validator/components/stakingListener/utils/getStakingListenerLogHandler.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import sinon from 'sinon'; -import { expect } from 'chai'; -import * as stakingEventUtils from '@src/modules/validator/components/stakingListener/utils'; -import * as stakingComponents from '@src/modules/validator/components/stakingListener/stakingListenerJob/components'; -import { mockBridgeConfig, mockWallets } from '@src/test/mockData'; - -describe('getStakingListenerLogHandler', () => { - beforeEach(() => { - console.info = () => {}; - }); - - afterEach(() => { - sinon.restore(); - }); - - it('should be able to approve stake', async () => { - const getStakeEventDecodedLogStub = sinon - .stub(stakingEventUtils, 'getStakeEventDecodedLog') - .returns({ - validatorAddressAndChainType: [ - { - validatorAddress: - '0x8f1fd3a5dbbd5659579ae7d9b258cc6cbcb3e53d', - chainType: 'evm', - }, - ], - }); - const approveStakeStub = sinon - .stub(stakingComponents, 'approveStake') - .resolves(); - - const handleLog = stakingEventUtils.getStakingListenerLogHandler({ - config: mockBridgeConfig, - wallets: mockWallets, - }); - - await handleLog({ - log: { - address: '0x8f1fd3a5dbbd5659579ae7d9b258cc6cbcb3e53d', - topics: [ - '0x9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d', - '0x00000000000000000000000067081bd856e29d7d7b3028c34afb331fa6b3186e', - ], - data: '0x0000000000000000000000000000000000000000000000056bc75e2d63100000', - blockNumber: BigInt('34603042'), - transactionHash: - '0x9f82e0133481e667af275a047daa7113fce293101c2af792fed5676df6ee5ada', - transactionIndex: BigInt(1), - blockHash: - '0x89fd9da1073ee98652c17b1d5700cb10a79fcc9262bc63dcf4e1fb75ecf8616a', - logIndex: BigInt(9), - removed: false, - }, - }); - - expect(getStakeEventDecodedLogStub.calledOnce).to.be.true; - expect(approveStakeStub.calledOnce).to.be.true; - }); -}); diff --git a/src/test/modules/validator/utils/createJobWithWorker/index.test.ts b/src/test/modules/validator/utils/createJobWithWorker/index.test.ts deleted file mode 100644 index 26a3bdd7..00000000 --- a/src/test/modules/validator/utils/createJobWithWorker/index.test.ts +++ /dev/null @@ -1 +0,0 @@ -// @TODO add testcases for createJobWithWorker diff --git a/src/test/modules/validator/utils/evmContractListener/index.test.ts b/src/test/modules/validator/utils/evmContractListener/index.test.ts deleted file mode 100644 index 673448c8..00000000 --- a/src/test/modules/validator/utils/evmContractListener/index.test.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { expect } from 'chai'; -import sinon from 'sinon'; -import { Repository } from 'typeorm'; -import Web3 from 'web3'; -import { Block } from '@src/db/entity/Block'; -import { evmContractListener } from '@src/modules/validator/utils'; // Import your function here -import { LogEntry } from '@src/modules/validator/utils/evmContractListener/types'; // Import your types here -import { AppDataSource } from '@src/db/data-source'; -import { BLOCK_CHUNKS } from '@src/config/chainSpecs'; - -describe('evmContractListener', () => { - afterEach(() => { - sinon.restore(); - }); - - const testCases = [ - { - description: - 'should handle logs and update the last block when there are logs', - contractAddress: '0xContract1', - rpcURL: 'mockRpcURL', - lastBlock_: 0, - chain: 'mockChain', - logs: ['Log1', 'Log2'], - handleLog: async ({ log }: { log: LogEntry }) => { - console.info(log); - }, - expectedLastBlock: 110, - latestBlock: BigInt('110'), - }, - { - description: - 'should handle logs and update the last block when there are no logs', - contractAddress: '0xContract1', - rpcURL: 'mockRpcURL', - lastBlock_: 0, - chain: 'mockChain', - logs: [], - handleLog: async ({ log }: { log: LogEntry }) => { - console.info(log); - }, - expectedLastBlock: 110, - latestBlock: BigInt('110'), - }, - { - description: - 'should use BLOCK_CHUNKS if the latest block is greater than the BLOCK_CHUNKS size, and no previous logs were read', - contractAddress: '0xContract1', - rpcURL: 'mockRpcURL', - lastBlock_: 0, - chain: 'mockChain', - logs: [], - handleLog: async ({ log }: { log: LogEntry }) => { - console.info(log); - }, - expectedLastBlock: BLOCK_CHUNKS, - latestBlock: BigInt(BLOCK_CHUNKS + 56745), - }, - { - description: - 'should use BLOCK_CHUNKS + lastBlock_ if the latest block is greater than BLOCK_CHUNKS + lastBlock_, and previous logs were read', - contractAddress: '0xContract1', - rpcURL: 'mockRpcURL', - lastBlock_: 5000, - chain: 'mockChain', - logs: [], - handleLog: async ({ log }: { log: LogEntry }) => { - console.info(log); - }, - expectedLastBlock: BLOCK_CHUNKS + 5000, - latestBlock: BigInt(BLOCK_CHUNKS + 56757 + 5000), - }, - ]; - - testCases.forEach( - ({ - description, - contractAddress, - rpcURL, - lastBlock_, - chain, - handleLog, - expectedLastBlock, - latestBlock, - logs, - }) => { - it(description, async () => { - const getBlockNumberStub = sinon.stub().resolves(latestBlock); - const getPastLogsStub = sinon.stub().resolves(logs); - - Object.setPrototypeOf( - Web3, - sinon.stub().returns({ - request: sinon.stub().resolves(), - use: sinon.stub().returns({ - getBlockNumber: getBlockNumberStub, - getPastLogs: getPastLogsStub, - }), - }), - ); - - const blockRepositorySaveStub = sinon.stub(); - const blockRepositoryFindOneStub = sinon - .stub() - .resolves({ chain, contractAddress }); - - blockRepositorySaveStub.resolves({ - chain, - contractAddress, - lastBlock: expectedLastBlock, - }); // Simulate saving the block instance - - sinon.stub(AppDataSource, 'getRepository').returns({ - findOne: blockRepositoryFindOneStub, - save: blockRepositorySaveStub, - } as unknown as Repository); - - await evmContractListener({ - contractAddress, - rpcURL, - lastBlock_, - chain, - handleLog, - }); - - expect(getBlockNumberStub.calledOnce).to.be.true; - expect( - getPastLogsStub.calledOnceWith({ - fromBlock: lastBlock_, - toBlock: expectedLastBlock, - address: contractAddress, - }), - ).to.be.true; - expect( - blockRepositoryFindOneStub.calledOnceWith({ - where: { chain, contractAddress }, - }), - ).to.be.true; - expect( - blockRepositorySaveStub.calledOnceWith({ - chain, - contractAddress, - lastBlock: expectedLastBlock, - }), - ).to.be.true; - }); - }, - ); -}); diff --git a/src/tests/configs.ts b/src/tests/configs.ts new file mode 100644 index 00000000..ea0d499c --- /dev/null +++ b/src/tests/configs.ts @@ -0,0 +1,35 @@ +import { + IEvmChainConfig, + IHederaChainConfig, + IMultiversXChainConfig, + ISecretChainConfig, + ITezosChainConfig, + ITonChainConfig, + TChain, +} from '@src/types'; + +export function getConfigs(bridgeTestChains: TChain[]) { + return { + bsc: bridgeTestChains.find( + (e) => e.chain === 'BSC', + )! as IEvmChainConfig, + eth: bridgeTestChains.find( + (e) => e.chain === 'ETH', + )! as IEvmChainConfig, + hedera: bridgeTestChains.find( + (e) => e.chain === 'HEDERA', + )! as IHederaChainConfig, + tezos: bridgeTestChains.find( + (e) => e.chain === 'TEZOS', + )! as ITezosChainConfig, + multiversx: bridgeTestChains.find( + (e) => e.chain === 'MULTIVERSX', + )! as IMultiversXChainConfig, + secret: bridgeTestChains.find( + (e) => e.chain === 'SECRET', + )! as ISecretChainConfig, + ton: bridgeTestChains.find( + (e) => e.chain === 'TON', + )! as ITonChainConfig, + }; +} diff --git a/src/tests/data.ts b/src/tests/data.ts new file mode 100644 index 00000000..3248725d --- /dev/null +++ b/src/tests/data.ts @@ -0,0 +1,73 @@ +import { IGeneratedWallets } from '@src/types'; +import { JsonRpcProvider, Wallet } from 'ethers'; +import { getConfigs } from './configs'; +import { UserSigner } from '@multiversx/sdk-wallet/out'; +import { InMemorySigner } from '@taquito/signer'; +import { WalletContractV4 } from 'ton'; +import { Wallet as SecretWallet } from 'secretjs'; +import TonWeb from 'tonweb'; + +export async function generateData( + genWallets: IGeneratedWallets, + configs: ReturnType, +) { + const tonweb = new TonWeb(new TonWeb.HttpProvider(configs.ton.rpcURL)); + + const walletClass = tonweb.wallet.all['v4R2']; + + const wallet = new walletClass(tonweb.provider, { + publicKey: TonWeb.utils.hexToBytes(genWallets.tonWallet.publicKey), + }); + return { + bsc: { + signer: new Wallet( + genWallets.evmWallet.privateKey, + new JsonRpcProvider(configs.bsc.rpcURL), + ), + config: configs.bsc, + address: genWallets.evmWallet.address, + }, + hedera: { + signer: new Wallet(genWallets.evmWallet.privateKey), + config: configs.hedera, + + address: genWallets.evmWallet.address, + }, + multiversx: { + signer: UserSigner.fromWallet( + genWallets.multiversXWallet.userWallet, + genWallets.multiversXWallet.password, + ), + config: configs.multiversx, + address: genWallets.multiversXWallet.userWallet.address, + }, + eth: { + signer: new Wallet( + genWallets.evmWallet.privateKey, + new JsonRpcProvider(configs.eth.rpcURL), + ), + config: configs.eth, + address: genWallets.evmWallet.address, + }, + tezos: { + signer: new InMemorySigner(genWallets.tezosWallet.secretKey), + config: configs.tezos, + address: await new InMemorySigner( + genWallets.tezosWallet.secretKey, + ).publicKeyHash(), + }, + secret: { + signer: new SecretWallet(genWallets.secretWallet.privateKey), + config: configs.secret, + address: genWallets.secretWallet.publicKey, + }, + ton: { + signer: WalletContractV4.create({ + publicKey: Buffer.from(genWallets.tonWallet.publicKey, 'hex'), + workchain: 0, + }), + config: configs.ton, + address: (await wallet.getAddress()).toString(), + }, + }; +} diff --git a/src/tests/generic-test.ts b/src/tests/generic-test.ts new file mode 100644 index 00000000..d957056a --- /dev/null +++ b/src/tests/generic-test.ts @@ -0,0 +1,210 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { JsonRpcProvider } from 'ethers'; +import { generateWalletsForChains } from '../modules/setup/components'; +import { bridgeTestChains, testnetBridgeConfig } from '../config/chainSpecs'; +import { ERC721Royalty } from '../contractsTypes'; +import { getEvmSingleNftContract, waitForMSWithMsg } from '../utils'; +import { SignerAndSignature, TChain } from '../types'; +import { CodeInfo } from '../utils/functions/getSecretBridgeContract'; +import { + ChainFactory, + ChainFactoryConfigs, + MetaMap, +} from 'xp-decentralized-sdk'; +import { getSigners } from './signers'; +import { getConfigs } from './configs'; +import { generateData } from './data'; +import { promptToGetFunding } from '@src/modules/setup/components/getInitialFunds/components'; +import { deployEVMNftContract } from './mint'; + +(async () => { + const genWallets = await generateWalletsForChains(); + const factory = ChainFactory(ChainFactoryConfigs.TestNet()); + + let result = false; + + while (!result) { + result = await promptToGetFunding({ + wallets: genWallets, + config: testnetBridgeConfig, + }); + } + + // Assuming we have enough funds on the validator accounts itself. + + const signers = getSigners(genWallets); + const configs = getConfigs(bridgeTestChains as unknown as TChain[]); + const data = await generateData(genWallets, configs); + + // Create a NFT Contract + console.log(`Deploying NFT Contract on BSC`); + let contract: ERC721Royalty; + let deployed = false; + + while (!deployed) { + try { + contract = await deployEVMNftContract({ + evmChainConfig: configs.bsc, + evmWallet: signers.bsc, + }); + deployed = true; + } catch (e) { + `Retrying to deploy NFT Contract on BSC`; + } + } + + // Mint 5 NFT on the contract + for (let i = 0; i < 1; i++) { + let minted = false; + while (!minted) { + try { + await contract!.mint( + signers.bsc.address, + i, + 10, + signers.bsc.address, + 'https://meta.polkamon.com/meta?id=10001852306', + ); + minted = true; + } catch (e) { + console.log(`Retrying to mint NFT on BSC`); + } + } + } + console.log('Minted 1 NFTs ON BSC'); + + // Approve the contract to spend the NFTs + const nftC = getEvmSingleNftContract( + { + contractAddress: await contract!.getAddress(), + rpcURL: configs.bsc.rpcURL, + }, + data.bsc.signer.connect(new JsonRpcProvider(data.bsc.config.rpcURL)), + ); + for (let i = 0; i < 1; i++) { + let approved = false; + while (!approved) { + try { + await nftC.approve(BigInt(i), data.bsc.config.contractAddress); + approved = true; + } catch (e: any) { + console.log( + `Retrying to approve NFT on BSC`, + console.log(e.shortMessage), + ); + } + } + } + console.log(`Approved NFTs on BSC`); + + // Lock the NFTs + async function transfer( + args: [ + { + fromChain: (typeof data)[keyof typeof data]; + toChain: (typeof data)[keyof typeof data]; + tokenId: string; + contractAddress: string; + codeInfo?: CodeInfo; + nonce?: string; + nftType: 'singular' | 'multiple'; + }, + ], + ) { + for (const tx of args) { + const chain = await factory.inner( + tx.fromChain.config.chain as keyof MetaMap, + ); + let locked = false; + let lockHash: string = ''; + while (!locked) { + try { + const lock = await chain.lockNft( + tx.fromChain.signer as any, + tx.contractAddress, + tx.toChain.config.chain as keyof MetaMap, + tx.toChain.address, + BigInt(tx.tokenId), + { gasLimit: 1000000 }, + ); + console.log(`Lock Hash:`, lock.hash()); + await (lock.tx as any).wait(); + locked = true; + lockHash = lock.hash(); + } catch (e: any) { + console.log( + `Retrying to lock NFT on ${tx.fromChain.config.chain}`, + e.shortMessage, + ); + } + } + + console.log(`Finding Claim Data for Lock Hash: ${lockHash}`); + + const nftDetails = await factory.getClaimData(chain, lockHash); + console.log(nftDetails); + console.log(`Got Claim Data`); + + console.log(`Fetching Signatures`); + + const tc = await factory.inner( + tx.toChain.config.chain as keyof MetaMap, + ); + + let signatures = await tc + .getStorageContract() + .getLockNftSignatures(lockHash, tx.fromChain.config.chain); + const neededSignatures = + Math.floor((2 / 3) * Number(await tc.getValidatorCount())) + 1; + while (signatures.length < neededSignatures) { + await waitForMSWithMsg( + 1000, + `waiting for signatures, ${signatures.length}`, + ); + signatures = await tc + .getStorageContract() + .getLockNftSignatures(lockHash, tx.fromChain.config.chain); + } + + const signatureArray: SignerAndSignature[] = []; + signatures.forEach((item) => { + signatureArray.push({ + signer: item.signerAddress, + signature: item.signature, + }); + }); + + let claimed = false; + while (!claimed) + try { + const claim = await tc.claimNft( + tx.toChain.signer as any, + tc.transform(nftDetails) as any, + {}, + signatureArray, + ); + console.log( + `Claimed on ${tx.toChain.config.chain} at ${claim}`, + ); + claimed = true; + return ''; + } catch (e) { + console.log(e); + console.log(`Retrying Claiming`); + } + } + return ''; + } + + await transfer([ + { + fromChain: data.bsc, + toChain: data.eth, + contractAddress: await contract!.getAddress(), + tokenId: '0', + nftType: 'singular', + }, + ]); +})().catch((e) => { + console.error(e); +}); diff --git a/src/tests/mint.ts b/src/tests/mint.ts new file mode 100644 index 00000000..98e3d740 --- /dev/null +++ b/src/tests/mint.ts @@ -0,0 +1,43 @@ +import { createInterface } from 'node:readline'; + +import { JsonRpcProvider, Wallet, isAddress } from 'ethers'; +import { ERC721Royalty__factory } from '@src/contractsTypes'; +import { IEvmChainConfigAndEvmWallet } from '@src/types'; + +const readline = createInterface({ + input: process.stdin, + output: process.stdout, +}); + +function question(query: string) { + return new Promise((resolve) => { + readline.question(query, resolve); + }); +} + +export async function deployEVMNftContract( + tchain: IEvmChainConfigAndEvmWallet, +) { + const sa = await question( + 'To Deploy new contract press Y or pass a nft Contract Address', + ); + const is = isAddress(sa); + if (is) { + return ERC721Royalty__factory.connect( + sa, + new JsonRpcProvider(tchain.evmChainConfig.rpcURL), + ); + } else { + const wallet = new Wallet( + tchain.evmWallet.privateKey, + new JsonRpcProvider(tchain.evmChainConfig.rpcURL), + ); + const factory = new ERC721Royalty__factory(wallet); + const contract = await factory.deploy( + 'TestContract', + 'TC', + wallet.address, + ); + return contract; + } +} diff --git a/src/tests/signers.ts b/src/tests/signers.ts new file mode 100644 index 00000000..da28d03f --- /dev/null +++ b/src/tests/signers.ts @@ -0,0 +1,22 @@ +import { UserSigner } from '@multiversx/sdk-wallet/out'; +import { IGeneratedWallets } from '@src/types'; +import { InMemorySigner } from '@taquito/signer'; +import { Wallet } from 'ethers'; +import { keyPairFromSecretKey } from 'ton-crypto'; +import { Wallet as SecretWallet } from 'secretjs'; + +export function getSigners(genWallets: IGeneratedWallets) { + return { + bsc: new Wallet(genWallets.evmWallet.privateKey), + eth: new Wallet(genWallets.evmWallet.privateKey), + tezos: new InMemorySigner(genWallets.tezosWallet.secretKey), + multiversx: UserSigner.fromWallet( + genWallets.multiversXWallet.userWallet, + genWallets.multiversXWallet.password, + ), + secret: new SecretWallet(genWallets.secretWallet.privateKey), + ton: keyPairFromSecretKey( + Buffer.from(genWallets.tonWallet.secretKey, 'hex'), + ), + }; +} diff --git a/yarn.lock b/yarn.lock index 17bd51e2..32eda2c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7393,7 +7393,7 @@ ws@^8.8.1: "xp-decentralized-sdk@git+https://github.com/XP-NETWORK/xp-decentralized-client-library#bleeding-edge": version "1.0.0" - resolved "git+https://github.com/XP-NETWORK/xp-decentralized-client-library#5b1a40323e9ef9cebe862974e6942f8a3aa9e2f0" + resolved "git+https://github.com/XP-NETWORK/xp-decentralized-client-library#449d53e85f6500d5d4dc8d455131d96af83893e4" dependencies: "@multiversx/sdk-core" "^12.18.0" "@multiversx/sdk-network-providers" "^2.2.1"