withdrawTwo.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import * as anchor from "@coral-xyz/anchor";
  2. import { decode, mapProof } from "../utils";
  3. import { PROGRAM_ID as BUBBLEGUM_PROGRAM_ID } from "@metaplex-foundation/mpl-bubblegum";
  4. import {
  5. SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
  6. SPL_NOOP_PROGRAM_ID,
  7. } from "@solana/spl-account-compression";
  8. import { getAsset, getAssetProof } from "../readAPI";
  9. import { AccountMeta } from "@solana/web3.js";
  10. import { program, programID } from "./constants";
  11. async function main() {
  12. // TODO change all of these to your values
  13. const assetId1 = "DGWU3mHenDerCvjkeDsKYEbsvXbWvqdo1bVoXy3dkeTd";
  14. const assetId2 = "14JojSTdBZvP7f77rCxB3oQK78skTVD6DiXrXUL4objg"; //"D2CoMLCRfsfv1EAiNbaBHfoU1Sqf1964KXLGxEfyUwWo";
  15. const tree1 = new anchor.web3.PublicKey(
  16. "trezdkTFPKyj4gE9LAJYPpxn8AYVCvM7Mc4JkTb9X5B"
  17. );
  18. const tree2 = new anchor.web3.PublicKey(
  19. "Feywkti8LLBLfxhSGmYgzUBqpq89qehfB1SMTYV1zCu"
  20. );
  21. const receiver1 = new anchor.web3.PublicKey(
  22. "Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM"
  23. );
  24. const receiver2 = new anchor.web3.PublicKey(
  25. "Andys9wuoMdUeRiZLgRS5aJwYNFv4Ut6qQi8PNDTAPEM"
  26. );
  27. // ---
  28. const [vaultPDA, _bump] = anchor.web3.PublicKey.findProgramAddressSync(
  29. [Buffer.from("cNFT-vault", "utf8")],
  30. programID
  31. );
  32. const [treeAuthority1, _bump2] = anchor.web3.PublicKey.findProgramAddressSync(
  33. [tree1.toBuffer()],
  34. BUBBLEGUM_PROGRAM_ID
  35. );
  36. const [treeAuthority2, _bump3] = anchor.web3.PublicKey.findProgramAddressSync(
  37. [tree2.toBuffer()],
  38. BUBBLEGUM_PROGRAM_ID
  39. );
  40. const asset1 = await getAsset(assetId1);
  41. const asset2 = await getAsset(assetId2);
  42. const proof1 = await getAssetProof(assetId1);
  43. const proofPathAsAccounts1 = mapProof(proof1);
  44. const proof2 = await getAssetProof(assetId2);
  45. const proofPathAsAccounts2 = mapProof(proof2);
  46. const ixData1 = getInstructionData(asset1, proof1);
  47. const ixData2 = getInstructionData(asset2, proof2);
  48. const remainingAccounts: AccountMeta[] = [
  49. ...proofPathAsAccounts1,
  50. ...proofPathAsAccounts2,
  51. ];
  52. const tx = await program.methods
  53. .withdrawTwoCnfts(...ixData1, ...ixData2)
  54. .accounts({
  55. leafOwner: vaultPDA,
  56. merkleTree1: tree1,
  57. newLeafOwner1: receiver1,
  58. treeAuthority1: treeAuthority1,
  59. merkleTree2: tree2,
  60. newLeafOwner2: receiver2,
  61. treeAuthority2: treeAuthority2,
  62. bubblegumProgram: BUBBLEGUM_PROGRAM_ID,
  63. compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
  64. logWrapper: SPL_NOOP_PROGRAM_ID,
  65. systemProgram: anchor.web3.SystemProgram.programId,
  66. })
  67. .remainingAccounts(remainingAccounts)
  68. .rpc();
  69. console.log(tx);
  70. }
  71. function getInstructionData(
  72. asset: any,
  73. proof: any
  74. ): [number[], number[], number[], anchor.BN, number, number] {
  75. const root = decode(proof.root);
  76. const dataHash = decode(asset.compression.data_hash);
  77. const creatorHash = decode(asset.compression.creator_hash);
  78. const nonce = new anchor.BN(asset.compression.leaf_id);
  79. const index = asset.compression.leaf_id;
  80. const proofLength = proof.proof.length;
  81. return [root, dataHash, creatorHash, nonce, index, proofLength];
  82. }
  83. main();