@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
@@ -0,0 +1,3 @@
1
+ export * from "./collection.js";
2
+ export * from "./nft.js";
3
+ export * from "./admin.js";
@@ -0,0 +1,344 @@
1
+ import {
2
+ Field,
3
+ PublicKey,
4
+ Bool,
5
+ SmartContract,
6
+ method,
7
+ state,
8
+ State,
9
+ VerificationKey,
10
+ } from "o1js";
11
+ import { Storage } from "@silvana-one/storage";
12
+ import {
13
+ NFTData,
14
+ NFTDataPacked,
15
+ NFTState,
16
+ NFTImmutableState,
17
+ UpdateEvent,
18
+ TransferExtendedParams,
19
+ UpgradeVerificationKeyEvent,
20
+ PauseEvent,
21
+ OwnershipChangeEvent,
22
+ UpgradeVerificationKeyData,
23
+ NFTStateStruct,
24
+ NFTTransactionContext,
25
+ } from "../interfaces/index.js";
26
+
27
+ export { NFT };
28
+
29
+ const NftErrors = {
30
+ cannotChangeMetadataVerificationKeyHash:
31
+ "Cannot change metadata verification key hash",
32
+ cannotChangeOwner: "Cannot change owner",
33
+ cannotChangeStorage: "Cannot change storage",
34
+ cannotChangePauseState: "Cannot change pause state",
35
+ noPermissionToPause: "No permission to pause",
36
+ nftAlreadyPaused: "NFT is already paused",
37
+ nftIsNotPaused: "NFT is not paused",
38
+ nftIsPaused: "NFT is paused",
39
+ cannotChangeName: "Cannot change name",
40
+ cannotChangeMetadata: "Cannot change metadata",
41
+ noMetadataVerificationKey: "No metadata verification key",
42
+ };
43
+
44
+ /**
45
+ * The NFT Contract represents an individual NFT within a collection.
46
+ *
47
+ * It manages the state and behavior of a single NFT, including ownership, metadata,
48
+ * storage, pricing, and permissions. The contract provides functionality for updating
49
+ * NFT properties with proofs and permissions, transferring ownership, selling and buying NFTs,
50
+ * upgrading the verification key, and pausing or resuming the NFT.
51
+ */
52
+ class NFT extends SmartContract {
53
+ /** The name of the NFT (`Field`). */
54
+ @state(Field) name = State<Field>();
55
+
56
+ /** The metadata associated with the NFT (`Field`). */
57
+ @state(Field) metadata = State<Field>();
58
+
59
+ /** Holds off-chain storage information, e.g., IPFS hash (`Storage`). */
60
+ @state(Storage) storage = State<Storage>();
61
+
62
+ /** A packed field containing additional NFT data and flags (`Field`). */
63
+ @state(NFTDataPacked) packedData = State<NFTDataPacked>();
64
+
65
+ /** The hash of the verification key used for metadata proofs (`Field`). */
66
+ @state(Field) metadataVerificationKeyHash = State<Field>();
67
+
68
+ /** Events emitted by the NFT contract. */
69
+ events = {
70
+ update: UpdateEvent,
71
+ transfer: OwnershipChangeEvent,
72
+ approve: PublicKey,
73
+ upgradeVerificationKey: UpgradeVerificationKeyEvent,
74
+ pause: PauseEvent,
75
+ resume: PauseEvent,
76
+ };
77
+
78
+ @method.returns(NFTStateStruct)
79
+ async getState(): Promise<NFTStateStruct> {
80
+ const name = this.name.getAndRequireEquals();
81
+ const metadata = this.metadata.getAndRequireEquals();
82
+ const storage = this.storage.getAndRequireEquals();
83
+ const packedData = this.packedData.getAndRequireEquals();
84
+ const metadataVerificationKeyHash =
85
+ this.metadataVerificationKeyHash.getAndRequireEquals();
86
+ return new NFTStateStruct({
87
+ name,
88
+ metadata,
89
+ storage,
90
+ packedData,
91
+ metadataVerificationKeyHash,
92
+ });
93
+ }
94
+
95
+ /**
96
+ * Updates the NFT's state with provided proofs and permissions.
97
+ *
98
+ * @param input - The current state of the NFT (`NFTState`).
99
+ * @param output - The desired new state of the NFT (`NFTState`).
100
+ * @param creator - The public key of the creator (`PublicKey`).
101
+ * @returns The hash of the metadata verification key (`Field`).
102
+ */
103
+ @method.returns(Field)
104
+ async update(
105
+ input: NFTState,
106
+ output: NFTState,
107
+ creator: PublicKey
108
+ ): Promise<Field> {
109
+ const name = this.name.getAndRequireEquals();
110
+ const metadata = this.metadata.getAndRequireEquals();
111
+ const data = NFTData.unpack(this.packedData.getAndRequireEquals());
112
+ const owner = data.owner;
113
+
114
+ const storage = this.storage.getAndRequireEquals();
115
+ const metadataVerificationKeyHash =
116
+ this.metadataVerificationKeyHash.getAndRequireEquals();
117
+ // Check that the metadata verification key exists
118
+ metadataVerificationKeyHash.assertNotEquals(
119
+ Field(0),
120
+ NftErrors.noMetadataVerificationKey
121
+ );
122
+
123
+ // We do not check if the NFT is paused here
124
+ // It is the responsibility of metadata zkProgram to check if the NFT is paused,
125
+ // similar to data.isPaused.assertFalse(NftErrors.nftIsPaused);
126
+
127
+ // Assert that the public input matches the NFT state
128
+ NFTState.assertEqual(
129
+ input,
130
+ new NFTState({
131
+ immutableState: new NFTImmutableState({
132
+ canChangeOwnerByProof: data.canChangeOwnerByProof,
133
+ canTransfer: data.canTransfer,
134
+ canApprove: data.canApprove,
135
+ canChangeMetadata: data.canChangeMetadata,
136
+ canChangeStorage: data.canChangeStorage,
137
+ canChangeName: data.canChangeName,
138
+ canChangeMetadataVerificationKeyHash:
139
+ data.canChangeMetadataVerificationKeyHash,
140
+ canPause: data.canPause,
141
+ address: this.address,
142
+ tokenId: this.tokenId,
143
+ id: data.id,
144
+ }),
145
+ name,
146
+ metadata,
147
+ storage,
148
+ owner,
149
+ approved: data.approved,
150
+ version: data.version,
151
+ isPaused: data.isPaused,
152
+ metadataVerificationKeyHash,
153
+ creator,
154
+ context: input.context,
155
+ oracleAddress: input.oracleAddress,
156
+ })
157
+ );
158
+
159
+ // assert that the read-only fields are not changed
160
+ input.creator.assertEquals(output.creator);
161
+ NFTTransactionContext.assertEqual(input.context, output.context);
162
+ input.oracleAddress.assertEquals(output.oracleAddress);
163
+ // Check permissions and set new state
164
+ name
165
+ .equals(output.name)
166
+ .not()
167
+ .and(data.canChangeName.not())
168
+ .assertFalse(NftErrors.cannotChangeName);
169
+ this.name.set(output.name);
170
+
171
+ metadata
172
+ .equals(output.metadata)
173
+ .not()
174
+ .and(data.canChangeMetadata.not())
175
+ .assertFalse(NftErrors.cannotChangeMetadata);
176
+ this.metadata.set(output.metadata);
177
+
178
+ metadataVerificationKeyHash
179
+ .equals(output.metadataVerificationKeyHash)
180
+ .not()
181
+ .and(data.canChangeMetadataVerificationKeyHash.not())
182
+ .assertFalse(NftErrors.cannotChangeMetadataVerificationKeyHash);
183
+ this.metadataVerificationKeyHash.set(output.metadataVerificationKeyHash);
184
+
185
+ owner
186
+ .equals(output.owner)
187
+ .not()
188
+ .and(data.canChangeOwnerByProof.not())
189
+ .assertFalse(NftErrors.cannotChangeOwner);
190
+
191
+ Storage.equals(storage, output.storage)
192
+ .not()
193
+ .and(data.canChangeStorage.not())
194
+ .assertFalse(NftErrors.cannotChangeStorage);
195
+ this.storage.set(output.storage);
196
+
197
+ data.approved
198
+ .equals(output.approved)
199
+ .not()
200
+ .and(data.canChangeOwnerByProof.not())
201
+ .assertFalse(NftErrors.cannotChangeOwner);
202
+
203
+ data.isPaused
204
+ .equals(output.isPaused)
205
+ .not()
206
+ .and(data.canPause.not())
207
+ .assertFalse(NftErrors.cannotChangePauseState);
208
+
209
+ // recursive proofs can increase the version by more than 1
210
+ output.version.assertGreaterThan(data.version);
211
+
212
+ data.owner = output.owner;
213
+ data.approved = output.approved;
214
+ data.version = output.version;
215
+
216
+ this.packedData.set(data.pack());
217
+
218
+ const event = new UpdateEvent({
219
+ name: output.name,
220
+ metadata: output.metadata,
221
+ storage: output.storage,
222
+ owner: output.owner,
223
+ approved: output.approved,
224
+ version: output.version,
225
+ isPaused: output.isPaused,
226
+ metadataVerificationKeyHash: output.metadataVerificationKeyHash,
227
+ });
228
+ this.emitEvent("update", event);
229
+ return metadataVerificationKeyHash;
230
+ }
231
+
232
+ /**
233
+ * Transfers ownership of the NFT from one user to another.
234
+ *
235
+ * @param params - The parameters for the transfer (`TransferExtendedParams`).
236
+ * @returns The public key of the old owner (`PublicKey`).
237
+ */
238
+ @method.returns(TransferExtendedParams)
239
+ async transfer(
240
+ params: TransferExtendedParams
241
+ ): Promise<TransferExtendedParams> {
242
+ const data = NFTData.unpack(this.packedData.getAndRequireEquals());
243
+ data.canTransfer.assertTrue(NftErrors.cannotChangeOwner);
244
+ data.isPaused.assertFalse(NftErrors.nftIsPaused);
245
+ const owner = data.owner;
246
+ const approved = data.approved;
247
+ params.transferByOwner = owner.equals(params.from);
248
+
249
+ owner
250
+ .equals(params.from)
251
+ .or(
252
+ approved
253
+ .equals(params.from)
254
+ .and(approved.equals(PublicKey.empty()).not())
255
+ )
256
+ .assertTrue(NftErrors.cannotChangeOwner);
257
+ params.from = owner;
258
+ params.approved = approved;
259
+ const version = data.version.add(1);
260
+ data.version = version;
261
+ data.approved = PublicKey.empty();
262
+ data.owner = params.to;
263
+ this.packedData.set(data.pack());
264
+ this.emitEvent(
265
+ "transfer",
266
+ new OwnershipChangeEvent({
267
+ from: owner,
268
+ to: params.to,
269
+ })
270
+ );
271
+
272
+ return params;
273
+ }
274
+
275
+ /**
276
+ * Transfers ownership of the NFT from one user to another.
277
+ *
278
+ * @param approved - The public key of the approved address (`PublicKey`).
279
+ * @returns The public key of the owner (`PublicKey`).
280
+ */
281
+ @method.returns(PublicKey)
282
+ async approveAddress(approved: PublicKey): Promise<PublicKey> {
283
+ const data = NFTData.unpack(this.packedData.getAndRequireEquals());
284
+ data.isPaused.assertFalse(NftErrors.nftIsPaused);
285
+ data.approved = approved;
286
+ this.packedData.set(data.pack());
287
+ this.emitEvent("approve", approved);
288
+ return data.owner;
289
+ }
290
+
291
+ /**
292
+ * Upgrades the verification key used by the NFT contract.
293
+ *
294
+ * @param vk - The new verification key (`VerificationKey`).
295
+ * @returns An owner public key to be checked by the Collection contract and the Boolean flag indicating if the owner's authorization is required
296
+ */
297
+ @method.returns(UpgradeVerificationKeyData)
298
+ async upgradeVerificationKey(
299
+ vk: VerificationKey
300
+ ): Promise<UpgradeVerificationKeyData> {
301
+ const data = NFTData.unpack(this.packedData.getAndRequireEquals());
302
+
303
+ const version = data.version.add(1);
304
+ data.version = version;
305
+ this.account.verificationKey.set(vk);
306
+ this.packedData.set(data.pack());
307
+ return new UpgradeVerificationKeyData({
308
+ owner: data.owner,
309
+ isOwnerApprovalRequired: data.requireOwnerAuthorizationToUpgrade,
310
+ });
311
+ }
312
+
313
+ /**
314
+ * Pauses the NFT, disabling certain actions.
315
+ *
316
+ * @returns An owner public key to be checked by the Collection contract
317
+ */
318
+ @method.returns(PublicKey)
319
+ async pause(): Promise<PublicKey> {
320
+ const data = NFTData.unpack(this.packedData.getAndRequireEquals());
321
+ data.canPause.assertTrue(NftErrors.noPermissionToPause);
322
+ data.isPaused.assertFalse(NftErrors.nftAlreadyPaused);
323
+ data.isPaused = Bool(true);
324
+ this.packedData.set(data.pack());
325
+ this.emitEvent("pause", new PauseEvent({ isPaused: Bool(true) }));
326
+ return data.owner;
327
+ }
328
+
329
+ /**
330
+ * Resumes the NFT, re-enabling actions.
331
+ *
332
+ * @returns An owner public key to be checked by the Collection contract
333
+ */
334
+ @method.returns(PublicKey)
335
+ async resume(): Promise<PublicKey> {
336
+ const data = NFTData.unpack(this.packedData.getAndRequireEquals());
337
+ data.canPause.assertTrue(NftErrors.noPermissionToPause);
338
+ data.isPaused.assertTrue(NftErrors.nftIsNotPaused);
339
+ data.isPaused = Bool(false);
340
+ this.packedData.set(data.pack());
341
+ this.emitEvent("resume", new PauseEvent({ isPaused: Bool(false) }));
342
+ return data.owner;
343
+ }
344
+ }
@@ -0,0 +1,107 @@
1
+ import { CollectionFactory, NFTAdmin } from "./contracts/index.js";
2
+ import { NFTAdvancedAdminContract } from "./admin/index.js";
3
+ import { VerificationKeyUpgradeAuthority } from "@silvana-one/upgradable";
4
+ import { OfferFactory } from "./marketplace/offer.js";
5
+ import {
6
+ NFTOwnerContractConstructor,
7
+ NFTAdminContractConstructor,
8
+ NFTApprovalContractConstructor,
9
+ NFTStandardOwner,
10
+ DefineApprovalFactory,
11
+ DefineOwnerFactory,
12
+ DefineUpdateFactory,
13
+ NFTStandardUpdate,
14
+ NFTUpdateContractConstructor,
15
+ } from "./interfaces/index.js";
16
+
17
+ export const NFTAdvancedAdmin = NFTAdvancedAdminContract({
18
+ upgradeContract: VerificationKeyUpgradeAuthority,
19
+ });
20
+
21
+ export type NonFungibleTokenContracts = {
22
+ Collection: ReturnType<typeof CollectionFactory>;
23
+ Approval: NFTApprovalContractConstructor;
24
+ Owner: NFTOwnerContractConstructor;
25
+ Admin: NFTAdminContractConstructor;
26
+ Update: NFTUpdateContractConstructor;
27
+ };
28
+
29
+ export function NonFungibleTokenContractsFactory(params: {
30
+ adminContract?: NFTAdminContractConstructor;
31
+ approvalFactory?: DefineApprovalFactory;
32
+ ownerFactory?: DefineOwnerFactory;
33
+ updateFactory?: DefineUpdateFactory;
34
+ }): NonFungibleTokenContracts {
35
+ const {
36
+ adminContract = NFTAdmin,
37
+ approvalFactory = OfferFactory,
38
+ ownerFactory = ({ collectionContract }) => NFTStandardOwner,
39
+ updateFactory = ({ collectionContract }) => NFTStandardUpdate,
40
+ } = params;
41
+
42
+ let Collection: ReturnType<typeof CollectionFactory>;
43
+ let Approval: NFTApprovalContractConstructor;
44
+ let Owner: NFTOwnerContractConstructor;
45
+ let Admin: NFTAdminContractConstructor = adminContract;
46
+ let Update: NFTUpdateContractConstructor;
47
+
48
+ function getCollection() {
49
+ if (!Collection) {
50
+ throw new Error("Collection constructor not set up yet!");
51
+ }
52
+ return Collection;
53
+ }
54
+ function getApproval() {
55
+ if (!Approval) {
56
+ throw new Error("Approval constructor not set up yet!");
57
+ }
58
+ return Approval;
59
+ }
60
+
61
+ function getUpdate() {
62
+ if (!Update) {
63
+ throw new Error("Update constructor not set up yet!");
64
+ }
65
+ return Update;
66
+ }
67
+
68
+ function getOwner() {
69
+ if (!Owner) {
70
+ throw new Error("Owner constructor not set up yet!");
71
+ }
72
+ return Owner;
73
+ }
74
+
75
+ Approval = approvalFactory({
76
+ collectionContract: getCollection,
77
+ });
78
+
79
+ Update = updateFactory({
80
+ collectionContract: getCollection,
81
+ });
82
+
83
+ Collection = CollectionFactory({
84
+ adminContract: () => adminContract,
85
+ ownerContract: getOwner,
86
+ approvalContract: getApproval,
87
+ updateContract: getUpdate,
88
+ });
89
+
90
+ Owner = ownerFactory({
91
+ collectionContract: getCollection,
92
+ });
93
+
94
+ return { Collection, Approval, Owner, Admin, Update };
95
+ }
96
+
97
+ export const { Collection, Approval, Owner, Admin, Update } =
98
+ NonFungibleTokenContractsFactory({});
99
+
100
+ export const {
101
+ Collection: AdvancedCollection,
102
+ Approval: AdvancedApproval,
103
+ Owner: AdvancedOwner,
104
+ Admin: AdvancedAdmin,
105
+ } = NonFungibleTokenContractsFactory({
106
+ adminContract: NFTAdvancedAdmin,
107
+ });
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from "./admin/index.js";
2
+ export * from "./contracts/index.js";
3
+ export * from "./metadata/index.js";
4
+ export * from "./zkprogram-example/index.js";
5
+ export * from "./marketplace/index.js";
6
+ export * from "./vk.js";
7
+ export * from "./contracts.js";
8
+ export * from "./interfaces/index.js";
@@ -0,0 +1,127 @@
1
+ import {
2
+ Bool,
3
+ PublicKey,
4
+ SmartContract,
5
+ VerificationKey,
6
+ Field,
7
+ UInt32,
8
+ UInt64,
9
+ } from "o1js";
10
+ import { MintParamsOption, MintRequest, NFTState } from "./types.js";
11
+ import { TransferEvent } from "./events.js";
12
+ export { NFTAdminBase, NFTAdminContractConstructor };
13
+
14
+ /**
15
+ * The `NFTAdminBase` interface defines the administrative functionalities required for managing an NFT collection on the Mina Protocol.
16
+ * It extends the `SmartContract` class and specifies methods that enforce permissions and validations for various NFT operations.
17
+ */
18
+ type NFTAdminBase = SmartContract & {
19
+ /**
20
+ * Validates whether a new NFT can be minted based on the provided `MintRequest`.
21
+ *
22
+ * @param nft - The mint request containing details of the NFT to be minted.
23
+ * @returns A `Promise` resolving to `MintParamsOption`, containing mint parameters if minting is allowed, or an empty option if not.
24
+ */
25
+ canMint(nft: MintRequest): Promise<MintParamsOption>;
26
+
27
+ /**
28
+ * Checks if an NFT can be updated from its current state (`input`) to a new state (`output`).
29
+ *
30
+ * @param input - The current state of the NFT.
31
+ * @param output - The desired new state of the NFT.
32
+ * @returns A `Promise` resolving to a `Bool` indicating whether the update is permitted.
33
+ */
34
+ canUpdate(input: NFTState, output: NFTState): Promise<Bool>;
35
+
36
+ /**
37
+ * Determines if an NFT can be transferred from one owner (`from`) to another (`to`) for a specific NFT contract address.
38
+ *
39
+ * @param transferEvent - The transfer event containing details of the transfer.
40
+ * @returns A `Promise` resolving to a `Bool` indicating whether the transfer is allowed.
41
+ */
42
+ canTransfer(transferEvent: TransferEvent): Promise<Bool>;
43
+
44
+ /**
45
+ * Determines if the name can be changed for a Collection.
46
+ *
47
+ * @param name - The new name for the Collection.
48
+ * @returns A `Promise` resolving to a `Bool` indicating whether the name change is allowed.
49
+ */
50
+ canChangeName(name: Field): Promise<Bool>;
51
+
52
+ /**
53
+ * Determines if the creator can be changed for a Collection.
54
+ *
55
+ * @param creator - The new creator for the Collection.
56
+ * @returns A `Promise` resolving to a `Bool` indicating whether the creator change is allowed.
57
+ */
58
+ canChangeCreator(creator: PublicKey): Promise<Bool>;
59
+
60
+ /**
61
+ * Determines if the base URI can be changed for a Collection.
62
+ *
63
+ * @param baseUri - The new base URI for the Collection.
64
+ * @returns A `Promise` resolving to a `Bool` indicating whether the base URI change is allowed.
65
+ */
66
+ canChangeBaseUri(baseUri: Field): Promise<Bool>;
67
+
68
+ /**
69
+ * Determines if the royalty fee can be changed for a Collection.
70
+ *
71
+ * @param royaltyFee - The new royalty fee for the Collection.
72
+ * @returns A `Promise` resolving to a `Bool` indicating whether the royalty fee change is allowed.
73
+ */
74
+ canChangeRoyalty(royaltyFee: UInt32): Promise<Bool>;
75
+
76
+ /**
77
+ * Determines if the transfer fee can be changed for a Collection.
78
+ *
79
+ * @param transferFee - The new transfer fee for the Collection.
80
+ * @returns A `Promise` resolving to a `Bool` indicating whether the transfer fee change is allowed.
81
+ */
82
+ canChangeTransferFee(transferFee: UInt64): Promise<Bool>;
83
+
84
+ /**
85
+ * Determines if the admin contract can be changed for a Collection.
86
+ *
87
+ * @param admin - The new admin for the Collection.
88
+ * @returns A `Promise` resolving to a `Bool` indicating whether the admin contract change is allowed.
89
+ */
90
+ canSetAdmin(admin: PublicKey): Promise<Bool>;
91
+
92
+ /**
93
+ * Determines if the collection can be paused.
94
+ *
95
+ * @returns A `Promise` resolving to a `Bool` indicating whether the collection can be paused.
96
+ */
97
+ canPause(): Promise<Bool>;
98
+
99
+ /**
100
+ * Determines if the collection can be resumed.
101
+ *
102
+ * @returns A `Promise` resolving to a `Bool` indicating whether the collection can be resumed.
103
+ */
104
+ canResume(): Promise<Bool>;
105
+
106
+ /**
107
+ * Determines if the verification key can be changed for a specific NFT contract address and token ID.
108
+ *
109
+ * @param vk - The verification key to be changed.
110
+ * @param address - The public key of the NFT contract address or CollectionContract address.
111
+ * @param tokenId - The token ID of the NFT.
112
+ * @returns A `Promise` resolving to a `Bool` indicating whether the verification key change is allowed.
113
+ */
114
+ canChangeVerificationKey(
115
+ vk: VerificationKey,
116
+ address: PublicKey,
117
+ tokenId: Field
118
+ ): Promise<Bool>;
119
+ };
120
+
121
+ /**
122
+ * Defines a constructor for contracts implementing `NFTAdminBase`, accepting an `address` public key and returning an instance of `NFTAdminBase`.
123
+ *
124
+ * @param address - The contract's address.
125
+ * @returns An instance of `NFTAdminBase`.
126
+ */
127
+ type NFTAdminContractConstructor = new (address: PublicKey) => NFTAdminBase;
@@ -0,0 +1,99 @@
1
+ import {
2
+ AccountUpdate,
3
+ Bool,
4
+ method,
5
+ PublicKey,
6
+ SmartContract,
7
+ state,
8
+ State,
9
+ Permissions,
10
+ DeployArgs,
11
+ } from "o1js";
12
+ import { NFTCollectionContractConstructor } from "./collection.js";
13
+ import { TransferExtendedParams } from "./types.js";
14
+ export {
15
+ NFTApprovalBase,
16
+ NFTApprovalContractConstructor,
17
+ NFTStandardApproval,
18
+ NFTApprovalDeployProps,
19
+ DefineApprovalFactory,
20
+ };
21
+ type DefineApprovalFactory = (params: {
22
+ collectionContract: () => NFTCollectionContractConstructor;
23
+ }) => NFTApprovalContractConstructor;
24
+
25
+ /**
26
+ * The `NFTApprovalBase` interface defines the administrative functionalities required for managing an NFT transfer approval on the Mina Protocol.
27
+ */
28
+ type NFTApprovalBase = SmartContract & {
29
+ /**
30
+ * Determines if an NFT can be transferred from one owner (`from`) to another (`to`) for a specific NFT contract address.
31
+ *
32
+ * @param params - The transfer details.
33
+ * @returns A `Promise` resolving to a `Bool` indicating whether the transfer is allowed.
34
+ */
35
+ canTransfer(params: TransferExtendedParams): Promise<Bool>;
36
+ };
37
+
38
+ /**
39
+ * Defines a constructor for contracts implementing `NFTApprovalBase`, accepting an `address` public key and returning an instance of `NFTApprovalBase`.
40
+ *
41
+ * @param address - The public key of the contract's owner.
42
+ * @returns An instance of `NFTApprovalBase`.
43
+ */
44
+ type NFTApprovalContractConstructor = new (
45
+ address: PublicKey
46
+ ) => NFTApprovalBase;
47
+
48
+ interface NFTApprovalDeployProps extends Exclude<DeployArgs, undefined> {
49
+ admin: PublicKey;
50
+ uri: string;
51
+ }
52
+
53
+ /**
54
+ * The **NFTStandardApproval** contract is the default implementation of the `NFTApprovalBase` interface.
55
+ */
56
+ class NFTStandardApproval extends SmartContract implements NFTApprovalBase {
57
+ /**
58
+ * The public key of the contract's administrator.
59
+ * This account has the authority to perform administrative actions such as pausing the contract or upgrading the verification key.
60
+ */
61
+ @state(PublicKey) admin = State<PublicKey>();
62
+
63
+ /**
64
+ * Deploys the contract with initial settings.
65
+ * @param props - Deployment properties including admin, upgradeAuthority, uri, canPause, and isPaused.
66
+ */
67
+ async deploy(props: NFTApprovalDeployProps) {
68
+ await super.deploy(props);
69
+ this.admin.set(props.admin);
70
+ this.account.zkappUri.set(props.uri);
71
+ this.account.permissions.set({
72
+ ...Permissions.default(),
73
+ setVerificationKey: Permissions.VerificationKey.signature(),
74
+ setPermissions: Permissions.impossible(),
75
+ });
76
+ }
77
+
78
+ /**
79
+ * Ensures that the transaction is authorized by the contract owner.
80
+ * @returns A signed `AccountUpdate` from the admin.
81
+ */
82
+ async ensureOwnerSignature(): Promise<AccountUpdate> {
83
+ const admin = this.admin.getAndRequireEquals();
84
+ const adminUpdate = AccountUpdate.createSigned(admin);
85
+ adminUpdate.body.useFullCommitment = Bool(true); // Prevent memo and fee change
86
+ return adminUpdate;
87
+ }
88
+ /**
89
+ * Determines if an NFT can be transferred.
90
+ *
91
+ * @param params - The transfer details.
92
+ * @returns A `Promise` resolving to a `Bool` indicating whether the transfer is allowed.
93
+ */
94
+ @method.returns(Bool)
95
+ async canTransfer(params: TransferExtendedParams): Promise<Bool> {
96
+ await this.ensureOwnerSignature();
97
+ return Bool(true);
98
+ }
99
+ }