@silvana-one/nft 0.2.0 → 0.2.1

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 (190) hide show
  1. package/dist/tsconfig.web.tsbuildinfo +1 -0
  2. package/dist/web/admin/advanced.js.map +1 -0
  3. package/dist/web/admin/index.js.map +1 -0
  4. package/dist/web/contracts/admin.js.map +1 -0
  5. package/dist/web/contracts/collection.js.map +1 -0
  6. package/dist/web/contracts/index.js.map +1 -0
  7. package/dist/web/contracts/nft.js.map +1 -0
  8. package/dist/web/contracts.js.map +1 -0
  9. package/dist/web/index.js.map +1 -0
  10. package/dist/web/{src/interfaces → interfaces}/admin.js.map +1 -1
  11. package/dist/web/interfaces/approval.js.map +1 -0
  12. package/dist/web/interfaces/collection.js.map +1 -0
  13. package/dist/web/interfaces/encoding.js.map +1 -0
  14. package/dist/web/interfaces/events.js.map +1 -0
  15. package/dist/web/interfaces/index.js.map +1 -0
  16. package/dist/web/interfaces/ownable.js.map +1 -0
  17. package/dist/web/interfaces/owner.js.map +1 -0
  18. package/dist/web/interfaces/pausable.js.map +1 -0
  19. package/dist/web/interfaces/types.js.map +1 -0
  20. package/dist/web/interfaces/update.js.map +1 -0
  21. package/dist/web/marketplace/auction.js.map +1 -0
  22. package/dist/web/marketplace/bb.js.map +1 -0
  23. package/dist/web/marketplace/bid.js.map +1 -0
  24. package/dist/web/marketplace/index.js.map +1 -0
  25. package/dist/web/marketplace/nft-shares.js.map +1 -0
  26. package/dist/web/marketplace/offer.js.map +1 -0
  27. package/dist/web/marketplace/types.js.map +1 -0
  28. package/dist/web/metadata/address.js.map +1 -0
  29. package/dist/web/metadata/index.js.map +1 -0
  30. package/dist/web/metadata/metadata.js.map +1 -0
  31. package/dist/web/metadata/pin.js.map +1 -0
  32. package/dist/web/metadata/text.js.map +1 -0
  33. package/dist/web/metadata/tree.js.map +1 -0
  34. package/dist/web/util/div.js.map +1 -0
  35. package/dist/web/util/index.js.map +1 -0
  36. package/dist/web/vk.js.map +1 -0
  37. package/dist/web/zkprogram-example/game.js.map +1 -0
  38. package/dist/web/zkprogram-example/index.js.map +1 -0
  39. package/dist/web/zkprogram-example/update.js.map +1 -0
  40. package/package.json +8 -8
  41. package/dist/web/src/admin/advanced.js.map +0 -1
  42. package/dist/web/src/admin/index.js.map +0 -1
  43. package/dist/web/src/contracts/admin.js.map +0 -1
  44. package/dist/web/src/contracts/collection.js.map +0 -1
  45. package/dist/web/src/contracts/index.js.map +0 -1
  46. package/dist/web/src/contracts/nft.js.map +0 -1
  47. package/dist/web/src/contracts.js.map +0 -1
  48. package/dist/web/src/index.js.map +0 -1
  49. package/dist/web/src/interfaces/approval.js.map +0 -1
  50. package/dist/web/src/interfaces/collection.js.map +0 -1
  51. package/dist/web/src/interfaces/encoding.js.map +0 -1
  52. package/dist/web/src/interfaces/events.js.map +0 -1
  53. package/dist/web/src/interfaces/index.js.map +0 -1
  54. package/dist/web/src/interfaces/ownable.js.map +0 -1
  55. package/dist/web/src/interfaces/owner.js.map +0 -1
  56. package/dist/web/src/interfaces/pausable.js.map +0 -1
  57. package/dist/web/src/interfaces/types.js.map +0 -1
  58. package/dist/web/src/interfaces/update.js.map +0 -1
  59. package/dist/web/src/marketplace/auction.js.map +0 -1
  60. package/dist/web/src/marketplace/bb.js.map +0 -1
  61. package/dist/web/src/marketplace/bid.js.map +0 -1
  62. package/dist/web/src/marketplace/index.js.map +0 -1
  63. package/dist/web/src/marketplace/nft-shares.js.map +0 -1
  64. package/dist/web/src/marketplace/offer.js.map +0 -1
  65. package/dist/web/src/marketplace/types.js.map +0 -1
  66. package/dist/web/src/metadata/address.js.map +0 -1
  67. package/dist/web/src/metadata/index.js.map +0 -1
  68. package/dist/web/src/metadata/metadata.js.map +0 -1
  69. package/dist/web/src/metadata/pin.js.map +0 -1
  70. package/dist/web/src/metadata/text.js.map +0 -1
  71. package/dist/web/src/metadata/tree.js.map +0 -1
  72. package/dist/web/src/util/div.js.map +0 -1
  73. package/dist/web/src/util/index.js.map +0 -1
  74. package/dist/web/src/vk.js.map +0 -1
  75. package/dist/web/src/zkprogram-example/game.js.map +0 -1
  76. package/dist/web/src/zkprogram-example/index.js.map +0 -1
  77. package/dist/web/src/zkprogram-example/update.js.map +0 -1
  78. package/dist/web/test/auction.test.d.ts +0 -1212
  79. package/dist/web/test/auction.test.js +0 -1248
  80. package/dist/web/test/auction.test.js.map +0 -1
  81. package/dist/web/test/bb.test.d.ts +0 -1
  82. package/dist/web/test/bb.test.js +0 -159
  83. package/dist/web/test/bb.test.js.map +0 -1
  84. package/dist/web/test/contract.test.d.ts +0 -1
  85. package/dist/web/test/contract.test.js +0 -1333
  86. package/dist/web/test/contract.test.js.map +0 -1
  87. package/dist/web/test/div.test.d.ts +0 -1
  88. package/dist/web/test/div.test.js +0 -55
  89. package/dist/web/test/div.test.js.map +0 -1
  90. package/dist/web/test/helpers/config.d.ts +0 -4
  91. package/dist/web/test/helpers/config.js +0 -103
  92. package/dist/web/test/helpers/config.js.map +0 -1
  93. package/dist/web/test/helpers/metadata.d.ts +0 -30
  94. package/dist/web/test/helpers/metadata.js +0 -155
  95. package/dist/web/test/helpers/metadata.js.map +0 -1
  96. package/dist/web/test/helpers/utils.d.ts +0 -16
  97. package/dist/web/test/helpers/utils.js +0 -36
  98. package/dist/web/test/helpers/utils.js.map +0 -1
  99. package/dist/web/test/helpers/validators.d.ts +0 -15
  100. package/dist/web/test/helpers/validators.js +0 -46
  101. package/dist/web/test/helpers/validators.js.map +0 -1
  102. package/dist/web/test/metadata.test.d.ts +0 -1
  103. package/dist/web/test/metadata.test.js +0 -66
  104. package/dist/web/test/metadata.test.js.map +0 -1
  105. package/dist/web/test/mint.test.d.ts +0 -1
  106. package/dist/web/test/mint.test.js +0 -262
  107. package/dist/web/test/mint.test.js.map +0 -1
  108. package/dist/web/test/pack.test.d.ts +0 -1
  109. package/dist/web/test/pack.test.js +0 -141
  110. package/dist/web/test/pack.test.js.map +0 -1
  111. package/dist/web/test/zkprogram.test.d.ts +0 -1
  112. package/dist/web/test/zkprogram.test.js +0 -728
  113. package/dist/web/test/zkprogram.test.js.map +0 -1
  114. package/dist/web/tsconfig.web.tsbuildinfo +0 -1
  115. /package/dist/web/{src/admin → admin}/advanced.d.ts +0 -0
  116. /package/dist/web/{src/admin → admin}/advanced.js +0 -0
  117. /package/dist/web/{src/admin → admin}/index.d.ts +0 -0
  118. /package/dist/web/{src/admin → admin}/index.js +0 -0
  119. /package/dist/web/{src/contracts → contracts}/admin.d.ts +0 -0
  120. /package/dist/web/{src/contracts → contracts}/admin.js +0 -0
  121. /package/dist/web/{src/contracts → contracts}/collection.d.ts +0 -0
  122. /package/dist/web/{src/contracts → contracts}/collection.js +0 -0
  123. /package/dist/web/{src/contracts → contracts}/index.d.ts +0 -0
  124. /package/dist/web/{src/contracts → contracts}/index.js +0 -0
  125. /package/dist/web/{src/contracts → contracts}/nft.d.ts +0 -0
  126. /package/dist/web/{src/contracts → contracts}/nft.js +0 -0
  127. /package/dist/web/{src/contracts.d.ts → contracts.d.ts} +0 -0
  128. /package/dist/web/{src/contracts.js → contracts.js} +0 -0
  129. /package/dist/web/{src/index.d.ts → index.d.ts} +0 -0
  130. /package/dist/web/{src/index.js → index.js} +0 -0
  131. /package/dist/web/{src/interfaces → interfaces}/admin.d.ts +0 -0
  132. /package/dist/web/{src/interfaces → interfaces}/admin.js +0 -0
  133. /package/dist/web/{src/interfaces → interfaces}/approval.d.ts +0 -0
  134. /package/dist/web/{src/interfaces → interfaces}/approval.js +0 -0
  135. /package/dist/web/{src/interfaces → interfaces}/collection.d.ts +0 -0
  136. /package/dist/web/{src/interfaces → interfaces}/collection.js +0 -0
  137. /package/dist/web/{src/interfaces → interfaces}/encoding.d.ts +0 -0
  138. /package/dist/web/{src/interfaces → interfaces}/encoding.js +0 -0
  139. /package/dist/web/{src/interfaces → interfaces}/events.d.ts +0 -0
  140. /package/dist/web/{src/interfaces → interfaces}/events.js +0 -0
  141. /package/dist/web/{src/interfaces → interfaces}/index.d.ts +0 -0
  142. /package/dist/web/{src/interfaces → interfaces}/index.js +0 -0
  143. /package/dist/web/{src/interfaces → interfaces}/ownable.d.ts +0 -0
  144. /package/dist/web/{src/interfaces → interfaces}/ownable.js +0 -0
  145. /package/dist/web/{src/interfaces → interfaces}/owner.d.ts +0 -0
  146. /package/dist/web/{src/interfaces → interfaces}/owner.js +0 -0
  147. /package/dist/web/{src/interfaces → interfaces}/pausable.d.ts +0 -0
  148. /package/dist/web/{src/interfaces → interfaces}/pausable.js +0 -0
  149. /package/dist/web/{src/interfaces → interfaces}/types.d.ts +0 -0
  150. /package/dist/web/{src/interfaces → interfaces}/types.js +0 -0
  151. /package/dist/web/{src/interfaces → interfaces}/update.d.ts +0 -0
  152. /package/dist/web/{src/interfaces → interfaces}/update.js +0 -0
  153. /package/dist/web/{src/marketplace → marketplace}/auction.d.ts +0 -0
  154. /package/dist/web/{src/marketplace → marketplace}/auction.js +0 -0
  155. /package/dist/web/{src/marketplace → marketplace}/bb.d.ts +0 -0
  156. /package/dist/web/{src/marketplace → marketplace}/bb.js +0 -0
  157. /package/dist/web/{src/marketplace → marketplace}/bid.d.ts +0 -0
  158. /package/dist/web/{src/marketplace → marketplace}/bid.js +0 -0
  159. /package/dist/web/{src/marketplace → marketplace}/index.d.ts +0 -0
  160. /package/dist/web/{src/marketplace → marketplace}/index.js +0 -0
  161. /package/dist/web/{src/marketplace → marketplace}/nft-shares.d.ts +0 -0
  162. /package/dist/web/{src/marketplace → marketplace}/nft-shares.js +0 -0
  163. /package/dist/web/{src/marketplace → marketplace}/offer.d.ts +0 -0
  164. /package/dist/web/{src/marketplace → marketplace}/offer.js +0 -0
  165. /package/dist/web/{src/marketplace → marketplace}/types.d.ts +0 -0
  166. /package/dist/web/{src/marketplace → marketplace}/types.js +0 -0
  167. /package/dist/web/{src/metadata → metadata}/address.d.ts +0 -0
  168. /package/dist/web/{src/metadata → metadata}/address.js +0 -0
  169. /package/dist/web/{src/metadata → metadata}/index.d.ts +0 -0
  170. /package/dist/web/{src/metadata → metadata}/index.js +0 -0
  171. /package/dist/web/{src/metadata → metadata}/metadata.d.ts +0 -0
  172. /package/dist/web/{src/metadata → metadata}/metadata.js +0 -0
  173. /package/dist/web/{src/metadata → metadata}/pin.d.ts +0 -0
  174. /package/dist/web/{src/metadata → metadata}/pin.js +0 -0
  175. /package/dist/web/{src/metadata → metadata}/text.d.ts +0 -0
  176. /package/dist/web/{src/metadata → metadata}/text.js +0 -0
  177. /package/dist/web/{src/metadata → metadata}/tree.d.ts +0 -0
  178. /package/dist/web/{src/metadata → metadata}/tree.js +0 -0
  179. /package/dist/web/{src/util → util}/div.d.ts +0 -0
  180. /package/dist/web/{src/util → util}/div.js +0 -0
  181. /package/dist/web/{src/util → util}/index.d.ts +0 -0
  182. /package/dist/web/{src/util → util}/index.js +0 -0
  183. /package/dist/web/{src/vk.d.ts → vk.d.ts} +0 -0
  184. /package/dist/web/{src/vk.js → vk.js} +0 -0
  185. /package/dist/web/{src/zkprogram-example → zkprogram-example}/game.d.ts +0 -0
  186. /package/dist/web/{src/zkprogram-example → zkprogram-example}/game.js +0 -0
  187. /package/dist/web/{src/zkprogram-example → zkprogram-example}/index.d.ts +0 -0
  188. /package/dist/web/{src/zkprogram-example → zkprogram-example}/index.js +0 -0
  189. /package/dist/web/{src/zkprogram-example → zkprogram-example}/update.d.ts +0 -0
  190. /package/dist/web/{src/zkprogram-example → zkprogram-example}/update.js +0 -0
