mpl_metadata.sol 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import 'solana';
  2. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/instruction/metadata.rs#L449
  3. // Solidity does not support Rust Option<> type, so we need to handle it manually
  4. // Requires creating a struct for each combination of Option<> types
  5. // If bool for Option<> type is false, comment out the corresponding struct field otherwise instruction fails with "invalid account data"
  6. // TODO: figure out better way to handle Option<> types
  7. library MplMetadata {
  8. address constant metadataProgramId = address"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
  9. address constant systemAddress = address"11111111111111111111111111111111";
  10. address constant rentAddress = address"SysvarRent111111111111111111111111111111111";
  11. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/instruction/metadata.rs#L31
  12. struct CreateMetadataAccountArgsV3 {
  13. DataV2 data;
  14. bool isMutable;
  15. bool collectionDetailsPresent; // To handle Rust Option<> in Solidity
  16. // CollectionDetails collectionDetails;
  17. }
  18. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/state/data.rs#L22
  19. struct DataV2 {
  20. string name;
  21. string symbol;
  22. string uri;
  23. uint16 sellerFeeBasisPoints;
  24. bool creatorsPresent; // To handle Rust Option<> in Solidity
  25. // Creator[] creators;
  26. bool collectionPresent; // To handle Rust Option<> in Solidity
  27. // Collection collection;
  28. bool usesPresent; // To handle Rust Option<> in Solidity
  29. // Uses uses;
  30. }
  31. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L10
  32. struct Creator {
  33. address creatorAddress;
  34. bool verified;
  35. uint8 share;
  36. }
  37. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L66
  38. struct Collection {
  39. bool verified;
  40. address key;
  41. }
  42. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/state/collection.rs#L57
  43. struct CollectionDetails {
  44. CollectionDetailsType detailType;
  45. uint64 size;
  46. }
  47. enum CollectionDetailsType {
  48. V1
  49. }
  50. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L43
  51. struct Uses {
  52. UseMethod useMethod;
  53. uint64 remaining;
  54. uint64 total;
  55. }
  56. // Reference: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/bubblegum/program/src/state/metaplex_adapter.rs#L35
  57. enum UseMethod {
  58. Burn,
  59. Multiple,
  60. Single
  61. }
  62. function create_metadata_account(
  63. address metadata,
  64. address mint,
  65. address mintAuthority,
  66. address payer,
  67. address updateAuthority,
  68. string name,
  69. string symbol,
  70. string uri
  71. ) public view {
  72. // // Example of how to add a Creator[] array to the DataV2 struct
  73. // Creator[] memory creators = new Creator[](1);
  74. // creators[0] = Creator({
  75. // creatorAddress: payer,
  76. // verified: false,
  77. // share: 100
  78. // });
  79. DataV2 data = DataV2({
  80. name: name,
  81. symbol: symbol,
  82. uri: uri,
  83. sellerFeeBasisPoints: 0,
  84. creatorsPresent: false,
  85. // creators: creators,
  86. collectionPresent: false,
  87. // collection: Collection({
  88. // verified: false,
  89. // key: address(0)
  90. // }),
  91. usesPresent: false
  92. // uses: Uses({
  93. // useMethod: UseMethod.Burn,
  94. // remaining: 0,
  95. // total: 0
  96. // })
  97. });
  98. CreateMetadataAccountArgsV3 args = CreateMetadataAccountArgsV3({
  99. data: data,
  100. isMutable: true,
  101. collectionDetailsPresent: false
  102. // collectionDetails: CollectionDetails({
  103. // detailType: CollectionDetailsType.V1,
  104. // size: 0
  105. // })
  106. });
  107. AccountMeta[7] metas = [
  108. AccountMeta({pubkey: metadata, is_writable: true, is_signer: false}),
  109. AccountMeta({pubkey: mint, is_writable: false, is_signer: false}),
  110. AccountMeta({pubkey: mintAuthority, is_writable: false, is_signer: true}),
  111. AccountMeta({pubkey: payer, is_writable: true, is_signer: true}),
  112. AccountMeta({pubkey: updateAuthority, is_writable: false, is_signer: false}),
  113. AccountMeta({pubkey: systemAddress, is_writable: false, is_signer: false}),
  114. AccountMeta({pubkey: rentAddress, is_writable: false, is_signer: false})
  115. ];
  116. bytes1 discriminator = 33;
  117. bytes instructionData = abi.encode(discriminator, args);
  118. metadataProgramId.call{accounts: metas}(instructionData);
  119. }
  120. }