@silvana-one/nft 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/README.md +1400 -0
  2. package/dist/node/admin/advanced.d.ts +469 -0
  3. package/dist/node/admin/advanced.js +525 -0
  4. package/dist/node/admin/advanced.js.map +1 -0
  5. package/dist/node/admin/index.d.ts +1 -0
  6. package/dist/node/admin/index.js +2 -0
  7. package/dist/node/admin/index.js.map +1 -0
  8. package/dist/node/contracts/admin.d.ts +140 -0
  9. package/dist/node/contracts/admin.js +336 -0
  10. package/dist/node/contracts/admin.js.map +1 -0
  11. package/dist/node/contracts/collection.d.ts +551 -0
  12. package/dist/node/contracts/collection.js +1049 -0
  13. package/dist/node/contracts/collection.js.map +1 -0
  14. package/dist/node/contracts/index.d.ts +3 -0
  15. package/dist/node/contracts/index.js +4 -0
  16. package/dist/node/contracts/index.js.map +1 -0
  17. package/dist/node/contracts/nft.d.ts +76 -0
  18. package/dist/node/contracts/nft.js +329 -0
  19. package/dist/node/contracts/nft.js.map +1 -0
  20. package/dist/node/contracts.d.ts +709 -0
  21. package/dist/node/contracts.js +61 -0
  22. package/dist/node/contracts.js.map +1 -0
  23. package/dist/node/index.cjs +5032 -0
  24. package/dist/node/index.d.ts +8 -0
  25. package/dist/node/index.js +9 -0
  26. package/dist/node/index.js.map +1 -0
  27. package/dist/node/interfaces/admin.d.ts +102 -0
  28. package/dist/node/interfaces/admin.js +2 -0
  29. package/dist/node/interfaces/admin.js.map +1 -0
  30. package/dist/node/interfaces/approval.d.ts +57 -0
  31. package/dist/node/interfaces/approval.js +62 -0
  32. package/dist/node/interfaces/approval.js.map +1 -0
  33. package/dist/node/interfaces/collection.d.ts +57 -0
  34. package/dist/node/interfaces/collection.js +2 -0
  35. package/dist/node/interfaces/collection.js.map +1 -0
  36. package/dist/node/interfaces/encoding.d.ts +24 -0
  37. package/dist/node/interfaces/encoding.js +32 -0
  38. package/dist/node/interfaces/encoding.js.map +1 -0
  39. package/dist/node/interfaces/events.d.ts +833 -0
  40. package/dist/node/interfaces/events.js +106 -0
  41. package/dist/node/interfaces/events.js.map +1 -0
  42. package/dist/node/interfaces/index.d.ts +10 -0
  43. package/dist/node/interfaces/index.js +11 -0
  44. package/dist/node/interfaces/index.js.map +1 -0
  45. package/dist/node/interfaces/ownable.d.ts +94 -0
  46. package/dist/node/interfaces/ownable.js +12 -0
  47. package/dist/node/interfaces/ownable.js.map +1 -0
  48. package/dist/node/interfaces/owner.d.ts +61 -0
  49. package/dist/node/interfaces/owner.js +101 -0
  50. package/dist/node/interfaces/owner.js.map +1 -0
  51. package/dist/node/interfaces/pausable.d.ts +74 -0
  52. package/dist/node/interfaces/pausable.js +14 -0
  53. package/dist/node/interfaces/pausable.js.map +1 -0
  54. package/dist/node/interfaces/types.d.ts +2297 -0
  55. package/dist/node/interfaces/types.js +507 -0
  56. package/dist/node/interfaces/types.js.map +1 -0
  57. package/dist/node/interfaces/update.d.ts +53 -0
  58. package/dist/node/interfaces/update.js +58 -0
  59. package/dist/node/interfaces/update.js.map +1 -0
  60. package/dist/node/marketplace/auction.d.ts +775 -0
  61. package/dist/node/marketplace/auction.js +430 -0
  62. package/dist/node/marketplace/auction.js.map +1 -0
  63. package/dist/node/marketplace/bid.d.ts +254 -0
  64. package/dist/node/marketplace/bid.js +260 -0
  65. package/dist/node/marketplace/bid.js.map +1 -0
  66. package/dist/node/marketplace/index.d.ts +5 -0
  67. package/dist/node/marketplace/index.js +6 -0
  68. package/dist/node/marketplace/index.js.map +1 -0
  69. package/dist/node/marketplace/nft-shares.d.ts +1083 -0
  70. package/dist/node/marketplace/nft-shares.js +398 -0
  71. package/dist/node/marketplace/nft-shares.js.map +1 -0
  72. package/dist/node/marketplace/offer.d.ts +192 -0
  73. package/dist/node/marketplace/offer.js +132 -0
  74. package/dist/node/marketplace/offer.js.map +1 -0
  75. package/dist/node/marketplace/types.d.ts +374 -0
  76. package/dist/node/marketplace/types.js +33 -0
  77. package/dist/node/marketplace/types.js.map +1 -0
  78. package/dist/node/metadata/index.d.ts +3 -0
  79. package/dist/node/metadata/index.js +4 -0
  80. package/dist/node/metadata/index.js.map +1 -0
  81. package/dist/node/metadata/metadata.d.ts +337 -0
  82. package/dist/node/metadata/metadata.js +439 -0
  83. package/dist/node/metadata/metadata.js.map +1 -0
  84. package/dist/node/metadata/text.d.ts +44 -0
  85. package/dist/node/metadata/text.js +42 -0
  86. package/dist/node/metadata/text.js.map +1 -0
  87. package/dist/node/metadata/tree.d.ts +75 -0
  88. package/dist/node/metadata/tree.js +85 -0
  89. package/dist/node/metadata/tree.js.map +1 -0
  90. package/dist/node/vk.d.ts +42 -0
  91. package/dist/node/vk.js +45 -0
  92. package/dist/node/vk.js.map +1 -0
  93. package/dist/node/zkprogram-example/game.d.ts +76 -0
  94. package/dist/node/zkprogram-example/game.js +108 -0
  95. package/dist/node/zkprogram-example/game.js.map +1 -0
  96. package/dist/node/zkprogram-example/index.d.ts +2 -0
  97. package/dist/node/zkprogram-example/index.js +3 -0
  98. package/dist/node/zkprogram-example/index.js.map +1 -0
  99. package/dist/node/zkprogram-example/update.d.ts +76 -0
  100. package/dist/node/zkprogram-example/update.js +85 -0
  101. package/dist/node/zkprogram-example/update.js.map +1 -0
  102. package/dist/tsconfig.tsbuildinfo +1 -0
  103. package/dist/tsconfig.web.tsbuildinfo +1 -0
  104. package/dist/web/admin/advanced.d.ts +469 -0
  105. package/dist/web/admin/advanced.js +525 -0
  106. package/dist/web/admin/advanced.js.map +1 -0
  107. package/dist/web/admin/index.d.ts +1 -0
  108. package/dist/web/admin/index.js +2 -0
  109. package/dist/web/admin/index.js.map +1 -0
  110. package/dist/web/contracts/admin.d.ts +140 -0
  111. package/dist/web/contracts/admin.js +336 -0
  112. package/dist/web/contracts/admin.js.map +1 -0
  113. package/dist/web/contracts/collection.d.ts +551 -0
  114. package/dist/web/contracts/collection.js +1049 -0
  115. package/dist/web/contracts/collection.js.map +1 -0
  116. package/dist/web/contracts/index.d.ts +3 -0
  117. package/dist/web/contracts/index.js +4 -0
  118. package/dist/web/contracts/index.js.map +1 -0
  119. package/dist/web/contracts/nft.d.ts +76 -0
  120. package/dist/web/contracts/nft.js +329 -0
  121. package/dist/web/contracts/nft.js.map +1 -0
  122. package/dist/web/contracts.d.ts +709 -0
  123. package/dist/web/contracts.js +61 -0
  124. package/dist/web/contracts.js.map +1 -0
  125. package/dist/web/index.d.ts +8 -0
  126. package/dist/web/index.js +9 -0
  127. package/dist/web/index.js.map +1 -0
  128. package/dist/web/interfaces/admin.d.ts +102 -0
  129. package/dist/web/interfaces/admin.js +2 -0
  130. package/dist/web/interfaces/admin.js.map +1 -0
  131. package/dist/web/interfaces/approval.d.ts +57 -0
  132. package/dist/web/interfaces/approval.js +62 -0
  133. package/dist/web/interfaces/approval.js.map +1 -0
  134. package/dist/web/interfaces/collection.d.ts +57 -0
  135. package/dist/web/interfaces/collection.js +2 -0
  136. package/dist/web/interfaces/collection.js.map +1 -0
  137. package/dist/web/interfaces/encoding.d.ts +24 -0
  138. package/dist/web/interfaces/encoding.js +32 -0
  139. package/dist/web/interfaces/encoding.js.map +1 -0
  140. package/dist/web/interfaces/events.d.ts +833 -0
  141. package/dist/web/interfaces/events.js +106 -0
  142. package/dist/web/interfaces/events.js.map +1 -0
  143. package/dist/web/interfaces/index.d.ts +10 -0
  144. package/dist/web/interfaces/index.js +11 -0
  145. package/dist/web/interfaces/index.js.map +1 -0
  146. package/dist/web/interfaces/ownable.d.ts +94 -0
  147. package/dist/web/interfaces/ownable.js +12 -0
  148. package/dist/web/interfaces/ownable.js.map +1 -0
  149. package/dist/web/interfaces/owner.d.ts +61 -0
  150. package/dist/web/interfaces/owner.js +101 -0
  151. package/dist/web/interfaces/owner.js.map +1 -0
  152. package/dist/web/interfaces/pausable.d.ts +74 -0
  153. package/dist/web/interfaces/pausable.js +14 -0
  154. package/dist/web/interfaces/pausable.js.map +1 -0
  155. package/dist/web/interfaces/types.d.ts +2297 -0
  156. package/dist/web/interfaces/types.js +507 -0
  157. package/dist/web/interfaces/types.js.map +1 -0
  158. package/dist/web/interfaces/update.d.ts +53 -0
  159. package/dist/web/interfaces/update.js +58 -0
  160. package/dist/web/interfaces/update.js.map +1 -0
  161. package/dist/web/marketplace/auction.d.ts +775 -0
  162. package/dist/web/marketplace/auction.js +430 -0
  163. package/dist/web/marketplace/auction.js.map +1 -0
  164. package/dist/web/marketplace/bid.d.ts +254 -0
  165. package/dist/web/marketplace/bid.js +260 -0
  166. package/dist/web/marketplace/bid.js.map +1 -0
  167. package/dist/web/marketplace/index.d.ts +5 -0
  168. package/dist/web/marketplace/index.js +6 -0
  169. package/dist/web/marketplace/index.js.map +1 -0
  170. package/dist/web/marketplace/nft-shares.d.ts +1083 -0
  171. package/dist/web/marketplace/nft-shares.js +398 -0
  172. package/dist/web/marketplace/nft-shares.js.map +1 -0
  173. package/dist/web/marketplace/offer.d.ts +192 -0
  174. package/dist/web/marketplace/offer.js +132 -0
  175. package/dist/web/marketplace/offer.js.map +1 -0
  176. package/dist/web/marketplace/types.d.ts +374 -0
  177. package/dist/web/marketplace/types.js +33 -0
  178. package/dist/web/marketplace/types.js.map +1 -0
  179. package/dist/web/metadata/index.d.ts +3 -0
  180. package/dist/web/metadata/index.js +4 -0
  181. package/dist/web/metadata/index.js.map +1 -0
  182. package/dist/web/metadata/metadata.d.ts +337 -0
  183. package/dist/web/metadata/metadata.js +439 -0
  184. package/dist/web/metadata/metadata.js.map +1 -0
  185. package/dist/web/metadata/text.d.ts +44 -0
  186. package/dist/web/metadata/text.js +42 -0
  187. package/dist/web/metadata/text.js.map +1 -0
  188. package/dist/web/metadata/tree.d.ts +75 -0
  189. package/dist/web/metadata/tree.js +85 -0
  190. package/dist/web/metadata/tree.js.map +1 -0
  191. package/dist/web/vk.d.ts +42 -0
  192. package/dist/web/vk.js +45 -0
  193. package/dist/web/vk.js.map +1 -0
  194. package/dist/web/zkprogram-example/game.d.ts +76 -0
  195. package/dist/web/zkprogram-example/game.js +108 -0
  196. package/dist/web/zkprogram-example/game.js.map +1 -0
  197. package/dist/web/zkprogram-example/index.d.ts +2 -0
  198. package/dist/web/zkprogram-example/index.js +3 -0
  199. package/dist/web/zkprogram-example/index.js.map +1 -0
  200. package/dist/web/zkprogram-example/update.d.ts +76 -0
  201. package/dist/web/zkprogram-example/update.js +85 -0
  202. package/dist/web/zkprogram-example/update.js.map +1 -0
  203. package/package.json +65 -0
  204. package/src/admin/advanced.ts +601 -0
  205. package/src/admin/index.ts +1 -0
  206. package/src/contracts/admin.ts +301 -0
  207. package/src/contracts/collection.ts +1172 -0
  208. package/src/contracts/index.ts +3 -0
  209. package/src/contracts/nft.ts +344 -0
  210. package/src/contracts.ts +107 -0
  211. package/src/index.ts +8 -0
  212. package/src/interfaces/admin.ts +127 -0
  213. package/src/interfaces/approval.ts +99 -0
  214. package/src/interfaces/collection.ts +68 -0
  215. package/src/interfaces/encoding.ts +32 -0
  216. package/src/interfaces/events.ts +115 -0
  217. package/src/interfaces/index.ts +10 -0
  218. package/src/interfaces/ownable.ts +32 -0
  219. package/src/interfaces/owner.ts +143 -0
  220. package/src/interfaces/pausable.ts +41 -0
  221. package/src/interfaces/types.ts +623 -0
  222. package/src/interfaces/update.ts +104 -0
  223. package/src/marketplace/auction.ts +527 -0
  224. package/src/marketplace/bid.ts +294 -0
  225. package/src/marketplace/index.ts +5 -0
  226. package/src/marketplace/nft-shares.ts +388 -0
  227. package/src/marketplace/offer.ts +153 -0
  228. package/src/marketplace/types.ts +33 -0
  229. package/src/metadata/index.ts +3 -0
  230. package/src/metadata/metadata.ts +603 -0
  231. package/src/metadata/text.ts +60 -0
  232. package/src/metadata/tree.ts +128 -0
  233. package/src/vk.ts +64 -0
  234. package/src/zkprogram-example/game.ts +136 -0
  235. package/src/zkprogram-example/index.ts +2 -0
  236. package/src/zkprogram-example/update.ts +98 -0