@@ -1,728 +0,0 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import { afterEach, beforeEach, describe, it } from "node:test";
3
- import assert from "node:assert";
4
- import { Mina, Field, AccountUpdate, UInt32, Cache, UInt64, fetchLastBlock, PublicKey, Struct, state, State, SmartContract, method, Provable, Bool, } from "o1js";
5
- import { fetchMinaAccount, initBlockchain, accountBalanceMina, Memory, sendTx, pinJSON, } from "@silvana-one/mina-utils";
6
- import { TEST_ACCOUNTS } from "./helpers/config.js";
7
- import { NFT, NFTAdmin, CollectionData, fieldFromString, NFTData, NFTState, NFTUpdateProof, NFTStateStruct, MintParams, NFTGameProgram, nftVerificationKeys, Metadata, NonFungibleTokenContractsFactory, NFTTransactionContext, TransferParams, MetadataValue, } from "../src/index.js";
8
- import { processArguments } from "./helpers/utils.js";
9
- import { randomMetadata } from "./helpers/metadata.js";
10
- import { Storage, UInt64Option, createIpfsURL } from "@silvana-one/storage";
11
- let { chain, readOnly, noLog } = processArguments();
12
- const networkId = chain === "mainnet" ? "mainnet" : "devnet";
13
- const expectedTxStatus = chain === "zeko" ? "pending" : "included";
14
- const vk = nftVerificationKeys[networkId].vk;
15
- const { TestPublicKey } = Mina;
16
- /*
17
- “Richard Of York Gave Battle In Vain”:
18
- 1. Richard – Red
19
- Hex: #FF0000
20
- 2. Of – Orange
21
- Hex: #FFA500
22
- 3. York – Yellow
23
- Hex: #FFFF00
24
- 4. Gave – Green
25
- Hex: #008000
26
- 5. Battle – Blue
27
- Hex: #0000FF
28
- 6. In – Indigo
29
- Hex: #4B0082
30
- 7. Vain – Violet
31
- Hex: #EE82EE
32
- */
33
- const colors = [
34
- 0xff0000, 0xffa500, 0xffff00, 0x008000, 0x0000ff, 0x4b0082, 0xee82ee,
35
- ];
36
- const black = 0x000000;
37
- class Colors extends Struct({
38
- Richard: Field,
39
- Of: Field,
40
- York: Field,
41
- Gave: Field,
42
- Battle: Field,
43
- In: Field,
44
- Vain: Field,
45
- }) {
46
- }
47
- const rightAnswers = new Colors({
48
- Richard: Field(colors[0]),
49
- Of: Field(colors[1]),
50
- York: Field(colors[2]),
51
- Gave: Field(colors[3]),
52
- Battle: Field(colors[4]),
53
- In: Field(colors[5]),
54
- Vain: Field(colors[6]),
55
- });
56
- class ColorGame extends SmartContract {
57
- constructor() {
58
- super(...arguments);
59
- this.score = State(Field(0));
60
- this.color = State(Field(black));
61
- this.user = State(PublicKey.empty());
62
- this.maxScore = State(Field(0));
63
- }
64
- async play(answers) {
65
- const Richard = answers.Richard.equals(rightAnswers.Richard);
66
- const Of = answers.Of.equals(rightAnswers.Of);
67
- const York = answers.York.equals(rightAnswers.York);
68
- const Gave = answers.Gave.equals(rightAnswers.Gave);
69
- const Battle = answers.Battle.equals(rightAnswers.Battle);
70
- const In = answers.In.equals(rightAnswers.In);
71
- const Vain = answers.Vain.equals(rightAnswers.Vain);
72
- const isCorrectArray = [Richard, Of, York, Gave, Battle, In, Vain];
73
- let score = Field(0);
74
- for (let i = 0; i < 7; i++) {
75
- score = score.add(Provable.if(isCorrectArray[i], Field(1), Field(0)));
76
- }
77
- this.score.set(score);
78
- const maxScore = this.maxScore.getAndRequireEquals();
79
- maxScore
80
- .equals(Field(7))
81
- .assertFalse("Game is over, the winner is already known");
82
- this.maxScore.set(Provable.if(score.greaterThan(maxScore), score, maxScore));
83
- const color = Provable.if(Vain, rightAnswers.Vain, Provable.if(In, rightAnswers.In, Provable.if(Battle, rightAnswers.Battle, Provable.if(Gave, rightAnswers.Gave, Provable.if(York, rightAnswers.York, Provable.if(Of, rightAnswers.Of, Provable.if(Richard, rightAnswers.Richard, Field(black))))))));
84
- this.color.set(color);
85
- const sender = this.sender.getAndRequireSignature();
86
- this.user.set(sender);
87
- }
88
- async canUpdate(collectionAddress, nftAddress, input, output) {
89
- const user = this.user.getAndRequireEquals();
90
- const score = this.score.getAndRequireEquals();
91
- const color = this.color.getAndRequireEquals();
92
- input.context.custom[0].assertEquals(score);
93
- input.context.custom[1].assertEquals(color);
94
- input.owner
95
- .equals(user)
96
- .or(score.equals(Field(7)))
97
- .assertTrue("Only the winner can change the NFT owner");
98
- output.owner.assertEquals(user);
99
- return Bool(true);
100
- }
101
- }
102
- __decorate([
103
- state(Field),
104
- __metadata("design:type", Object)
105
- ], ColorGame.prototype, "score", void 0);
106
- __decorate([
107
- state(Field),
108
- __metadata("design:type", Object)
109
- ], ColorGame.prototype, "color", void 0);
110
- __decorate([
111
- state(PublicKey),
112
- __metadata("design:type", Object)
113
- ], ColorGame.prototype, "user", void 0);
114
- __decorate([
115
- state(Field),
116
- __metadata("design:type", Object)
117
- ], ColorGame.prototype, "maxScore", void 0);
118
- __decorate([
119
- method,
120
- __metadata("design:type", Function),
121
- __metadata("design:paramtypes", [Colors]),
122
- __metadata("design:returntype", Promise)
123
- ], ColorGame.prototype, "play", null);
124
- __decorate([
125
- method.returns(Bool),
126
- __metadata("design:type", Function),
127
- __metadata("design:paramtypes", [PublicKey,
128
- PublicKey,
129
- NFTState,
130
- NFTState]),
131
- __metadata("design:returntype", Promise)
132
- ], ColorGame.prototype, "canUpdate", null);
133
- let nftContractVk;
134
- let nftProgramVk;
135
- let collectionVk;
136
- let adminVk;
137
- const cache = Cache.FileSystem("./cache");
138
- const zkNFTKey = TestPublicKey.random();
139
- const zkCollectionKey = TestPublicKey.random();
140
- const zkAdminKey = TestPublicKey.random();
141
- const zkColorGameKey = TestPublicKey.random();
142
- const { Collection } = NonFungibleTokenContractsFactory({
143
- adminContract: NFTAdmin,
144
- updateFactory: () => ColorGame,
145
- });
146
- const collectionContract = new Collection(zkCollectionKey);
147
- const tokenId = collectionContract.deriveTokenId();
148
- const adminContract = new NFTAdmin(zkAdminKey);
149
- const colorGameContract = new ColorGame(zkColorGameKey);
150
- const NUMBER_OF_USERS = 6;
151
- let admin;
152
- let users = [];
153
- let creator;
154
- let owner;
155
- const nftParams = [];
156
- describe(`NFT ZkProgram tests: ${chain} ${readOnly ? "read-only " : ""}${noLog ? "noLog" : ""} `, () => {
157
- const originalConsoleLog = console.log;
158
- if (noLog) {
159
- beforeEach(() => {
160
- console.log = () => { };
161
- });
162
- afterEach(() => {
163
- console.log = originalConsoleLog;
164
- });
165
- }
166
- it("should initialize a blockchain", async () => {
167
- if (chain === "devnet" || chain === "zeko" || chain === "mainnet") {
168
- await initBlockchain(chain);
169
- admin = TestPublicKey.fromBase58(TEST_ACCOUNTS[0].privateKey);
170
- users = TEST_ACCOUNTS.slice(1).map((account) => TestPublicKey.fromBase58(account.privateKey));
171
- }
172
- else if (chain === "local") {
173
- const { keys } = await initBlockchain(chain, NUMBER_OF_USERS + 2);
174
- admin = TestPublicKey(keys[1].key);
175
- users = keys.slice(2);
176
- }
177
- else if (chain === "lightnet") {
178
- const { keys } = await initBlockchain(chain, NUMBER_OF_USERS + 2);
179
- admin = TestPublicKey(keys[1].key);
180
- users = keys.slice(2);
181
- }
182
- creator = users[0];
183
- owner = creator;
184
- assert(users.length >= NUMBER_OF_USERS);
185
- console.log("chain:", chain);
186
- console.log("networkId:", Mina.getNetworkId());
187
- console.log("Collection contract address:", zkCollectionKey.toBase58());
188
- console.log("Admin contract address:", zkAdminKey.toBase58());
189
- console.log("NFT contract address:", zkNFTKey.toBase58());
190
- console.log("Color Game contract address:", zkColorGameKey.toBase58());
191
- console.log("Creator", creator.toBase58(), "balance:", await accountBalanceMina(creator));
192
- console.log("Admin ", admin.toBase58(), "balance:", await accountBalanceMina(admin));
193
- for (let i = 0; i < NUMBER_OF_USERS; i++) {
194
- console.log(`User ${i} `, users[i].toBase58(), "balance:", await accountBalanceMina(users[i]));
195
- }
196
- Memory.info("before compiling");
197
- });
198
- it("should compile NFT Contract", async () => {
199
- console.log("compiling...");
200
- console.time("compiled NFTContract");
201
- const { verificationKey } = await NFT.compile({ cache });
202
- nftContractVk = verificationKey;
203
- console.timeEnd("compiled NFTContract");
204
- assert.strictEqual(nftContractVk.hash.toJSON(), vk.NFT.hash);
205
- assert.strictEqual(nftContractVk.data, vk.NFT.data);
206
- });
207
- it("should compile Color Game", async () => {
208
- console.log("compiling...");
209
- console.time("compiled Color Game");
210
- await ColorGame.compile({ cache });
211
- console.timeEnd("compiled Color Game");
212
- });
213
- it("should compile Admin", async () => {
214
- console.time("compiled Admin");
215
- const { verificationKey } = await NFTAdmin.compile({ cache });
216
- adminVk = verificationKey;
217
- console.timeEnd("compiled Admin");
218
- console.log("Admin vk hash:", adminVk.hash.toJSON());
219
- });
220
- it("should compile Collection", async () => {
221
- console.time("compiled Collection");
222
- const { verificationKey } = await Collection.compile({ cache });
223
- collectionVk = verificationKey;
224
- console.timeEnd("compiled Collection");
225
- console.log("Collection vk hash:", collectionVk.hash.toJSON());
226
- });
227
- it("should compile nft ZkProgram", async () => {
228
- console.time("compiled NFTProgram");
229
- nftProgramVk = (await NFTGameProgram.compile({ cache })).verificationKey;
230
- console.timeEnd("compiled NFTProgram");
231
- console.log("NFTProgram vk hash:", nftProgramVk.hash.toJSON());
232
- });
233
- it("should deploy a Collection", async () => {
234
- console.time("deployed Collection");
235
- const { metadataRoot, ipfsHash, serializedMap, name, privateMetadata } = await randomMetadata({
236
- includePrivateTraits: false,
237
- includeBanner: true,
238
- });
239
- if (!ipfsHash) {
240
- throw new Error("IPFS hash is undefined");
241
- }
242
- const slot = chain === "local"
243
- ? Mina.currentSlot()
244
- : chain === "zeko"
245
- ? UInt32.zero
246
- : (await fetchLastBlock()).globalSlotSinceGenesis;
247
- const expiry = slot.add(UInt32.from(100000));
248
- const masterNFT = new MintParams({
249
- name: fieldFromString(name),
250
- address: zkCollectionKey,
251
- tokenId,
252
- data: NFTData.new({
253
- owner: creator,
254
- }),
255
- fee: UInt64.zero,
256
- metadata: metadataRoot,
257
- storage: Storage.fromString(ipfsHash),
258
- metadataVerificationKeyHash: Field(0),
259
- expiry,
260
- });
261
- await fetchMinaAccount({ publicKey: creator, force: true });
262
- const tx = await Mina.transaction({
263
- sender: creator,
264
- fee: 100_000_000,
265
- memo: `Deploy Collection ${name}`.substring(0, 30),
266
- }, async () => {
267
- AccountUpdate.fundNewAccount(creator, 3);
268
- await adminContract.deploy({
269
- admin: creator,
270
- uri: `AdminContract`,
271
- });
272
- // deploy() and initialize() create 2 account updates for the same publicKey, it is intended
273
- await collectionContract.deploy({
274
- creator,
275
- collectionName: fieldFromString(name),
276
- baseURL: fieldFromString("ipfs"),
277
- admin: zkAdminKey,
278
- symbol: "NFT",
279
- url: `https://${chain}.minanft.io`,
280
- });
281
- await collectionContract.initialize(masterNFT, CollectionData.new({
282
- requireTransferApproval: false,
283
- royaltyFee: 10, // 10%
284
- transferFee: 1_000_000_000, // 1 MINA
285
- }));
286
- });
287
- await tx.prove();
288
- assert.strictEqual((await sendTx({
289
- tx: tx.sign([creator.key, zkCollectionKey.key, zkAdminKey.key]),
290
- description: "deploy Collection",
291
- }))?.status, expectedTxStatus);
292
- console.timeEnd("deployed Collection");
293
- });
294
- it("should mint NFT", async () => {
295
- Memory.info("before mint");
296
- console.time("minted NFT");
297
- const { name, metadata } = await randomMetadata({
298
- includePrivateTraits: false,
299
- pin: false,
300
- });
301
- // add color game contract address to metadata to be checked by the Zkprogram
302
- metadata.addTrait({
303
- key: "contractX",
304
- type: "field",
305
- value: zkColorGameKey.x,
306
- });
307
- metadata.addTrait({
308
- key: "contractIsOdd",
309
- type: "field",
310
- value: zkColorGameKey.isOdd.toField(),
311
- });
312
- const contractX = metadata.map.get(fieldFromString("contractX"));
313
- const isOdd = metadata.map.get(fieldFromString("contractIsOdd"));
314
- assert.strictEqual(MetadataValue.new({ value: zkColorGameKey.x, type: "field" })
315
- .hash()
316
- .equals(contractX)
317
- .toBoolean(), true);
318
- assert.strictEqual(MetadataValue.new({
319
- value: zkColorGameKey.isOdd.toField(),
320
- type: "field",
321
- })
322
- .hash()
323
- .equals(isOdd)
324
- .toBoolean(), true);
325
- const ipfsHash = await pinJSON({
326
- data: metadata.toJSON(true),
327
- name: "metadata",
328
- });
329
- if (!ipfsHash)
330
- throw new Error("Failed to pin metadata");
331
- nftParams.push({
332
- name,
333
- address: zkNFTKey,
334
- collection: zkCollectionKey,
335
- });
336
- await fetchMinaAccount({ publicKey: creator, force: true });
337
- await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
338
- await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
339
- owner = users[1];
340
- const slot = chain === "local"
341
- ? Mina.currentSlot()
342
- : chain === "zeko"
343
- ? UInt32.zero
344
- : (await fetchLastBlock()).globalSlotSinceGenesis;
345
- const expiry = slot.add(UInt32.from(100000));
346
- const tx = await Mina.transaction({
347
- sender: creator,
348
- fee: 100_000_000,
349
- memo: `Mint NFT ${name}`.substring(0, 30),
350
- }, async () => {
351
- await collectionContract.mintByCreator({
352
- name: fieldFromString(name),
353
- address: zkNFTKey,
354
- tokenId,
355
- metadata: metadata.map.root,
356
- data: NFTData.new({
357
- owner,
358
- canChangeMetadata: !readOnly,
359
- canChangeStorage: !readOnly,
360
- canPause: true,
361
- canChangeName: false,
362
- canChangeOwnerByProof: !readOnly,
363
- canTransfer: !readOnly,
364
- }),
365
- metadataVerificationKeyHash: nftProgramVk.hash,
366
- expiry,
367
- fee: UInt64.from(10_000_000_000),
368
- storage: Storage.fromString(ipfsHash),
369
- });
370
- AccountUpdate.fundNewAccount(creator, 1);
371
- await colorGameContract.deploy({});
372
- });
373
- await tx.prove();
374
- assert.strictEqual((await sendTx({
375
- tx: tx.sign([creator.key, zkNFTKey.key, zkColorGameKey.key]),
376
- description: "mint",
377
- }))?.status, expectedTxStatus);
378
- await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
379
- const nft = new NFT(zkNFTKey, tokenId);
380
- const dataCheck = NFTData.unpack(nft.packedData.get());
381
- console.log("owner", owner.toBase58());
382
- console.log("ownerCheck", dataCheck.owner.toBase58());
383
- console.log("approvalCheck", dataCheck.approved.toBase58());
384
- assert.strictEqual(dataCheck.owner.equals(owner).toBoolean(), true);
385
- assert.strictEqual(dataCheck.approved.equals(PublicKey.empty()).toBoolean(), true);
386
- console.timeEnd("minted NFT");
387
- });
388
- it("should play game", async () => {
389
- Memory.info("before play");
390
- console.time("played game");
391
- const player = owner;
392
- await fetchMinaAccount({ publicKey: player, force: true });
393
- await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
394
- await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
395
- await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
396
- await fetchMinaAccount({ publicKey: zkColorGameKey, force: true });
397
- const answers = new Colors({
398
- Richard: Field(colors[0]),
399
- Of: Field(75843),
400
- York: Field(colors[2]),
401
- Gave: Field(colors[3]),
402
- Battle: Field(65943),
403
- In: Field(colors[5]),
404
- Vain: Field(67483),
405
- });
406
- const tx = await Mina.transaction({
407
- sender: player,
408
- fee: 100_000_000,
409
- memo: `Play game`.substring(0, 30),
410
- }, async () => {
411
- await colorGameContract.play(answers);
412
- });
413
- await tx.prove();
414
- assert.strictEqual((await sendTx({
415
- tx: tx.sign([player.key]),
416
- description: "play",
417
- }))?.status, expectedTxStatus);
418
- console.timeEnd("played game");
419
- await fetchMinaAccount({ publicKey: zkColorGameKey, force: true });
420
- const score = colorGameContract.score.get();
421
- const color = colorGameContract.color.get();
422
- const user = colorGameContract.user.get();
423
- console.log("score:", score.toJSON());
424
- console.log("color:", "#" + color.toBigInt().toString(16).toUpperCase());
425
- console.log("user", user.toBase58());
426
- assert.strictEqual(user.equals(player).toBoolean(), true);
427
- assert.strictEqual(score.equals(Field(4)).toBoolean(), true);
428
- });
429
- it("should update NFT metadata", async () => {
430
- Memory.info("before update");
431
- console.time("updated NFT");
432
- await fetchMinaAccount({ publicKey: owner, force: true });
433
- await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
434
- await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
435
- await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
436
- await fetchMinaAccount({ publicKey: zkColorGameKey, force: true });
437
- const score = colorGameContract.score.get();
438
- const color = colorGameContract.color.get();
439
- const user = colorGameContract.user.get();
440
- assert.strictEqual(user.equals(owner).toBoolean(), true);
441
- assert.strictEqual(score.equals(Field(4)).toBoolean(), true);
442
- assert.strictEqual(color.equals(Field(colors[5])).toBoolean(), true);
443
- const nftAccount = Mina.getAccount(zkNFTKey, tokenId);
444
- const nftContract = new NFT(zkNFTKey, tokenId);
445
- const nftStateStruct = NFTStateStruct.fromAccount(nftAccount);
446
- assert.strictEqual(nftAccount.zkapp?.verificationKey?.hash.toJSON(), nftContractVk.hash.toJSON());
447
- const nftState = NFTState.fromNFTState({
448
- nftState: nftStateStruct,
449
- creator: creator,
450
- address: zkNFTKey,
451
- tokenId,
452
- oracleAddress: zkColorGameKey,
453
- context: new NFTTransactionContext({
454
- custom: [score, color, Field(0)],
455
- }),
456
- });
457
- const index = nftParams.findIndex((p) => p.address.equals(zkNFTKey).toBoolean() &&
458
- p.collection.equals(zkCollectionKey).toBoolean());
459
- if (index === -1) {
460
- throw new Error("NFT not found");
461
- }
462
- const nft = nftParams[index];
463
- const { name } = nft;
464
- const fetchResult = await fetch(createIpfsURL({ hash: nftContract.storage.get().toString() }));
465
- if (!fetchResult.ok) {
466
- throw new Error("Failed to fetch metadata");
467
- }
468
- const json = await fetchResult.json();
469
- if (!json) {
470
- throw new Error("Failed to fetch metadata");
471
- }
472
- const metadata = Metadata.fromJSON({
473
- json,
474
- checkRoot: true,
475
- });
476
- assert.strictEqual(nftState.metadata.toJSON(), metadata.map.root.toJSON());
477
- if (nftState.metadata.toJSON() !== metadata.map.root.toJSON()) {
478
- throw new Error("NFT metadata is not the same as the one in the collection");
479
- }
480
- const map = metadata.map.clone(); // we need to pass original metadata to the zkprogram
481
- metadata.addTrait({
482
- key: "color",
483
- type: "field",
484
- value: color,
485
- });
486
- metadata.addTrait({
487
- key: "score",
488
- type: "field",
489
- value: score,
490
- });
491
- const ipfsHash = await pinJSON({
492
- data: metadata.toJSON(true),
493
- name: "metadata",
494
- });
495
- if (!ipfsHash)
496
- throw new Error("Failed to pin new metadata");
497
- console.time("proved update");
498
- const update = await NFTGameProgram.updateMetadataAndOwner(nftState, map, zkColorGameKey, score, color, Storage.fromString(ipfsHash), owner);
499
- const dynamicProof = NFTUpdateProof.fromProof(update.proof);
500
- console.timeEnd("proved update");
501
- let success = true;
502
- try {
503
- const tx = await Mina.transaction({
504
- sender: users[2],
505
- fee: 100_000_000,
506
- memo: `Update NFT ${name}`.substring(0, 30),
507
- }, async () => {
508
- await collectionContract.updateWithOracle(dynamicProof, nftProgramVk);
509
- });
510
- await tx.prove();
511
- const txSigned = tx.sign([users[2].key]);
512
- assert.strictEqual((await sendTx({
513
- tx: txSigned,
514
- description: "update",
515
- }))?.status, expectedTxStatus);
516
- await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
517
- const nftCheck = new NFT(zkNFTKey, tokenId);
518
- const storageCheck = nftCheck.storage.get().toString();
519
- assert.strictEqual(storageCheck, ipfsHash);
520
- const metadataCheck = nftCheck.metadata.get();
521
- assert.strictEqual(metadataCheck.toJSON(), metadata.map.root.toJSON());
522
- }
523
- catch (error) {
524
- console.log("Failed to update read-only NFT:", error?.message ?? "");
525
- success = false;
526
- }
527
- assert.strictEqual(success, !readOnly);
528
- console.timeEnd("updated NFT");
529
- });
530
- it("should win game", { skip: readOnly }, async () => {
531
- Memory.info("before win");
532
- console.time("win game");
533
- const player = users[3];
534
- await fetchMinaAccount({ publicKey: player, force: true });
535
- await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
536
- await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
537
- await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
538
- await fetchMinaAccount({ publicKey: zkColorGameKey, force: true });
539
- const answers = new Colors({
540
- Richard: Field(colors[0]),
541
- Of: Field(colors[1]),
542
- York: Field(colors[2]),
543
- Gave: Field(colors[3]),
544
- Battle: Field(colors[4]),
545
- In: Field(colors[5]),
546
- Vain: Field(colors[6]),
547
- });
548
- const tx = await Mina.transaction({
549
- sender: player,
550
- fee: 100_000_000,
551
- memo: `Win game`.substring(0, 30),
552
- }, async () => {
553
- await colorGameContract.play(answers);
554
- });
555
- await tx.prove();
556
- assert.strictEqual((await sendTx({
557
- tx: tx.sign([player.key]),
558
- description: "win game",
559
- }))?.status, expectedTxStatus);
560
- console.timeEnd("win game");
561
- await fetchMinaAccount({ publicKey: zkColorGameKey, force: true });
562
- const score = colorGameContract.score.get();
563
- const color = colorGameContract.color.get();
564
- const user = colorGameContract.user.get();
565
- console.log("score:", score.toJSON());
566
- console.log("color:", "#" + color.toBigInt().toString(16).toUpperCase());
567
- console.log("user", user.toBase58());
568
- assert.strictEqual(user.equals(player).toBoolean(), true);
569
- assert.strictEqual(score.equals(Field(7)).toBoolean(), true);
570
- });
571
- it("should update NFT owner to the game winner", {
572
- skip: readOnly,
573
- }, async () => {
574
- Memory.info("before update");
575
- console.time("updated NFT");
576
- const winner = users[3];
577
- await fetchMinaAccount({ publicKey: winner, force: true });
578
- await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
579
- await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
580
- await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
581
- await fetchMinaAccount({ publicKey: zkColorGameKey, force: true });
582
- const score = colorGameContract.score.get();
583
- const color = colorGameContract.color.get();
584
- const user = colorGameContract.user.get();
585
- assert.strictEqual(user.equals(winner).toBoolean(), true);
586
- assert.strictEqual(score.equals(Field(7)).toBoolean(), true);
587
- assert.strictEqual(color.equals(Field(colors[6])).toBoolean(), true);
588
- const nftAccount = Mina.getAccount(zkNFTKey, tokenId);
589
- const nftContract = new NFT(zkNFTKey, tokenId);
590
- const nftStateStruct = NFTStateStruct.fromAccount(nftAccount);
591
- assert.strictEqual(nftAccount.zkapp?.verificationKey?.hash.toJSON(), nftContractVk.hash.toJSON());
592
- const nftState = NFTState.fromNFTState({
593
- nftState: nftStateStruct,
594
- creator: creator,
595
- address: zkNFTKey,
596
- tokenId,
597
- oracleAddress: zkColorGameKey,
598
- context: new NFTTransactionContext({
599
- custom: [score, color, Field(0)],
600
- }),
601
- });
602
- const index = nftParams.findIndex((p) => p.address.equals(zkNFTKey).toBoolean() &&
603
- p.collection.equals(zkCollectionKey).toBoolean());
604
- if (index === -1) {
605
- throw new Error("NFT not found");
606
- }
607
- const nft = nftParams[index];
608
- const { name } = nft;
609
- const fetchResult = await fetch(createIpfsURL({ hash: nftContract.storage.get().toString() }));
610
- if (!fetchResult.ok) {
611
- throw new Error("Failed to fetch metadata");
612
- }
613
- const json = await fetchResult.json();
614
- if (!json) {
615
- throw new Error("Failed to fetch metadata");
616
- }
617
- const metadata = Metadata.fromJSON({
618
- json,
619
- checkRoot: true,
620
- });
621
- assert.strictEqual(nftState.metadata.toJSON(), metadata.map.root.toJSON());
622
- if (nftState.metadata.toJSON() !== metadata.map.root.toJSON()) {
623
- throw new Error("NFT metadata is not the same as the one in the collection");
624
- }
625
- const map = metadata.map.clone(); // we need to pass original metadata to the zkprogram
626
- metadata.addTrait({
627
- key: "color",
628
- type: "field",
629
- value: color,
630
- });
631
- metadata.addTrait({
632
- key: "score",
633
- type: "field",
634
- value: score,
635
- });
636
- const ipfsHash = await pinJSON({
637
- data: metadata.toJSON(true),
638
- name: "metadata",
639
- });
640
- if (!ipfsHash)
641
- throw new Error("Failed to pin new metadata");
642
- console.time("proved update");
643
- const update = await NFTGameProgram.updateMetadataAndOwner(nftState, map, zkColorGameKey, score, color, Storage.fromString(ipfsHash), winner);
644
- const dynamicProof = NFTUpdateProof.fromProof(update.proof);
645
- console.timeEnd("proved update");
646
- let success = true;
647
- try {
648
- const tx = await Mina.transaction({
649
- sender: winner,
650
- fee: 100_000_000,
651
- memo: `Change owner to the game winner for NFT ${name}`.substring(0, 30),
652
- }, async () => {
653
- await collectionContract.updateWithOracle(dynamicProof, nftProgramVk);
654
- });
655
- await tx.prove();
656
- const txSigned = tx.sign([winner.key]);
657
- assert.strictEqual((await sendTx({
658
- tx: txSigned,
659
- description: "change owner to the game winner",
660
- }))?.status, expectedTxStatus);
661
- await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
662
- const nftCheck = new NFT(zkNFTKey, tokenId);
663
- const storageCheck = nftCheck.storage.get().toString();
664
- const ownerCheck = NFTData.unpack(nftCheck.packedData.get()).owner;
665
- const metadataCheck = nftCheck.metadata.get();
666
- assert.strictEqual(storageCheck, ipfsHash);
667
- assert.strictEqual(metadataCheck.toJSON(), metadata.map.root.toJSON());
668
- assert.strictEqual(ownerCheck.equals(winner).toBoolean(), true);
669
- owner = winner;
670
- }
671
- catch (error) {
672
- console.log("Failed to update read-only NFT:", error?.message ?? "");
673
- success = false;
674
- }
675
- assert.strictEqual(success, !readOnly);
676
- console.timeEnd("updated NFT");
677
- });
678
- it("should fail to transfer soulbound NFT", { skip: !readOnly }, async () => {
679
- Memory.info("before transfer");
680
- await fetchMinaAccount({ publicKey: owner, force: true });
681
- await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
682
- await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
683
- await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
684
- const requireTransferApproval = CollectionData.unpack(collectionContract.packedData.get()).requireTransferApproval.toBoolean();
685
- console.log("requireTransferApproval", requireTransferApproval);
686
- const to = users[2];
687
- const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
688
- p.collection.equals(zkCollectionKey).toBoolean());
689
- if (!nft) {
690
- throw new Error("NFT not found");
691
- }
692
- const { name } = nft;
693
- let success = true;
694
- try {
695
- const tx = await Mina.transaction({
696
- sender: owner,
697
- fee: 100_000_000,
698
- memo: `Transfer NFT ${name}`.substring(0, 30),
699
- }, async () => {
700
- if (requireTransferApproval) {
701
- await collectionContract.approvedTransferBySignature(new TransferParams({
702
- address: zkNFTKey,
703
- from: owner,
704
- to,
705
- price: UInt64Option.none(),
706
- context: NFTTransactionContext.empty(),
707
- }));
708
- }
709
- else {
710
- await collectionContract.transferBySignature(new TransferParams({
711
- address: zkNFTKey,
712
- from: owner,
713
- to,
714
- price: UInt64Option.none(),
715
- context: NFTTransactionContext.empty(),
716
- }));
717
- }
718
- });
719
- await tx.prove();
720
- }
721
- catch (e) {
722
- console.log("Failed to transfer soulbound NFT:", e?.message ?? "");
723
- success = false;
724
- }
725
- assert.strictEqual(success, false);
726
- });
727
- });
728
- //# sourceMappingURL=zkprogram.test.js.map