compressed-nft.sol 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import "solana";
  2. @program_id("BvgEJTPXfriGPopjJr1nLc4vADXm7A7TqjLFVztpd19Q")
  3. contract compressed_nft {
  4. @payer(payer) // payer address
  5. @seed("seed") // hardcoded seed
  6. constructor(
  7. @bump bytes1 bump // bump seed for pda address
  8. ) {
  9. // Creating a dataAccount for the program, which is required by Solang
  10. // However, this account is not used in the program
  11. }
  12. // Mint a compressed NFT to an existing merkle tree, via a cross-program invocation to the Bubblegum program
  13. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/lib.rs#L922
  14. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/lib.rs#L67
  15. @mutableAccount(tree_authority) // authority of the merkle tree
  16. @account(leaf_owner) // owner of the new compressed NFT
  17. @account(leaf_delegate) // delegate of the new compressed NFT (can be the same as leaf_owner)
  18. @mutableAccount(merkle_tree) // address of the merkle tree
  19. @mutableSigner(payer) // payer
  20. @mutableSigner(tree_delegate) // delegate of the merkle tree
  21. @account(noop_address)
  22. @account(compression_pid)
  23. @account(bubblegum_pid)
  24. function mint(
  25. string uri // uri of the new compressed NFT (metadata)
  26. ) external {
  27. print("Minting Compressed NFT");
  28. // Create a creator array with a single creator
  29. Creator[] memory creators = new Creator[](1);
  30. // Set the creator to the payer
  31. creators[0] = Creator({
  32. creatorAddress: tx.accounts.payer.key,
  33. verified: false,
  34. share: 100
  35. });
  36. // Create the metadata args, representing the metadata of the new compressed NFT
  37. // Solidity does not support optional arguments,
  38. // So we have to explicitly declare if the optional arguments are present or not
  39. // If not present, we comment them out, otherwise the transaction will fail with a invalid instruction data error
  40. MetadataArgs memory args = MetadataArgs({
  41. name: "RGB",
  42. symbol: "RGB",
  43. uri: uri,
  44. sellerFeeBasisPoints: 0,
  45. primarySaleHappened: false,
  46. isMutable: true,
  47. editionNoncePresent: false,
  48. // editionNonce: 0,
  49. tokenStandardPresent: true,
  50. tokenStandard: TokenStandard.NonFungible,
  51. collectionPresent: false,
  52. // collection: Collection({
  53. // verified: false,
  54. // key: address(0)
  55. // }),
  56. usesPresent: false,
  57. // uses: Uses({
  58. // useMethod: UseMethod.Burn,
  59. // remaining: 0,
  60. // total: 0
  61. // }),
  62. tokenProgramVersion: TokenProgramVersion.Original,
  63. creators: creators
  64. });
  65. AccountMeta[9] metas = [
  66. AccountMeta({pubkey: tx.accounts.tree_authority.key, is_writable: true, is_signer: false}),
  67. AccountMeta({pubkey: tx.accounts.leaf_owner.key, is_writable: false, is_signer: false}),
  68. AccountMeta({pubkey: tx.accounts.leaf_delegate.key, is_writable: false, is_signer: false}),
  69. AccountMeta({pubkey: tx.accounts.merkle_tree.key, is_writable: true, is_signer: false}),
  70. AccountMeta({pubkey: tx.accounts.payer.key, is_writable: true, is_signer: true}),
  71. AccountMeta({pubkey: tx.accounts.tree_delegate.key, is_writable: true, is_signer: true}),
  72. AccountMeta({pubkey: tx.accounts.noop_address.key, is_writable: false, is_signer: false}),
  73. AccountMeta({pubkey: tx.accounts.compression_pid.key, is_writable: false, is_signer: false}),
  74. AccountMeta({pubkey: address"11111111111111111111111111111111", is_writable: false, is_signer: false})
  75. ];
  76. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/js/src/generated/instructions/mintV1.ts#L64
  77. bytes8 discriminator = 0x9162c076b8937668;
  78. bytes instructionData = abi.encode(discriminator, args);
  79. // Invoking the Bubblegum program
  80. tx.accounts.bubblegum_pid.key.call{accounts: metas}(instructionData);
  81. }
  82. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L81
  83. struct MetadataArgs {
  84. string name;
  85. string symbol;
  86. string uri;
  87. uint16 sellerFeeBasisPoints;
  88. bool primarySaleHappened;
  89. bool isMutable;
  90. bool editionNoncePresent;
  91. // uint8 editionNonce;
  92. bool tokenStandardPresent;
  93. TokenStandard tokenStandard;
  94. bool collectionPresent;
  95. // Collection collection;
  96. bool usesPresent;
  97. // Uses uses;
  98. TokenProgramVersion tokenProgramVersion;
  99. Creator[] creators;
  100. }
  101. enum TokenStandard {
  102. NonFungible,
  103. FungibleAsset,
  104. Fungible,
  105. NonFungibleEdition
  106. }
  107. enum TokenProgramVersion {
  108. Original,
  109. Token2022
  110. }
  111. struct Creator {
  112. address creatorAddress;
  113. bool verified;
  114. uint8 share;
  115. }
  116. struct Collection {
  117. bool verified;
  118. address key;
  119. }
  120. struct Uses {
  121. UseMethod useMethod;
  122. uint64 remaining;
  123. uint64 total;
  124. }
  125. enum UseMethod {
  126. Burn,
  127. Multiple,
  128. Single
  129. }
  130. }