import * as anchor from "@project-serum/anchor"; import { CnftVault } from "../target/types/cnft_vault"; import { loadWalletKey, decode, mapProof } from "./utils"; import { IDL } from "../target/types/cnft_vault" import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum"; import { SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, SPL_NOOP_PROGRAM_ID } from "@solana/spl-account-compression"; import { getAsset, getAssetProof } from "./readAPI"; import { AccountMeta } from "@solana/web3.js"; const connection = new anchor.web3.Connection("https://api.devnet.solana.com"); const keypair = loadWalletKey("../AndYPfCmbSSHpe2yukLXDT9N29twa7kJDk3yrRMQW7SN.json"); const wallet = new anchor.Wallet(keypair); const provider = new anchor.AnchorProvider(connection, wallet, {}); const programID = new anchor.web3.PublicKey("CNftyK7T8udPwYRzZUMWzbh79rKrz9a5GwV2wv7iEHpk") const program = new anchor.Program(IDL, programID, provider); async function main() { // TODO change all of these to your values const assetId1 = "DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd"; const assetId2 = "14JojSTdBZvP7f77rCxB3oQK78skTVD6DiXrXUL4objg";//"D2CoMLCRfsfv1EAiNbaBHfoU1Sqf1964KXLGxEfyUwWo"; const tree1 = new anchor.web3.PublicKey("trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B") const tree2 = new anchor.web3.PublicKey("Feywkti8LLBLfxhSGmYgzUBqpq89qehfB1SMTYV1zCu") const receiver1 = new anchor.web3.PublicKey("Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM") const receiver2 = new anchor.web3.PublicKey("Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM") // --- const [vaultPDA, _bump] = anchor.web3.PublicKey.findProgramAddressSync( [Buffer.from("cNFT-vault", "utf8")], programID, ); const [treeAuthority1, _bump2] = anchor.web3.PublicKey.findProgramAddressSync( [tree1.toBuffer()], BUBBLEGUM_PROGRAM_ID, ); const [treeAuthority2, _bump3] = anchor.web3.PublicKey.findProgramAddressSync( [tree2.toBuffer()], BUBBLEGUM_PROGRAM_ID, ); const asset1 = await getAsset(assetId1); const asset2 = await getAsset(assetId2); const proof1 = await getAssetProof(assetId1); const proofPathAsAccounts1 = mapProof(proof1); const proof2 = await getAssetProof(assetId2); const proofPathAsAccounts2 = mapProof(proof2); const ixData1 = getInstructionData(asset1, proof1); const ixData2 = getInstructionData(asset2, proof2); const remainingAccounts: AccountMeta[] = [...proofPathAsAccounts1, ...proofPathAsAccounts2]; const tx = await program.methods.withdrawTwoCnfts(...ixData1, ...ixData2) .accounts({ leafOwner: vaultPDA, merkleTree1: tree1, newLeafOwner1: receiver1, treeAuthority1: treeAuthority1, merkleTree2: tree2, newLeafOwner2: receiver2, treeAuthority2: treeAuthority2, bubblegumProgram: BUBBLEGUM_PROGRAM_ID, compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, logWrapper: SPL_NOOP_PROGRAM_ID, systemProgram: anchor.web3.SystemProgram.programId }) .remainingAccounts(remainingAccounts) .rpc(); console.log(tx); }; function getInstructionData(asset: any, proof: any): [number[], number[], number[], anchor.BN, number, number] { const root = decode(proof.root); const dataHash = decode(asset.compression.data_hash); const creatorHash = decode(asset.compression.creator_hash); const nonce = new anchor.BN(asset.compression.leaf_id); const index = asset.compression.leaf_id; const proofLength = proof.proof.length; return [root, dataHash, creatorHash, nonce, index, proofLength]; } main();