package/README.md ADDED
@@ -0,0 +1,1400 @@
1
+ # NFT Standard on Mina Protocol
2
+
3
+ The MinaNFT project is an innovative Non-Fungible Token (NFT) platform that integrates the unique privacy features of the Mina blockchain. It is designed to redefine the NFT space by offering a range of functionalities that go beyond traditional NFT capabilities.
4
+
5
+ ## Contracts Code
6
+
7
+ ### NFT Standard Contracts
8
+
9
+ Main contracts: packages/nft/src/contracts/
10
+
11
+ Interfaces: packages/nft/src/interfaces/
12
+
13
+ ### Examples of NFT Standard usage (not part of the standard)
14
+
15
+ Marketplace: packages/nft/src/marketplace/
16
+
17
+ Metadata: packages/nft/src/metadata/
18
+
19
+ ZkPrograms: packages/nft/src/zkprogram-example/
20
+
21
+ Admin: packages/nft/src/admin/
22
+
23
+ ### Dependencies
24
+
25
+ #### Storage class used by the NFT Standard
26
+
27
+ Storage: packages/storage/src/storage/storage.ts
28
+
29
+ #### Whitelist class used by the NFT Advanced Admin Example and Marketplace
30
+
31
+ Whitelist: packages/nft/src/whitelist/whitelist.ts
32
+
33
+ #### Upgrade Authority class used by the NFT Advanced Admin Example
34
+
35
+ UpgradeAuthority: packages/upgradable
36
+
37
+ ### Tests
38
+
39
+ Test are available at https://github.com/dfstio/nft-standard-worker/tree/audit
40
+
41
+ ## Project Background
42
+
43
+ Non-Fungible Tokens (NFTs) have become a pivotal aspect of digital ownership, allowing creators, individuals, and corporations to represent unique digital assets on the blockchain. However, current NFT standards, like ERC721, lack essential privacy, verifiability, and versatile content integration features. The NFT standard on Mina seeks to overcome these limitations by introducing enhanced functionality such as privacy features, verifiable proofs for both public and private data, unlocking new use cases for NFTs in the realms of digital identity, secure document sharing, and multimedia content.
44
+
45
+ Establishing a standard for NFTs on Mina reduces the complexity for developers while enabling seamless integration with third-party applications, marketplaces, and explorers. This NFT standard leverages Mina’s zero-knowledge (ZK) capabilities to ensure that NFTs created on the platform can securely handle both public and private content while providing proofs of authenticity that can be verified both on-chain and off-chain.
46
+
47
+ This standard enables businesses and individuals to create NFTs that not only represent unique digital assets but also serve as secure digital identities capable of hosting and sharing sensitive data. This significantly expands the utility of NFTs beyond art into domains like Real World Assets, Gaming, Communities, and Governance.
48
+
49
+ ## Motivation and Architecture Overview
50
+
51
+ Non-Fungible Tokens (NFTs) have become a central feature in blockchain ecosystems, enabling the ownership and exchange of unique digital assets. Establishing a standard for NFTs on the Mina Protocol will significantly simplify the creation and interaction with NFTs while ensuring that they can be easily integrated into wallets, marketplaces, and third-party applications.
52
+
53
+ The need for standardization goes beyond merely defining an API. NFTs on Mina will benefit from a standard implementation that can be universally used when deploying and interacting with NFT contracts. This is particularly important in Mina’s off-chain execution model, where applications need access to the contract code for verification and interaction. Without a standardized NFT contract, third-party developers, wallets, and explorers would face a significant burden when integrating with different, custom NFT contracts, as they would need to account for the unique logic and structure of each.
54
+
55
+ The design is based on existing MinaNFT contracts V2 deployed to the mainnet. Many NFTs have already been minted, sold, and bought on the mainnet, and many creators are developing collections, providing feedback, and requesting new features.
56
+
57
+ To provide flexibility without altering the core NFT contracts, the design separates key administrative actions, such as whitelisting or KYC checks, into dedicated admin contracts. This ensures that the core NFT contract remains standardized while custom logic can be introduced through the admin contracts. By doing so, applications that only need to handle basic NFT operations, such as transfers or ownership verification, can interact solely with the NFT contract, ensuring compatibility across all NFTs following the standard.
58
+
59
+ Additionally, Mina’s ZK architecture enhances NFTs’ functionality by allowing both on-chain and off-chain verifiability of public and private data attached to NFTs. This opens the door for NFTs representing a wide range of assets, from digital art to legal contracts and Real World Assets (RWA), while maintaining user privacy and security.
60
+
61
+ The metadata for the NFT will be stored off-chain, with the storage choice and metadata format being open. It will be possible to use metadata standards by the MinaNFT V2 and IPFS as storage options, but using this metadata standard will not be part of the standard, and it will be the NFT collection creator's choice what metadata format and storage to use.
62
+
63
+ The recommended metadata JSON format will be a part of the standard, but the method of calculating the metadata root or hash will not.
64
+
65
+ By providing a standard implementation for NFT creation, management, and verification, Mina enables seamless interoperability, ensuring that all NFT-based applications can work with the same contract, reducing the complexity for developers, and enhancing the user experience across the ecosystem.
66
+
67
+ ## Detailed Architecture Overview
68
+
69
+ ### Contracts Overview
70
+
71
+ The NFT standard on Mina Protocol consists of several contracts working together to provide comprehensive and flexible functionality for NFTs. The main contracts include:
72
+
73
+ - **NFT Collection Contract** (`collection.ts`)
74
+ - **NFT Contract** (`nft.ts`)
75
+ - **Admin Contract** (`admin.ts`)
76
+
77
+ Below is a detailed description of each contract, including their methods and functionalities.
78
+
79
+ ### NFT Collection Contract
80
+
81
+ The **NFT Collection Contract** manages a collection of NFTs on the Mina Protocol. It handles minting, transferring, buying, selling, and integrates with admin, approval, and owner contracts for fine-grained control. Below is an overview of its latest features and methods, along with the relevant flags and events that govern its behavior.
82
+
83
+ ---
84
+
85
+ ## Key Features
86
+
87
+ 1. **Minting NFTs**
88
+ • Allows creators and authorized users to mint new NFTs in the collection.
89
+ • Supports both direct creator minting (mintByCreator) and admin-approved minting (mint).
90
+
91
+ 2. **Transferring Ownership**
92
+ • Enables transferring NFTs with or without admin approval.
93
+ • Offers different methods for transfer:
94
+ – By signature.
95
+ – By proof.
96
+ • Optionally enforces transfer fees and royalty fees.
97
+
98
+ 3. **Buying and Selling**
99
+ • Facilitates listing and purchasing of NFTs, optionally requiring admin approval.
100
+ • Handles ownership checks, transfer fees, and royalty fees to creators.
101
+
102
+ 4. **Updating NFTs**
103
+ • Provides methods to update NFT metadata with zero-knowledge proofs.
104
+ • Supports both standard updates (update) and oracle-based updates (updateWithOracle).
105
+ • Integrates with admin and update contracts to enforce custom policies or off-chain logic.
106
+
107
+ 5. **Pausing and Resuming**
108
+ • Offers the ability to pause the entire collection (pause, resume).
109
+ • Also supports pausing or resuming individual NFTs.
110
+ • Pausing actions can be secured by owner signature (pauseNFTBySignature, resumeNFT) or by proof-based ownership (pauseNFTByProof, resumeNFTByProof).
111
+
112
+ 6. **Contract Upgrades**
113
+ • Supports upgrading the verification key of the collection (upgradeVerificationKey).
114
+ • Allows upgrading individual NFT verification keys (upgradeNFTVerificationKey).
115
+
116
+ 7. **Administrative and Ownership Controls**
117
+ • Interacts with Admin, Owner, Approval, and Update contracts for advanced workflows like KYC/AML compliance or flexible approval policies.
118
+ • Provides specialized methods to set collection parameters such as collection name, base URL, admin address, and royalty fee.
119
+ • Allows transferring overall ownership of the collection (transferOwnership).
120
+
121
+ 8. **Mint Limitation & Configuration Updates**
122
+ • Offers a limitMinting method to permanently stop further minting.
123
+ • Additional configuration updates are available through specialized methods (e.g., setName, setBaseURL, setAdmin, setRoyaltyFee).
124
+
125
+ ---
126
+
127
+ ## State Variables
128
+
129
+ • collectionName (Field)
130
+ The name of the NFT collection stored on-chain.
131
+ • creator (PublicKey)
132
+ The creator’s public key, used for collecting royalty fees and for certain ownership checks.
133
+ • admin (PublicKey)
134
+ The Admin Contract’s public key, controlling approval-based actions.
135
+ • baseURL (Field)
136
+ The base URL for the collection, used as a reference for off-chain metadata.
137
+ • packedData (CollectionDataPacked)
138
+ Stores flags and configuration (e.g., paused status, transfer-approval requirement, royalty fee, etc.).
139
+
140
+ ---
141
+
142
+ ## Core Methods
143
+
144
+ Below is a summary of major methods in the Collection Contract. Several are decorated with “@method”, indicating they are part of the on-chain zkApp logic.
145
+
146
+ • deploy(props: CollectionDeployProps): Promise<void>
147
+ Deploys the contract with initial settings (name, admin, royalty fee, etc.).
148
+
149
+ • initialize(masterNFT: MintParams, collectionData: CollectionData): Promise<void>
150
+ Initializes the collection with a “master” NFT and any initial parameters (name, base URL, flags).
151
+
152
+ • mintByCreator(params: MintParams): Promise<void>
153
+ Allows the creator to mint a new NFT in the collection directly.
154
+
155
+ • mint(mintRequest: MintRequest): Promise<void>
156
+ Mints a new NFT via an admin approval flow.
157
+ (The Admin Contract checks whether minting is authorized.)
158
+
159
+ • update(proof: NFTUpdateProof, vk: VerificationKey): Promise<void>
160
+ Updates the NFT’s metadata or state using a zero-knowledge proof.
161
+
162
+ • updateWithOracle(proof: NFTUpdateProof, vk: VerificationKey): Promise<void>
163
+ Similar to update, but enforces an additional oracle-based approval step.
164
+
165
+ • sell / sellWithApproval / buy / buyWithApproval: Promise<void>
166
+ Enable listing and buying NFTs, optionally requiring admin approval.
167
+
168
+ • transfer / transferWithApproval: Promise<void>
169
+ Transfer an NFT to a new owner with or without admin approval.
170
+
171
+ • pause / resume(): Promise<void>
172
+ Pauses or resumes the entire collection. When paused, certain actions are disallowed.
173
+
174
+ • pauseNFTBySignature(address: PublicKey): Promise<void>
175
+ Pauses an individual NFT’s contract logic, requiring the NFT owner’s signature.
176
+
177
+ • pauseNFTByProof(address: PublicKey): Promise<void>
178
+ Pauses an individual NFT’s contract logic using a zero-knowledge proof of ownership.
179
+
180
+ • resumeNFT(address: PublicKey): Promise<void>
181
+ Resumes an NFT’s logic, requiring the NFT owner’s signature.
182
+
183
+ • resumeNFTByProof(address: PublicKey): Promise<void>
184
+ Resumes an NFT’s logic via a proof-based check of ownership.
185
+
186
+ • upgradeNFTVerificationKey(address: PublicKey, vk: VerificationKey): Promise<void>
187
+ Upgrades the verification key for an individual NFT.
188
+
189
+ • upgradeVerificationKey(vk: VerificationKey): Promise<void>
190
+ Upgrades the verification key of the overall collection contract.
191
+
192
+ • limitMinting(): Promise<void>
193
+ Permanently shuts off new NFT minting in the collection.
194
+
195
+ • setName(name: Field): Promise<void>
196
+ Updates the collection’s on-chain name (requires admin check and “not paused” status).
197
+
198
+ • setBaseURL(baseURL: Field): Promise<void>
199
+ Updates the collection’s base metadata URL (requires admin check and “not paused” status).
200
+
201
+ • setAdmin(admin: PublicKey): Promise<void>
202
+ Sets a new admin contract address (requires admin check and “not paused” status).
203
+
204
+ • setRoyaltyFee(royaltyFee: UInt32): Promise<void>
205
+ Adjusts the royalty fee percentage for future NFT transactions (requires admin check and “not paused” status).
206
+
207
+ • transferOwnership(newOwner: PublicKey): Promise<PublicKey>
208
+ Transfers ownership from the current creator to a new public key (e.g., for contract handover).
209
+
210
+ • getNFTState(address: PublicKey): Promise<NFTStateStruct>
211
+ Returns the complete on-chain state (owner, metadata, paused flag, etc.) of a particular NFT in this collection.
212
+
213
+ ---
214
+
215
+ ## Events
216
+
217
+ The contract emits the following events during its lifecycle and interactions:
218
+
219
+ • mint
220
+ Emitted when a new NFT is successfully minted.
221
+
222
+ • update
223
+ Emitted when an NFT’s state or metadata is updated.
224
+
225
+ • transfer
226
+ Emitted when an NFT is transferred from one owner to another.
227
+
228
+ • approve
229
+ Emitted when an approved address is added or removed.
230
+
231
+ • upgradeNFTVerificationKey
232
+ Emitted when an individual NFT’s verification key is upgraded.
233
+
234
+ • upgradeVerificationKey
235
+ Emitted when the entire collection’s verification key is upgraded.
236
+
237
+ • limitMinting
238
+ Emitted when new NFT minting is permanently disabled within the collection.
239
+
240
+ • pause
241
+ Emitted when the entire collection is paused.
242
+
243
+ • resume
244
+ Emitted when the entire collection is resumed.
245
+
246
+ • pauseNFT
247
+ Emitted when an individual NFT is paused.
248
+
249
+ • resumeNFT
250
+ Emitted when an individual NFT is resumed.
251
+
252
+ • ownershipChange
253
+ Emitted when overall ownership of the collection contract is transferred.
254
+
255
+ • setName
256
+ Emitted when the collection name is changed.
257
+
258
+ • setBaseURL
259
+ Emitted when the base URL is updated.
260
+
261
+ • setRoyaltyFee
262
+ Emitted when the royalty fee is updated.
263
+
264
+ • setTransferFee
265
+ Emitted when the transfer fee is updated.
266
+
267
+ • setAdmin
268
+ Emitted when a new admin is set for the collection.
269
+
270
+ ---
271
+
272
+ ## Flags
273
+
274
+ These flags are stored in the contract’s packed data (packedData) and can be accessed or updated through various methods or admin contract checks:
275
+
276
+ • isPaused (Bool)
277
+ True if the collection is paused (certain features disabled).
278
+
279
+ • mintingIsLimited (Bool)
280
+ If true, no further NFTs can be minted.
281
+
282
+ • requireTransferApproval (Bool)
283
+ If true, NFT transfers must be approved by the Admin Contract.
284
+
285
+ • Additional flags or configuration fields may exist depending on how the CollectionData struct is extended (e.g., requireSaleApproval, requireUpdateApproval, royaltyFee, transferFee, etc.).
286
+
287
+ ---
288
+
289
+ ## Notes and References
290
+
291
+ • The contract extensively integrates with Admin, Owner, Approval, and Update contracts for additional checks and off-chain logic.
292
+ • The underlying methods rely on zero-knowledge proofs (ZKPs) for certain workflows, e.g., updateWithOracle or pauseNFTByProof.
293
+ • The “packedData” field bundles essential flags and numeric values (like royaltyFee, transferFee) into a single Field for efficient on-chain storage.
294
+ • Refer to @types.ts for definitions of NFTUpdateProof, NFTStateStruct, CollectionData, and other data structures, and @events.ts for event struct definitions.
295
+ • The “CollectionFactory” function programmatically generates the Collection class, injecting references to custom admin, owner, approval, and update contracts, allowing custom logic to be easily composed.
296
+
297
+ This updated description reflects the latest version of the Collection Contract, as seen in @collection.ts, @types.ts, and @events.ts. It includes support for oracle-driven updates, flexible NFT pausing/resuming, refined administrative checks, and extended event emissions.
298
+
299
+ ### NFT Contract
300
+
301
+ The NFT Contract represents an individual NFT within a collection and defines both its on-chain state and permissible actions. It manages ownership, metadata, off-chain storage references, pricing, and various permission flags. It includes functionality to update an NFT’s data with proofs, transfer ownership, approve a delegate address, pause or resume the NFT, and upgrade the verification key, maintaining a packed structure for efficient on-chain storage.
302
+
303
+ Below is an overview of its latest features, state variables, methods, and events, as reflected in the current implementation at:
304
+ • packages/nft/src/contracts/nft.ts
305
+ • packages/nft/src/interfaces/types.ts
306
+ • packages/nft/src/interfaces/events.ts
307
+
308
+ ---
309
+
310
+ #### State Variables
311
+
312
+ • name (Field)
313
+ – The on-chain name of the NFT.
314
+
315
+ • metadata (Field)
316
+ – A Field representing the NFT’s current metadata or metadata hash.
317
+
318
+ • storage (Storage)
319
+ – A reference to off-chain storage (e.g., IPFS hash or other storage root).
320
+
321
+ • packedData (NFTDataPacked)
322
+ – A packed Field containing key information and flags (e.g., owner, approved address, permission bits, and pause state).
323
+
324
+ • metadataVerificationKeyHash (Field)
325
+ – The hash of the verification key used for zero-knowledge proofs when updating or verifying the NFT’s metadata.
326
+
327
+ ---
328
+
329
+ #### Key Methods
330
+
331
+ ```typescript:packages/nft/src/contracts/nft.ts
332
+ class NFT extends SmartContract {
333
+
334
+
335
+ @method.returns(NFTStateStruct)
336
+ async getState(): Promise<NFTStateStruct> {
337
+ // Retrieves and returns the entire on-chain state of the NFT
338
+ }
339
+
340
+ @method.returns(Field)
341
+ async update(
342
+ input: NFTState,
343
+ output: NFTState,
344
+ creator: PublicKey
345
+ ): Promise<Field> {
346
+ // Updates the NFT’s state with provided proofs and permission checks,
347
+ // enforcing all read-only and mutable flag constraints
348
+ }
349
+
350
+ @method.returns(TransferExtendedParams)
351
+ async transfer(params: TransferExtendedParams): Promise<TransferExtendedParams> {
352
+ // Transfers ownership of the NFT to a new address,
353
+ // honoring permissions and pause states
354
+ }
355
+
356
+ @method.returns(PublicKey)
357
+ async approveAddress(approved: PublicKey): Promise<PublicKey> {
358
+ // Sets or changes the NFT’s approved address for delegated actions
359
+ }
360
+
361
+ @method.returns(UpgradeVerificationKeyData)
362
+ async upgradeVerificationKey(
363
+ vk: VerificationKey
364
+ ): Promise<UpgradeVerificationKeyData> {
365
+ // Upgrades the contract's verification key if permission flags allow it,
366
+ // returning data indicating whether the owner’s authorization is required
367
+ }
368
+
369
+ @method.returns(PublicKey)
370
+ async pause(): Promise<PublicKey> {
371
+ // Pauses the NFT if allowed (isPaused=true), disabling certain actions
372
+ }
373
+
374
+ @method.returns(PublicKey)
375
+ async resume(): Promise<PublicKey> {
376
+ // Resumes the NFT if it is currently paused, restoring normal functionality
377
+ }
378
+
379
+
380
+ }
381
+ ```
382
+
383
+ • getState(): Retrieves the full NFT state as an NFTStateStruct, including name, metadata, storage, packed data, and verification key hash.
384
+
385
+ • update(input, output, creator): Applies changes to the NFT state by comparing the “input” and “output” states, verifying that only permitted fields are modified (e.g., canChangeMetadata must be true to change metadata). Enforces that read-only flags (like canChangeName, canPause) are respected.
386
+
387
+ • transfer(params): Transfers ownership from the current owner (or approved address) to a new owner, incrementing version and clearing the approved address. Requires that canTransfer = true and isPaused = false.
388
+
389
+ • approveAddress(approved): Sets a new approved address, enabling delegated transfers or updates without requiring the owner to sign.
390
+
391
+ • upgradeVerificationKey(vk): Upgrades the NFT’s verification key. This method returns an UpgradeVerificationKeyData object containing (owner, isOwnerApprovalRequired). If the NFT’s flags enforce owner authorization, the collection contract can further validate the call.
392
+
393
+ • pause() / resume(): Pauses or resumes the NFT if canPause = true. A paused NFT cannot be transferred or updated until resumed.
394
+
395
+ ---
396
+
397
+ #### Events
398
+
399
+ • update
400
+ – Emitted when the NFT’s name, metadata, storage, owner, or related data fields are changed and version is incremented.
401
+
402
+ • transfer
403
+ – Emitted whenever ownership changes, providing the old and new owner addresses.
404
+
405
+ • approve
406
+ – Emitted when an approved address is set or changed.
407
+
408
+ • upgradeVerificationKey
409
+ – Emitted when a new verification key is successfully applied to the NFT.
410
+
411
+ • pause / resume
412
+ – Emitted when the NFT is paused or resumed (respectively).
413
+
414
+ ---
415
+
416
+ #### Flags (Immutable / Mutable Fields in packedData)
417
+
418
+ The NFT maintains various read-only flags to restrict or allow certain actions. These include:
419
+ • canChangeOwnerByProof: Whether ownership can be changed by a zero-knowledge proof.
420
+ • canTransfer: Whether ownership can be transferred (via signature or an approved address).
421
+ • canApprove: Whether the approved address can be changed.
422
+ • canChangeMetadata: Whether the NFT’s metadata can be updated.
423
+ • canChangeStorage: Whether the NFT’s off-chain storage reference can be changed.
424
+ • canChangeName: Whether the NFT’s name can be changed.
425
+ • canChangeMetadataVerificationKeyHash: Whether the metadata verification key hash can be changed.
426
+ • canPause: Whether the NFT can be paused, disabling its functionality.
427
+ • requireOwnerAuthorizationToUpgrade: Whether the owner’s signature is required for a verification key upgrade.
428
+
429
+ Additionally, the mutable flags tracked are:
430
+ • isPaused: A boolean indicating if the NFT is currently paused.
431
+ • version: An incrementing version number for the NFT state.
432
+
433
+ All these flags, along with ownership and approval addresses, are packed into a compact field structure for on-chain efficiency.
434
+
435
+ ---
436
+
437
+ #### Error Handling
438
+
439
+ The NFT contract enforces permission checks and immutability guarantees through custom errors, including:
440
+ • cannotChangeOwner
441
+ • cannotChangeMetadata
442
+ • cannotChangePauseState
443
+ • nftIsPaused / nftIsNotPaused / nftAlreadyPaused
444
+ • cannotChangeMetadataVerificationKeyHash
445
+
446
+ These errors are thrown when a user attempts an action that the NFT’s flags or state disallow.
447
+
448
+ ---
449
+
450
+ ### Admin Contracts
451
+
452
+ The **Admin Contracts** provide administrative functionalities for the NFT Collection. They allow for additional checks and controls, such as KYC/AML compliance, whitelisting, pausing the contract, and upgrading contract logic.
453
+
454
+ #### NFTAdminBase Interface
455
+
456
+ The `NFTAdminBase` interface defines the administrative functionalities required for managing an NFT collection on the Mina Protocol. It extends the `SmartContract` class and specifies methods that enforce permissions and validations for various NFT operations.
457
+
458
+ **Type Definition:**
459
+
460
+ ```typescript
461
+ type NFTAdminBase = SmartContract & {
462
+ canMint(nft: MintRequest): Promise<MintParamsOption>;
463
+ canUpdate(input: NFTState, output: NFTState): Promise<Bool>;
464
+ canTransfer(transferEvent: TransferEvent): Promise<Bool>;
465
+ canChangeName(name: Field): Promise<Bool>;
466
+ canChangeCreator(creator: PublicKey): Promise<Bool>;
467
+ canChangeBaseUri(baseUri: Field): Promise<Bool>;
468
+ canChangeRoyalty(royaltyFee: UInt32): Promise<Bool>;
469
+ canChangeTransferFee(transferFee: UInt64): Promise<Bool>;
470
+ canSetAdmin(admin: PublicKey): Promise<Bool>;
471
+ canPause(): Promise<Bool>;
472
+ canResume(): Promise<Bool>;
473
+ canChangeVerificationKey(
474
+ vk: VerificationKey,
475
+ address: PublicKey,
476
+ tokenId: Field
477
+ ): Promise<Bool>;
478
+ };
479
+ ```
480
+
481
+ **Methods:**
482
+
483
+ - `canMint(nft: MintRequest): Promise<MintParamsOption>`
484
+
485
+ - **Description**: Validates whether a new NFT can be minted based on the provided `MintRequest`.
486
+ - **Returns**: A `Promise` resolving to `MintParamsOption`, containing mint parameters if minting is allowed, or an empty option if not.
487
+
488
+ - `canUpdate(input: NFTState, output: NFTState): Promise<Bool>`
489
+
490
+ - **Description**: Checks if an NFT can be updated from its current state (`input`) to a new state (`output`).
491
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether the update is permitted.
492
+
493
+ - `canTransfer(transferEvent: TransferEvent): Promise<Bool>`
494
+
495
+ - **Description**: Determines if an NFT can be transferred based on the provided transfer event details.
496
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether the transfer is allowed.
497
+
498
+ - `canChangeName(name: Field): Promise<Bool>`
499
+
500
+ - **Description**: Determines if the collection name can be changed to the provided value.
501
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether the name change is allowed.
502
+
503
+ - `canChangeCreator(creator: PublicKey): Promise<Bool>`
504
+
505
+ - **Description**: Determines if the collection creator can be changed to the provided address.
506
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether the creator change is allowed.
507
+
508
+ - `canChangeBaseUri(baseUri: Field): Promise<Bool>`
509
+
510
+ - **Description**: Determines if the collection's base URI can be changed to the provided value.
511
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether the base URI change is allowed.
512
+
513
+ - `canChangeRoyalty(royaltyFee: UInt32): Promise<Bool>`
514
+
515
+ - **Description**: Determines if the collection's royalty fee can be changed to the provided value.
516
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether the royalty fee change is allowed.
517
+
518
+ - `canChangeTransferFee(transferFee: UInt64): Promise<Bool>`
519
+
520
+ - **Description**: Determines if the collection's transfer fee can be changed to the provided value.
521
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether the transfer fee change is allowed.
522
+
523
+ - `canSetAdmin(admin: PublicKey): Promise<Bool>`
524
+
525
+ - **Description**: Determines if the collection's admin contract can be changed to the provided address.
526
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether the admin change is allowed.
527
+
528
+ - `canPause(): Promise<Bool>`
529
+
530
+ - **Description**: Determines if the collection can be paused.
531
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether pausing is allowed.
532
+
533
+ - `canResume(): Promise<Bool>`
534
+
535
+ - **Description**: Determines if the collection can be resumed from a paused state.
536
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether resuming is allowed.
537
+
538
+ - `canChangeVerificationKey(vk: VerificationKey, address: PublicKey, tokenId: Field): Promise<Bool>`
539
+ - **Description**: Determines if the verification key can be changed for a specific NFT contract address and token ID.
540
+ - **Returns**: A `Promise` resolving to a `Bool` indicating whether the verification key change is allowed.
541
+
542
+ **Purpose:**
543
+
544
+ Implementing the `NFTAdminBase` interface ensures that an administrative contract provides the necessary methods to control and validate key NFT operations. This standardization allows different admin contracts to enforce specific rules (e.g., whitelisting, KYC/AML compliance) while maintaining a consistent interface for the NFT collection.
545
+
546
+ **Constructor Type:**
547
+
548
+ ```typescript
549
+ type NFTAdminContractConstructor = new (address: PublicKey) => NFTAdminBase;
550
+ ```
551
+
552
+ - **Description**: Defines a constructor for contracts implementing `NFTAdminBase`, accepting an `address` public key and returning an instance of `NFTAdminBase`.
553
+
554
+ #### Standard Admin Contract
555
+
556
+ #### Admin Contract
557
+
558
+ The NFTAdmin contract serves as a foundational administrative layer for Mina-based NFT collections. It implements the NFTAdminBase, PausableContract, and OwnableContract interfaces, providing crucial administrative flows such as contract deployment, pausing/resuming, ownership management, and selective allowance for changing fees or royalty parameters. It is designed to be extensible; more specialized admin contracts can inherit from it to add extra logic (e.g., whitelisting, KYC checks).
559
+
560
+ ##### Key Features
561
+
562
+ • Deployment and Configuration
563
+ – Deploys with initial admin and on-chain settings (URI).
564
+ – Optionally can be paused from the start or disallow future pausing altogether.
565
+ – Can enable/disable the ability to change royalty fees and transfer fees.
566
+
567
+ • Pausing and Resuming
568
+ – Lets the admin pause the contract if canBePaused is true.
569
+ – When paused, certain actions are restricted, and contract methods can check isPaused to decide if they proceed.
570
+ – Supports resuming the contract if it’s paused.
571
+
572
+ • Ownership Management
573
+ – Ensures only the current owner can perform restricted operations via ensureOwnerSignature().
574
+ – Ownership can be transferred to a new admin, but only if the contract is paused.
575
+
576
+ • Verification Key Upgrade
577
+ – Allows an admin-signed upgrade of the contract’s verification key (upgradeVerificationKey), letting the contract evolve without redeployment.
578
+
579
+ • Permission Checks (NFTAdminBase)
580
+ – Defines canMint, canUpdate, and canTransfer methods, typically returning bool or structured data indicating if an action is allowed.
581
+ – Methods like canChangeRoyalty, canChangeTransferFee, canChangeName, etc. define fine-grained checks for a collection’s policy.
582
+
583
+ ##### State Variables
584
+
585
+ • admin (PublicKey)
586
+ – Public key of the contract’s administrator. Must sign to authorize critical actions like pausing or upgrading the contract.
587
+
588
+ • isPaused (Bool)
589
+ – Indicates if the contract is currently paused. If true, many operations can be disallowed or require extra checks.
590
+
591
+ • canBePaused (Bool)
592
+ – Determines if the pause feature is permitted at all (true = pausing/resuming enabled, false = never paused).
593
+
594
+ • allowChangeRoyalty (Bool)
595
+ – If true, the admin can modify a collection’s royalty fee by calling canChangeRoyalty.
596
+
597
+ • allowChangeTransferFee (Bool)
598
+ – If true, the admin can modify a collection’s transfer fee by calling canChangeTransferFee.
599
+
600
+ ##### Key Methods
601
+
602
+ ```typescript:packages/nft/src/contracts/admin.ts
603
+ class NFTAdmin
604
+ extends SmartContract
605
+ implements NFTAdminBase, PausableContract, OwnableContract
606
+ {
607
+ // -------------------------
608
+ // Deployment
609
+ // -------------------------
610
+ async deploy(props: NFTAdminDeployProps) {
611
+ // Deploys the contract with the given admin, zkApp URI, and pause-related flags
612
+ }
613
+
614
+ // -------------------------
615
+ // Permissioned
616
+ // -------------------------
617
+ @method
618
+ async upgradeVerificationKey(vk: VerificationKey) {
619
+ // Upgrades the contract’s verification key after ensuring the admin signature
620
+ }
621
+
622
+ @method.returns(MintParamsOption)
623
+ async canMint(mintRequest: MintRequest): Promise<MintParamsOption> {
624
+ // Default implementation: returns none(), meaning minting is not permitted unless overridden
625
+ }
626
+
627
+ @method.returns(Bool)
628
+ async canUpdate(input: NFTState, output: NFTState): Promise<Bool> {
629
+ // Default implementation: returns true (e.g., always allow updates)
630
+ }
631
+
632
+ @method.returns(Bool)
633
+ async canTransfer(transferEvent: TransferEvent): Promise<Bool> {
634
+ // Default implementation: returns true (e.g., always allow transfers)
635
+ }
636
+
637
+ @method
638
+ async pause(): Promise<void> {
639
+ // Pauses the contract if canBePaused is true and the caller is the admin
640
+ }
641
+
642
+ @method
643
+ async resume(): Promise<void> {
644
+ // Resumes the contract if canBePaused is true and the caller is the admin
645
+ }
646
+
647
+ @method.returns(PublicKey)
648
+ async transferOwnership(newOwner: PublicKey): Promise<PublicKey> {
649
+ // Transfers contract ownership to a new admin only if the contract is paused
650
+ }
651
+
652
+ // -------------------------
653
+ // Fine-grained checks
654
+ // -------------------------
655
+ @method.returns(Bool)
656
+ async canChangeRoyalty(royaltyFee: UInt32): Promise<Bool> {
657
+ // Returns true if allowChangeRoyalty is true and the admin has signed
658
+ }
659
+
660
+ @method.returns(Bool)
661
+ async canChangeTransferFee(transferFee: UInt64): Promise<Bool> {
662
+ // Returns true if allowChangeTransferFee is true and the admin has signed
663
+ }
664
+
665
+ @method.returns(Bool)
666
+ async canChangeVerificationKey(
667
+ vk: VerificationKey,
668
+ address: PublicKey,
669
+ tokenId: Field
670
+ ): Promise<Bool> {
671
+ // Allows verifying or restricting verification key changes for specific addresses/tokens
672
+ // The default here checks admin signature
673
+ }
674
+
675
+ // Additional checks like canChangeName, canChangeBaseUri, etc. default to returning false or requiring admin signature
676
+ }
677
+ ```
678
+
679
+ • ensureOwnerSignature()
680
+ – Internal helper that creates a signed AccountUpdate restricted to the admin’s signature, preventing unauthorized calls and improper fee usage.
681
+
682
+ Overall, NFTAdmin provides a baseline set of administrative operations for an NFT collection. More specialized admin contracts can extend NFTAdmin to override methods like canMint or canTransfer with more advanced logic, such as whitelisting or KYC rules.
683
+
684
+ #### Advanced Admin Contract
685
+
686
+ The **Advanced Admin Contract** (`advanced.ts`) is a sophisticated implementation of an admin contract that provides comprehensive control over NFT operations through whitelisting and configurable permissions. It implements multiple interfaces including `NFTAdminBase`, `UpgradableContract`, `PausableContract`, and `OwnableContract`.
687
+
688
+ ##### Key Features
689
+
690
+ - **Whitelist-Based Access Control**: Uses a Merkle tree-based whitelist system to control who can interact with NFTs
691
+ - **Configurable Permissions**: Fine-grained control over various administrative actions through `AdminData`
692
+ - **Pause Mechanism**: Ability to pause/resume contract operations
693
+ - **Upgrade Support**: Secure verification key upgrade system through an Upgrade Authority Contract
694
+ - **Ownership Management**: Secure ownership transfer with proper authorization checks
695
+
696
+ ##### State Variables
697
+
698
+ ```typescript:src/admin/advanced.ts
699
+ class NFTAdvancedAdmin extends SmartContract {
700
+ @state(PublicKey) admin: State<PublicKey>;
701
+ @state(PublicKey) upgradeAuthority: State<PublicKey>;
702
+ @state(Field) data: State<Field>; // Packed AdminData
703
+ @state(Whitelist) whitelist: State<Whitelist>;
704
+ }
705
+ ```
706
+
707
+ ##### Key Methods
708
+
709
+ ###### Access Control Methods
710
+
711
+ ```typescript:src/admin/advanced.ts
712
+ @method.returns(MintParamsOption)
713
+ async canMint(mintRequest: MintRequest): Promise<MintParamsOption> {
714
+ // Verifies both owner and sender are whitelisted
715
+ // Checks contract isn't paused
716
+ // Returns none() by default (can be extended for custom minting logic)
717
+ }
718
+
719
+ @method.returns(Bool)
720
+ async canUpdate(input: NFTState, output: NFTState): Promise<Bool> {
721
+ // Ensures contract isn't paused
722
+ // Verifies both current and new owners are whitelisted
723
+ }
724
+
725
+ @method.returns(Bool)
726
+ async canTransfer(transferEvent: TransferEvent): Promise<Bool> {
727
+ // Verifies both sender and receiver are whitelisted
728
+ // Checks if their whitelisted amounts are sufficient for the transfer price
729
+ // Ensures contract isn't paused
730
+ }
731
+ ```
732
+
733
+ ###### Administrative Methods
734
+
735
+ ```typescript:src/admin/advanced.ts
736
+ @method
737
+ async updateWhitelist(whitelist: Whitelist) {
738
+ // Updates the whitelist Merkle root and storage
739
+ // Requires owner signature and unpaused contract
740
+ }
741
+
742
+ @method
743
+ async pause(): Promise<void> {
744
+ // Pauses the contract if canPause is true
745
+ // Requires owner signature
746
+ }
747
+
748
+ @method
749
+ async resume(): Promise<void> {
750
+ // Resumes the contract if canPause is true
751
+ // Requires owner signature
752
+ }
753
+
754
+ @method.returns(PublicKey)
755
+ async transferOwnership(to: PublicKey): Promise<PublicKey> {
756
+ // Transfers contract ownership
757
+ // Requires owner signature and unpaused contract
758
+ }
759
+ ```
760
+
761
+ ###### Configuration Methods
762
+
763
+ ```typescript:src/admin/advanced.ts
764
+ @method.returns(Bool)
765
+ async canChangeVerificationKey(
766
+ vk: VerificationKey,
767
+ address: PublicKey,
768
+ tokenId: Field
769
+ ): Promise<Bool>
770
+
771
+ @method.returns(Bool)
772
+ async canChangeName(name: Field): Promise<Bool>
773
+
774
+ @method.returns(Bool)
775
+ async canChangeCreator(creator: PublicKey): Promise<Bool>
776
+
777
+ @method.returns(Bool)
778
+ async canChangeBaseUri(baseUri: Field): Promise<Bool>
779
+
780
+ @method.returns(Bool)
781
+ async canChangeRoyalty(royaltyFee: UInt32): Promise<Bool>
782
+
783
+ @method.returns(Bool)
784
+ async canChangeTransferFee(transferFee: UInt64): Promise<Bool>
785
+
786
+ @method.returns(Bool)
787
+ async canSetAdmin(admin: PublicKey): Promise<Bool>
788
+ ```
789
+
790
+ ###### Events
791
+
792
+ - `updateWhitelist`: Emitted when the whitelist is updated
793
+ - `pause`: Emitted when the contract is paused
794
+ - `resume`: Emitted when the contract is resumed
795
+ - `ownershipChange`: Emitted when contract ownership changes
796
+ - `upgradeVerificationKey`: Emitted when verification key is upgraded
797
+
798
+ ###### Usage
799
+
800
+ The Advanced Admin Contract is ideal for:
801
+
802
+ 1. **Regulated NFT Collections**: Where participation requires KYC/AML verification
803
+ 2. **Tiered Access Systems**: Where different addresses have different transaction limits
804
+ 3. **Managed Marketplaces**: Where transfers and trades need administrative oversight
805
+ 4. **Upgradeable Collections**: Supporting secure contract upgrades through verification key management
806
+
807
+ ###### Security Features
808
+
809
+ - All administrative actions require owner signature verification
810
+ - Pause mechanism prevents operations during maintenance or emergencies
811
+ - Whitelist-based access control with amount restrictions
812
+ - Merkle tree implementation for efficient and secure whitelist verification
813
+ - Integration with Upgrade Authority Contract for secure verification key management
814
+
815
+ This contract provides a robust foundation for building regulated and controlled NFT ecosystems while maintaining flexibility for custom business logic implementation.
816
+
817
+ ### Upgrade Authority Contract
818
+
819
+ The **Upgrade Authority Contract** provides a secure mechanism for upgrading the verification keys of smart contracts without requiring redeployment. It manages a list of validators who can vote on upgrade proposals, ensuring that only authorized upgrades are applied.
820
+
821
+ #### Key Features
822
+
823
+ - **Verification Key Management**: Allows for secure upgrades of verification keys for other contracts.
824
+ - **Validators Governance**: Maintains a list of authorized validators who can vote on upgrade proposals.
825
+ - **Secure Voting Mechanism**: Implements Zero-Knowledge proofs to validate votes from validators without revealing sensitive information.
826
+ - **Upgrade Database Management**: Keeps track of upgrade proposals and their validity periods.
827
+ - **Event Emissions**: Emits events when validators list or upgrade database is updated.
828
+
829
+ #### State Variables
830
+
831
+ - `verificationKeyHash`: The hash of the proof verification key (`Field`).
832
+ - `validators`: The hash representing the current state of the validators list (`Field`).
833
+ - `upgradeDatabasePacked`: Packed state containing the upgrade database information (`UpgradeDatabaseStatePacked`).
834
+
835
+ #### Key Methods
836
+
837
+ ```typescript:src/upgrade/upgrade.ts
838
+ class VerificationKeyUpgradeAuthority extends SmartContract implements UpgradeAuthorityBase {
839
+ @method
840
+ async initialize(validators: ValidatorsState, storage: Storage, verificationKeyHash: Field) {
841
+ // Initialize the contract with validators and set the verification key hash
842
+ }
843
+
844
+ @method.returns(UpgradeAuthorityAnswer)
845
+ async verifyUpgradeData(data: VerificationKeyUpgradeData): Promise<UpgradeAuthorityAnswer> {
846
+ // Verify the upgrade data provided by another contract
847
+ }
848
+
849
+ @method
850
+ async updateDatabase(proof: ValidatorsVotingProof, vk: VerificationKey) {
851
+ // Update the upgrade database after validator consensus
852
+ }
853
+
854
+ @method
855
+ async updateValidatorsList(validators: ValidatorsState, storage: Storage, proof: ValidatorsVotingProof, vk: VerificationKey) {
856
+ // Update the validators list based on validator votes
857
+ }
858
+
859
+ // ... Additional methods and helper functions
860
+ }
861
+ ```
862
+
863
+ #### Events
864
+
865
+ - `validatorsList`: Emitted when the validators list is updated.
866
+ - `updateDatabase`: Emitted when the upgrade database is updated.
867
+
868
+ #### Notes
869
+
870
+ - **Validator Governance**: Validators can vote on upgrade proposals. The contract uses Zero-Knowledge proofs (ZkPrograms) to verify validator votes securely.
871
+ - **Upgrade Process**: Contracts wishing to upgrade their verification keys interact with the Upgrade Authority Contract to verify that the new verification key is authorized.
872
+ - **Validators List Management**: The validators list is stored as a Merkle Tree for efficient verification and can be updated through consensus.
873
+ - **Off-chain Data**: Some data, like the full validators list, is stored off-chain (e.g., in IPFS) with only the root hash stored on-chain to optimize performance.
874
+ - **Security**: The contract ensures that only valid upgrade proposals that have been approved by the required number of validators are executed.
875
+
876
+ #### Usage Example
877
+
878
+ This contract is essential for scenarios where:
879
+
880
+ - **Decentralized Governance**: Multiple validators need to agree on contract upgrades, ensuring no single party can unilaterally upgrade the contract.
881
+ - **Secure Contract Upgrades**: Contracts can securely upgrade their verification keys without redeploying, maintaining continuity and state.
882
+ - **Regulated Environments**: Applications requiring compliance and oversight can leverage validator governance for contract changes.
883
+
884
+ For a contract to utilize the Upgrade Authority Contract, it needs to implement the `UpgradableContract` interface and interact with the `VerificationKeyUpgradeAuthority` for upgrading its verification key securely.
885
+
886
+ ### Ownable Interface
887
+
888
+ The **Ownable Interface** provides an interface for ownership control mechanisms in smart contracts. It extends the `SmartContract` class and defines methods to ensure that only the owner can perform certain actions and to allow the transfer of ownership to a new owner. The key methods include:
889
+
890
+ - `ensureOwnerSignature()`: Ensures that the transaction is authorized by the contract owner, typically used to restrict access to sensitive functions.
891
+
892
+ - `transferOwnership(newOwner: PublicKey)`: Allows the current owner to transfer ownership of the contract to a new owner, returning the old owner's `PublicKey`.
893
+
894
+ Additionally, the `OwnershipChangeEvent` class represents an event emitted when the ownership of the contract changes, containing the `oldOwner` and `newOwner` public keys.
895
+
896
+ By implementing the Ownable interface, contracts can secure critical operations and provide a transparent mechanism for ownership management.
897
+
898
+ ##### Key Methods
899
+
900
+ ```typescript:src/ownable.ts
901
+ class OwnableContract extends SmartContract {
902
+ @method
903
+ async ensureOwnerSignature() {
904
+ // Ensure that the transaction is signed by the owner
905
+ }
906
+
907
+ @method
908
+ async transferOwnership(newOwner: PublicKey) {
909
+ // Transfer ownership to a new owner
910
+ }
911
+
912
+ // ... Additional methods and properties
913
+ }
914
+ ```
915
+
916
+ ### Pausable Interface
917
+
918
+ The **Pausable Interface** provides a mechanism to dynamically enable or disable certain functionalities within smart contracts. It extends the `SmartContract` class and introduces methods that allow a contract to be paused and resumed, which is crucial for managing emergencies, upgrades, or maintenance periods.
919
+
920
+ **Key Methods and Features:**
921
+
922
+ - `pause()`: Pauses the contract, potentially halting critical operations to protect against unforeseen issues or to perform maintenance. When called, the contract enters a paused state where certain functions are restricted.
923
+
924
+ - `resume()`: Resumes the contract's operations after it has been paused. This method restores the contract to its normal working state, allowing all functionalities to be accessible again.
925
+
926
+ The interface also includes the `PauseEvent` class, which is emitted whenever the contract is paused or resumed. This event contains the `isPaused` boolean field, indicating the current state of the contract.
927
+
928
+ By implementing the Pausable interface, contracts gain greater control over their operational states, enhancing security and flexibility in response to various scenarios.
929
+
930
+ ##### Key Methods
931
+
932
+ ```typescript:src/pausable.ts
933
+ class PausableContract extends SmartContract {
934
+ @method
935
+ async pause() {
936
+ // Logic to pause the contract
937
+ }
938
+
939
+ @method
940
+ async resume() {
941
+ // Logic to resume the contract
942
+ }
943
+
944
+ // ... Additional methods and properties
945
+ }
946
+
947
+ class PauseEvent extends Struct({
948
+ isPaused: Bool,
949
+ }) {}
950
+ ```
951
+
952
+ ### Upgradable Interface
953
+
954
+ The **Upgradable Interface** introduces a standardized way to upgrade the verification keys of smart contracts on the Mina blockchain. It allows contracts to be updated securely and efficiently, ensuring they remain compatible with protocol changes or receive enhancements without deploying entirely new contracts.
955
+
956
+ **Key Classes and Features:**
957
+
958
+ - `VerificationKeyUpgradeData`: A structured data class containing the necessary information for upgrading a contract's verification key. It includes the contract's address, token ID, previous verification key hash, and the new verification key hash. It also provides a `hash()` method to generate a unique identifier for the upgrade data.
959
+
960
+ - `PublicKeyOption`: An optional `PublicKey` type, used to specify the next upgrade authority if needed. This is crucial when the current upgrade authority cannot be used in future upgrades due to changes in the o1js version or other factors.
961
+
962
+ - `UpgradeAuthorityAnswer`: A structured response from the upgrade authority after verifying the upgrade data. It contains:
963
+
964
+ - `nextUpgradeAuthority`: An optional public key of the next upgrade authority if a change is required.
965
+ - `isVerified`: A boolean indicating whether the upgrade data has been successfully verified.
966
+
967
+ - `UpgradeAuthorityBase`: An interface that any upgrade authority contract should implement. It extends `SmartContract` and requires the implementation of the `verifyUpgradeData()` method, which takes `VerificationKeyUpgradeData` as input and returns an `UpgradeAuthorityAnswer`.
968
+
969
+ - `UpgradableContract`: An interface for contracts that can be upgraded. It extends `SmartContract` and requires:
970
+ - `getUpgradeContract()`: A method to retrieve the associated upgrade authority contract.
971
+ - `upgradeVerificationKey()`: A method to upgrade the contract's verification key using the provided verification key.
972
+
973
+ By implementing the Upgradable Interface, contracts can securely upgrade their verification keys through a standardized process, maintaining the integrity and security of the smart contract ecosystem on Mina.
974
+
975
+ ##### Key Classes and Methods
976
+
977
+ ```typescript
978
+ class VerificationKeyUpgradeData extends Struct({
979
+ address: PublicKey,
980
+ tokenId: Field,
981
+ previousVerificationKeyHash: Field,
982
+ newVerificationKeyHash: Field,
983
+ }) {
984
+ hash(): Field {
985
+ return Poseidon.hash(VerificationKeyUpgradeData.toFields(this));
986
+ }
987
+ }
988
+
989
+ class PublicKeyOption extends Option(PublicKey) {}
990
+
991
+ class UpgradeAuthorityAnswer extends Struct({
992
+ nextUpgradeAuthority: PublicKeyOption,
993
+ isVerified: Bool,
994
+ }) {}
995
+
996
+ type UpgradeAuthorityBase = SmartContract & {
997
+ verifyUpgradeData(
998
+ data: VerificationKeyUpgradeData
999
+ ): Promise<UpgradeAuthorityAnswer>;
1000
+ };
1001
+
1002
+ type UpgradableContract = SmartContract & {
1003
+ getUpgradeContract(): Promise<UpgradeAuthorityBase>;
1004
+ upgradeVerificationKey(vk: VerificationKey): Promise<void>;
1005
+ };
1006
+ ```
1007
+
1008
+ **Usage Example:**
1009
+
1010
+ Contracts implementing the `UpgradableContract` interface can upgrade their verification keys by interacting with an upgrade authority contract that implements `UpgradeAuthorityBase`. By following this pattern, smart contracts can be upgraded in a secure and controlled manner, allowing for continuous improvements and compliance with evolving standards.
1011
+
1012
+ **Note:** If an upgrade requires changing the upgrade authority (due to compatibility issues with newer versions), the `nextUpgradeAuthority` field in `UpgradeAuthorityAnswer` provides the public key of the new authority to be used in future upgrades.
1013
+
1014
+ ### Metadata Interface
1015
+
1016
+ The MinaNFT standard includes a robust `Metadata` interface that allows for secure and efficient representation of NFT metadata on-chain using Merkle trees. By leveraging Merkle trees, metadata can be stored compactly, and proofs can be generated to verify specific metadata elements without revealing the entire data.
1017
+
1018
+ ##### Key Components
1019
+
1020
+ - **Metadata Class (`metadata.ts`):** Represents the metadata for an NFT, including traits and associated data. It uses a specialized `MetadataMap`, which is an `IndexedMerkleMap`, to store key-value pairs of metadata traits securely.
1021
+
1022
+ - **Text Class (`text.ts`):** Represents textual data in the form of a Merkle tree. Each character of the text is converted to its ASCII code and stored as a leaf in the Merkle tree. This allows for efficient verification and integrity checks of large text data without revealing the entire content.
1023
+
1024
+ - **MetadataTree Class (`tree.ts`):** Represents a metadata tree using a Merkle tree structure. It manages a set of key-value pairs where each key is an index in the tree, and each value is a `Field` element. This class enables secure and verifiable storage of arbitrary metadata.
1025
+
1026
+ - **MetadataPlugin Class (`metadata.ts`):** An abstract class for creating custom metadata plugins. Plugins can define custom trait types and how they are serialized and deserialized, allowing for extensible metadata schemas.
1027
+
1028
+ ##### Key Classes and Methods
1029
+
1030
+ ```typescript
1031
+ // metadata.ts
1032
+
1033
+ class Metadata {
1034
+ readonly map: MetadataMap;
1035
+ readonly name: string;
1036
+ image: string;
1037
+ banner?: string;
1038
+ description?: string;
1039
+ plugins: MetadataPlugin[];
1040
+ traits: {
1041
+ [key: string]: {
1042
+ type: string;
1043
+ value: string | Field | Metadata | MetadataTree | unknown;
1044
+ isPrivate: boolean;
1045
+ };
1046
+ } = {};
1047
+
1048
+ constructor(params: {
1049
+ name: string;
1050
+ image: string;
1051
+ description?: string;
1052
+ banner?: string;
1053
+ plugins?: MetadataPlugin[];
1054
+ }) {
1055
+ // Initialization logic...
1056
+ }
1057
+
1058
+ /**
1059
+ * Adds a trait to the metadata.
1060
+ * @param params - The parameters including key, type, value, and isPrivate.
1061
+ */
1062
+ addTrait(params: {
1063
+ key: string;
1064
+ type: string;
1065
+ value: string | Field | Metadata | MetadataTree | unknown;
1066
+ isPrivate?: boolean;
1067
+ }): {
1068
+ key: Field;
1069
+ value: MetadataValue;
1070
+ } {
1071
+ // Trait addition logic...
1072
+ }
1073
+
1074
+ /**
1075
+ * Converts the metadata to a JSON representation.
1076
+ * @param includePrivateTraits - Whether to include private traits.
1077
+ */
1078
+ toJSON(includePrivateTraits = false): {
1079
+ name: string;
1080
+ image: string;
1081
+ description?: string;
1082
+ banner?: string;
1083
+ metadataRoot: string;
1084
+ traits: {
1085
+ key: string;
1086
+ type: string;
1087
+ value: string | object;
1088
+ isPrivate?: boolean;
1089
+ }[];
1090
+ } {
1091
+ // Serialization logic...
1092
+ }
1093
+
1094
+ /**
1095
+ * Constructs a Metadata instance from JSON data.
1096
+ */
1097
+ static fromJSON(params: {
1098
+ json: {
1099
+ name: string;
1100
+ image: string;
1101
+ description?: string;
1102
+ banner?: string;
1103
+ metadataRoot: string;
1104
+ traits: {
1105
+ key: string;
1106
+ type: string;
1107
+ value: string | object;
1108
+ isPrivate?: boolean;
1109
+ }[];
1110
+ };
1111
+ checkRoot?: boolean;
1112
+ plugins?: MetadataPlugin[];
1113
+ }): Metadata {
1114
+ // Deserialization logic...
1115
+ }
1116
+ }
1117
+
1118
+ abstract class MetadataPlugin {
1119
+ readonly name: string;
1120
+
1121
+ /**
1122
+ * Retrieves the trait representation of the metadata value.
1123
+ */
1124
+ abstract getTrait(params: {
1125
+ key: string;
1126
+ type: string;
1127
+ value: unknown;
1128
+ isPrivate?: boolean;
1129
+ }): {
1130
+ key: Field;
1131
+ value: MetadataValue;
1132
+ canonicalRepresentation: unknown;
1133
+ };
1134
+
1135
+ /**
1136
+ * Converts the value to JSON.
1137
+ */
1138
+ abstract toJSON(value: unknown): string | object;
1139
+
1140
+ /**
1141
+ * Parses the value from JSON.
1142
+ */
1143
+ abstract fromJSON(value: string | object): unknown;
1144
+ }
1145
+
1146
+ class ColorPlugin extends MetadataPlugin {
1147
+ readonly name = "color";
1148
+
1149
+ /**
1150
+ * Retrieves the trait representation of the color value.
1151
+ */
1152
+ getTrait(params: {
1153
+ key: string;
1154
+ type: string;
1155
+ value: Color | string | number;
1156
+ }): {
1157
+ key: Field;
1158
+ value: MetadataValue;
1159
+ canonicalRepresentation: number;
1160
+ } {
1161
+ // Trait handling logic...
1162
+ }
1163
+
1164
+ /**
1165
+ * Converts the color value to a JSON string.
1166
+ */
1167
+ toJSON(value: Color | string | number): string {
1168
+ // Serialization logic...
1169
+ }
1170
+
1171
+ /**
1172
+ * Parses the color value from a JSON string or object.
1173
+ */
1174
+ fromJSON(value: string | object): number {
1175
+ // Deserialization logic...
1176
+ }
1177
+ }
1178
+
1179
+ // text.ts
1180
+
1181
+ class Text {
1182
+ readonly size: number;
1183
+ readonly text: string;
1184
+ readonly root: Field;
1185
+ readonly height: number;
1186
+
1187
+ constructor(text: string, height: number = TEXT_TREE_HEIGHT) {
1188
+ // Initialization logic...
1189
+ }
1190
+
1191
+ /**
1192
+ * Returns the original text string.
1193
+ */
1194
+ toString(): string {
1195
+ return this.text;
1196
+ }
1197
+ }
1198
+
1199
+ // tree.ts
1200
+
1201
+ class MetadataTree {
1202
+ readonly values: { key: bigint; value: Field }[];
1203
+ readonly height: number;
1204
+ readonly root: Field;
1205
+
1206
+ constructor(height: number, values: { key: bigint; value: Field }[]) {
1207
+ // Initialization logic...
1208
+ }
1209
+
1210
+ /**
1211
+ * Serializes the MetadataTree to a JSON object.
1212
+ */
1213
+ toJSON(): {
1214
+ height: number;
1215
+ root: string;
1216
+ values: { key: string; value: string }[];
1217
+ } {
1218
+ // Serialization logic...
1219
+ }
1220
+
1221
+ /**
1222
+ * Deserializes a JSON object into a MetadataTree instance.
1223
+ */
1224
+ static fromJSON(json: {
1225
+ height: number;
1226
+ root: string;
1227
+ values: { key: string; value: string }[];
1228
+ }): MetadataTree {
1229
+ // Deserialization logic...
1230
+ }
1231
+ }
1232
+ ```
1233
+
1234
+ ##### Usage Example
1235
+
1236
+ Here's how you can create and use the `Metadata` class with custom traits and plugins:
1237
+
1238
+ ```typescript
1239
+ import { Metadata, ColorPlugin } from "./metadata";
1240
+
1241
+ // Initialize metadata with basic attributes and plugins
1242
+ const metadata = new Metadata({
1243
+ name: "MyUniqueNFT",
1244
+ image: "ipfs://imageHash",
1245
+ description: "An exclusive NFT.",
1246
+ plugins: [new ColorPlugin()],
1247
+ });
1248
+
1249
+ // Add standard traits
1250
+ metadata.addTrait({
1251
+ key: "rarity",
1252
+ type: "string",
1253
+ value: "legendary",
1254
+ });
1255
+
1256
+ metadata.addTrait({
1257
+ key: "origin",
1258
+ type: "text",
1259
+ value: "Mina Protocol",
1260
+ });
1261
+
1262
+ // Add a custom trait using a plugin
1263
+ metadata.addTrait({
1264
+ key: "backgroundColor",
1265
+ type: "color",
1266
+ value: "blue",
1267
+ });
1268
+
1269
+ // Serialize metadata to JSON
1270
+ const metadataJSON = metadata.toJSON();
1271
+
1272
+ // Deserialize metadata from JSON
1273
+ const metadataFromJSON = Metadata.fromJSON({
1274
+ json: metadataJSON,
1275
+ plugins: [new ColorPlugin()],
1276
+ });
1277
+ ```
1278
+
1279
+ **Note:** By using Merkle trees to represent metadata, the MinaNFT standard ensures that metadata can be efficiently verified on-chain without storing the entire data. This approach is particularly useful for large text fields or complex nested metadata structures, enabling secure and verifiable NFTs on the Mina Protocol.
1280
+
1281
+ ### NFT Program
1282
+
1283
+ The **NFT Program** is a Zero-Knowledge (ZK) program designed to provide privacy-preserving proofs for updating NFT metadata off-chain. It allows NFT owners to modify their NFTs' metadata without exposing sensitive information on-chain, ensuring both confidentiality and verifiability.
1284
+
1285
+ #### Key Methods and Features
1286
+
1287
+ - **`insertMetadata`**: Inserts a new key-value pair into the NFT's metadata Merkle tree. This method performs several critical steps:
1288
+
1289
+ - Verifies that the signature provided is valid and corresponds to the NFT owner.
1290
+ - Ensures the key does not already exist in the metadata, preventing duplicate entries.
1291
+ - Updates the NFT state with the new metadata root and increments the version number.
1292
+
1293
+ - **`merge`**: Merges two self-proofs to produce an updated NFT state. This is useful for batching multiple metadata updates into a single proof, optimizing on-chain verification. It ensures:
1294
+ - Both proofs are valid and correctly verified.
1295
+ - The output of the first proof matches the input of the second, maintaining consistency.
1296
+ - Returns the final NFT state after applying both updates.
1297
+
1298
+ #### Usage Example
1299
+
1300
+ Here's how you can use the `NFTProgram` to update NFT metadata off-chain and generate a proof for on-chain verification:
1301
+
1302
+ ```typescript
1303
+ import { NFTProgram, MetadataMap, NFTState } from "./update";
1304
+ import { Field, Signature, PrivateKey } from "o1js";
1305
+
1306
+ // Initialize the initial NFT state
1307
+ const initialState = new NFTState({
1308
+ // ... initialize with existing NFT state fields
1309
+ });
1310
+
1311
+ // Create a MetadataMap instance representing the current metadata Merkle tree
1312
+ const metadata = new MetadataMap(initialState.metadata);
1313
+
1314
+ // Define the key and value to insert into the metadata
1315
+ const key = Field(/* some key */);
1316
+ const value = Field(/* some value */);
1317
+
1318
+ // Owner's private key
1319
+ const ownerPrivateKey = PrivateKey.fromBase58(/* owner's private key */);
1320
+ const ownerPublicKey = ownerPrivateKey.toPublicKey();
1321
+
1322
+ // Get the owner's signature authorizing the metadata update
1323
+ const signature = Signature.create(ownerPrivateKey, [
1324
+ ...NFTState.toFields(initialState),
1325
+ key,
1326
+ value,
1327
+ ]);
1328
+
1329
+ // Generate a zero-knowledge proof for inserting the metadata
1330
+ const { proof, publicOutput, auxiliaryOutput } = await NFTProgram.prove(
1331
+ "insertMetadata",
1332
+ initialState,
1333
+ metadata,
1334
+ key,
1335
+ value,
1336
+ signature
1337
+ );
1338
+
1339
+ // The `publicOutput` contains the updated NFT state with the new metadata root
1340
+ // The `auxiliaryOutput` is the updated MetadataMap that can be used for further updates
1341
+
1342
+ // The generated proof can be submitted on-chain to update the NFT's metadata
1343
+ // The contract will verify the proof and update the on-chain state accordingly
1344
+ ```
1345
+
1346
+ **Note:** By using the NFT Program, you can perform multiple metadata updates off-chain and only submit succinct proofs to the blockchain. This approach greatly enhances scalability and privacy, as the actual metadata contents remain off-chain and are not exposed publicly.
1347
+
1348
+ #### Benefits of Using NFT Program
1349
+
1350
+ - **Privacy Preservation**: Sensitive metadata is kept off-chain, ensuring that only authorized parties can view or modify it.
1351
+ - **Scalability**: Reduces on-chain computation and storage requirements by handling complex operations off-chain.
1352
+ - **Verifiability**: On-chain verification of proofs ensures that all updates are authorized and comply with the NFT's rules.
1353
+ - **Efficiency**: Batch multiple updates using the `merge` method to optimize transactions and reduce fees.
1354
+
1355
+ #### Important Considerations
1356
+
1357
+ - **Signature Verification**: It's crucial that the NFT owner's signature is correctly generated and verified to prevent unauthorized updates.
1358
+ - **Off-chain Storage**: While metadata is stored off-chain, it's important to use reliable and secure storage solutions to prevent data loss or tampering.
1359
+
1360
+ By integrating the NFT Program into your NFT contracts, you can leverage advanced features of the Mina Protocol to build secure, private, and efficient NFT applications.
1361
+
1362
+ By keeping the constraint usage well below the maximum limit, we ensure that the contracts are efficient and maintain optimal performance on the Mina network.
1363
+
1364
+ ## Gap Analysis in Comparison with ERC721
1365
+
1366
+ ### Gap Analysis
1367
+
1368
+ In comparison to the ERC-721 standard, the MinaNFT standard intentionally omits or modifies certain features to align with the Mina Protocol's design and objectives.
1369
+
1370
+ | **Feature** | **Recommendation** | **Reasoning** |
1371
+ | ----------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1372
+ | **balanceOf** | Skip (Implementable off-chain) | Implementing `balanceOf` on-chain would introduce significant overhead without much benefit. For NFTs, this feature is not critical, as NFTs represent unique assets rather than balances. For those requiring this functionality, it can be computed off-chain using tools like the Blockberry API, avoiding contract modifications. |
1373
+ | **tokenOfOwnerByIndex** | Skip (Implementable off-chain) | On-chain implementation of this feature is infeasible, and off-chain solutions would be cumbersome with notable overhead. Since it’s not a crucial function for most NFT use cases, skipping it is recommended. Users needing this feature can calculate it off-chain via the Blockberry API without changing the contract. |
1374
+ | **safeTransferFrom** | Skip (Near-equivalent functionality exists) | While `safeTransferFrom` ensures that NFTs are only transferred to valid addresses, similar protection is already built into MinaNFT’s buy/sell mechanism, where the receiver must sign for payment. Although a transfer could still occur to an invalid address, an off-chain check is already available in the frontend, making an on-chain implementation unnecessary. |
1375
+ | **burn** | Skip or Maybe Implement | Implementing a burn function is feasible, but its utility is limited unless account deletion and the recovery of the 1 MINA account creation fee are supported. As such, this feature can be deferred unless future developments make it more useful. |
1376
+ | |
1377
+
1378
+ ### Advantages of MinaNFT Over ERC-721
1379
+
1380
+ - **Enhanced Privacy**: MinaNFT allows for both public and private data to be associated with NFTs, ensuring that sensitive information can be securely stored and shared. With Mina’s zero-knowledge proofs, users can verify both public and private content without revealing any underlying data, a feature unavailable in ERC-721.
1381
+ - **On-Chain and Off-Chain Verifiability**: MinaNFT enables both on-chain and off-chain verifiability of content, opening up new use cases such as attaching sensitive documents, contracts, and private media to NFTs while maintaining verifiable authenticity.
1382
+ - **Lower Overhead for Transactions**: Since Mina does not require high gas fees like Ethereum, there is no need for features like `setApprovalForAll` designed to save on transaction costs. This allows the MinaNFT standard to focus on security and functionality rather than optimization for gas fees.
1383
+
1384
+ ## Roadmap and Applications
1385
+
1386
+ ### Upcoming Developments
1387
+
1388
+ - **MinaNFT V3**: Introduces new features such as IndexedMerkleMap for faster proof calculations, parent-child relationships, time-locked NFTs, Rollup NFT V3 for use in app-chains and L2, and monitoring and indexing infrastructure.
1389
+ - **MinaNFT New Frontend**: A redesigned frontend with new features like leaderboards and ratings.
1390
+ - **Support in Explorers and Wallets**: Integration of the new NFT standard into minascan explorer and wallets.
1391
+ - **ZKProgram Plugins**: Community-created ZKPrograms (e.g., zkEmail) that can mutate and prove the metadata.
1392
+ - **zkProver Project: RWA**: Real-world applications using programmable NFTs.
1393
+
1394
+ ## Conclusion
1395
+
1396
+ The NFT standard on Mina Protocol presents a robust framework for creating and managing NFTs with enhanced privacy, security, and functionality. By leveraging Mina's zero-knowledge proofs and off-chain verifiability, the standard opens up new possibilities for NFTs in various domains. The detailed architecture and comprehensive contracts ensure interoperability and ease of integration, fostering a vibrant ecosystem for developers and users alike.
1397
+
1398
+ ---
1399
+
1400
+ **Note**: The detailed methods and classes provided above are a summary based on the final design from the specified files. For complete implementations and the most up-to-date code, please refer to the actual codebase.