@silvana-one/nft 0.1.30 → 0.2.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 (197) hide show
  1. package/dist/node/index.cjs +57 -1
  2. package/dist/node/marketplace/bb.d.ts +18 -0
  3. package/dist/node/marketplace/bb.js +58 -0
  4. package/dist/node/marketplace/bb.js.map +1 -1
  5. package/dist/tsconfig.node.tsbuildinfo +1 -0
  6. package/dist/web/src/admin/advanced.js.map +1 -0
  7. package/dist/web/src/admin/index.js.map +1 -0
  8. package/dist/web/src/contracts/admin.js.map +1 -0
  9. package/dist/web/src/contracts/collection.js.map +1 -0
  10. package/dist/web/src/contracts/index.js.map +1 -0
  11. package/dist/web/src/contracts/nft.js.map +1 -0
  12. package/dist/web/src/contracts.js.map +1 -0
  13. package/dist/web/src/index.js.map +1 -0
  14. package/dist/web/{interfaces → src/interfaces}/admin.js.map +1 -1
  15. package/dist/web/src/interfaces/approval.js.map +1 -0
  16. package/dist/web/src/interfaces/collection.js.map +1 -0
  17. package/dist/web/src/interfaces/encoding.js.map +1 -0
  18. package/dist/web/src/interfaces/events.js.map +1 -0
  19. package/dist/web/src/interfaces/index.js.map +1 -0
  20. package/dist/web/src/interfaces/ownable.js.map +1 -0
  21. package/dist/web/src/interfaces/owner.js.map +1 -0
  22. package/dist/web/src/interfaces/pausable.js.map +1 -0
  23. package/dist/web/src/interfaces/types.js.map +1 -0
  24. package/dist/web/src/interfaces/update.js.map +1 -0
  25. package/dist/web/src/marketplace/auction.js.map +1 -0
  26. package/dist/web/{marketplace → src/marketplace}/bb.d.ts +18 -0
  27. package/dist/web/{marketplace → src/marketplace}/bb.js +58 -0
  28. package/dist/web/src/marketplace/bb.js.map +1 -0
  29. package/dist/web/src/marketplace/bid.js.map +1 -0
  30. package/dist/web/src/marketplace/index.js.map +1 -0
  31. package/dist/web/src/marketplace/nft-shares.js.map +1 -0
  32. package/dist/web/src/marketplace/offer.js.map +1 -0
  33. package/dist/web/src/marketplace/types.js.map +1 -0
  34. package/dist/web/src/metadata/address.js.map +1 -0
  35. package/dist/web/src/metadata/index.js.map +1 -0
  36. package/dist/web/src/metadata/metadata.js.map +1 -0
  37. package/dist/web/src/metadata/pin.js.map +1 -0
  38. package/dist/web/src/metadata/text.js.map +1 -0
  39. package/dist/web/src/metadata/tree.js.map +1 -0
  40. package/dist/web/src/util/div.js.map +1 -0
  41. package/dist/web/src/util/index.js.map +1 -0
  42. package/dist/web/src/vk.js.map +1 -0
  43. package/dist/web/src/zkprogram-example/game.js.map +1 -0
  44. package/dist/web/src/zkprogram-example/index.js.map +1 -0
  45. package/dist/web/src/zkprogram-example/update.js.map +1 -0
  46. package/dist/web/test/auction.test.d.ts +1212 -0
  47. package/dist/web/test/auction.test.js +1248 -0
  48. package/dist/web/test/auction.test.js.map +1 -0
  49. package/dist/web/test/bb.test.d.ts +1 -0
  50. package/dist/web/test/bb.test.js +159 -0
  51. package/dist/web/test/bb.test.js.map +1 -0
  52. package/dist/web/test/contract.test.d.ts +1 -0
  53. package/dist/web/test/contract.test.js +1333 -0
  54. package/dist/web/test/contract.test.js.map +1 -0
  55. package/dist/web/test/div.test.d.ts +1 -0
  56. package/dist/web/test/div.test.js +55 -0
  57. package/dist/web/test/div.test.js.map +1 -0
  58. package/dist/web/test/helpers/config.d.ts +4 -0
  59. package/dist/web/test/helpers/config.js +103 -0
  60. package/dist/web/test/helpers/config.js.map +1 -0
  61. package/dist/web/test/helpers/metadata.d.ts +30 -0
  62. package/dist/web/test/helpers/metadata.js +155 -0
  63. package/dist/web/test/helpers/metadata.js.map +1 -0
  64. package/dist/web/test/helpers/utils.d.ts +16 -0
  65. package/dist/web/test/helpers/utils.js +36 -0
  66. package/dist/web/test/helpers/utils.js.map +1 -0
  67. package/dist/web/test/helpers/validators.d.ts +15 -0
  68. package/dist/web/test/helpers/validators.js +46 -0
  69. package/dist/web/test/helpers/validators.js.map +1 -0
  70. package/dist/web/test/metadata.test.d.ts +1 -0
  71. package/dist/web/test/metadata.test.js +66 -0
  72. package/dist/web/test/metadata.test.js.map +1 -0
  73. package/dist/web/test/mint.test.d.ts +1 -0
  74. package/dist/web/test/mint.test.js +262 -0
  75. package/dist/web/test/mint.test.js.map +1 -0
  76. package/dist/web/test/pack.test.d.ts +1 -0
  77. package/dist/web/test/pack.test.js +141 -0
  78. package/dist/web/test/pack.test.js.map +1 -0
  79. package/dist/web/test/zkprogram.test.d.ts +1 -0
  80. package/dist/web/test/zkprogram.test.js +728 -0
  81. package/dist/web/test/zkprogram.test.js.map +1 -0
  82. package/dist/web/tsconfig.web.tsbuildinfo +1 -0
  83. package/package.json +88 -14
  84. package/src/marketplace/bb.ts +51 -0
  85. package/dist/tsconfig.tsbuildinfo +0 -1
  86. package/dist/tsconfig.web.tsbuildinfo +0 -1
  87. package/dist/web/admin/advanced.js.map +0 -1
  88. package/dist/web/admin/index.js.map +0 -1
  89. package/dist/web/contracts/admin.js.map +0 -1
  90. package/dist/web/contracts/collection.js.map +0 -1
  91. package/dist/web/contracts/index.js.map +0 -1
  92. package/dist/web/contracts/nft.js.map +0 -1
  93. package/dist/web/contracts.js.map +0 -1
  94. package/dist/web/index.js.map +0 -1
  95. package/dist/web/interfaces/approval.js.map +0 -1
  96. package/dist/web/interfaces/collection.js.map +0 -1
  97. package/dist/web/interfaces/encoding.js.map +0 -1
  98. package/dist/web/interfaces/events.js.map +0 -1
  99. package/dist/web/interfaces/index.js.map +0 -1
  100. package/dist/web/interfaces/ownable.js.map +0 -1
  101. package/dist/web/interfaces/owner.js.map +0 -1
  102. package/dist/web/interfaces/pausable.js.map +0 -1
  103. package/dist/web/interfaces/types.js.map +0 -1
  104. package/dist/web/interfaces/update.js.map +0 -1
  105. package/dist/web/marketplace/auction.js.map +0 -1
  106. package/dist/web/marketplace/bb.js.map +0 -1
  107. package/dist/web/marketplace/bid.js.map +0 -1
  108. package/dist/web/marketplace/index.js.map +0 -1
  109. package/dist/web/marketplace/nft-shares.js.map +0 -1
  110. package/dist/web/marketplace/offer.js.map +0 -1
  111. package/dist/web/marketplace/types.js.map +0 -1
  112. package/dist/web/metadata/address.js.map +0 -1
  113. package/dist/web/metadata/index.js.map +0 -1
  114. package/dist/web/metadata/metadata.js.map +0 -1
  115. package/dist/web/metadata/pin.js.map +0 -1
  116. package/dist/web/metadata/text.js.map +0 -1
  117. package/dist/web/metadata/tree.js.map +0 -1
  118. package/dist/web/util/div.js.map +0 -1
  119. package/dist/web/util/index.js.map +0 -1
  120. package/dist/web/vk.js.map +0 -1
  121. package/dist/web/zkprogram-example/game.js.map +0 -1
  122. package/dist/web/zkprogram-example/index.js.map +0 -1
  123. package/dist/web/zkprogram-example/update.js.map +0 -1
  124. /package/dist/web/{admin → src/admin}/advanced.d.ts +0 -0
  125. /package/dist/web/{admin → src/admin}/advanced.js +0 -0
  126. /package/dist/web/{admin → src/admin}/index.d.ts +0 -0
  127. /package/dist/web/{admin → src/admin}/index.js +0 -0
  128. /package/dist/web/{contracts → src/contracts}/admin.d.ts +0 -0
  129. /package/dist/web/{contracts → src/contracts}/admin.js +0 -0
  130. /package/dist/web/{contracts → src/contracts}/collection.d.ts +0 -0
  131. /package/dist/web/{contracts → src/contracts}/collection.js +0 -0
  132. /package/dist/web/{contracts → src/contracts}/index.d.ts +0 -0
  133. /package/dist/web/{contracts → src/contracts}/index.js +0 -0
  134. /package/dist/web/{contracts → src/contracts}/nft.d.ts +0 -0
  135. /package/dist/web/{contracts → src/contracts}/nft.js +0 -0
  136. /package/dist/web/{contracts.d.ts → src/contracts.d.ts} +0 -0
  137. /package/dist/web/{contracts.js → src/contracts.js} +0 -0
  138. /package/dist/web/{index.d.ts → src/index.d.ts} +0 -0
  139. /package/dist/web/{index.js → src/index.js} +0 -0
  140. /package/dist/web/{interfaces → src/interfaces}/admin.d.ts +0 -0
  141. /package/dist/web/{interfaces → src/interfaces}/admin.js +0 -0
  142. /package/dist/web/{interfaces → src/interfaces}/approval.d.ts +0 -0
  143. /package/dist/web/{interfaces → src/interfaces}/approval.js +0 -0
  144. /package/dist/web/{interfaces → src/interfaces}/collection.d.ts +0 -0
  145. /package/dist/web/{interfaces → src/interfaces}/collection.js +0 -0
  146. /package/dist/web/{interfaces → src/interfaces}/encoding.d.ts +0 -0
  147. /package/dist/web/{interfaces → src/interfaces}/encoding.js +0 -0
  148. /package/dist/web/{interfaces → src/interfaces}/events.d.ts +0 -0
  149. /package/dist/web/{interfaces → src/interfaces}/events.js +0 -0
  150. /package/dist/web/{interfaces → src/interfaces}/index.d.ts +0 -0
  151. /package/dist/web/{interfaces → src/interfaces}/index.js +0 -0
  152. /package/dist/web/{interfaces → src/interfaces}/ownable.d.ts +0 -0
  153. /package/dist/web/{interfaces → src/interfaces}/ownable.js +0 -0
  154. /package/dist/web/{interfaces → src/interfaces}/owner.d.ts +0 -0
  155. /package/dist/web/{interfaces → src/interfaces}/owner.js +0 -0
  156. /package/dist/web/{interfaces → src/interfaces}/pausable.d.ts +0 -0
  157. /package/dist/web/{interfaces → src/interfaces}/pausable.js +0 -0
  158. /package/dist/web/{interfaces → src/interfaces}/types.d.ts +0 -0
  159. /package/dist/web/{interfaces → src/interfaces}/types.js +0 -0
  160. /package/dist/web/{interfaces → src/interfaces}/update.d.ts +0 -0
  161. /package/dist/web/{interfaces → src/interfaces}/update.js +0 -0
  162. /package/dist/web/{marketplace → src/marketplace}/auction.d.ts +0 -0
  163. /package/dist/web/{marketplace → src/marketplace}/auction.js +0 -0
  164. /package/dist/web/{marketplace → src/marketplace}/bid.d.ts +0 -0
  165. /package/dist/web/{marketplace → src/marketplace}/bid.js +0 -0
  166. /package/dist/web/{marketplace → src/marketplace}/index.d.ts +0 -0
  167. /package/dist/web/{marketplace → src/marketplace}/index.js +0 -0
  168. /package/dist/web/{marketplace → src/marketplace}/nft-shares.d.ts +0 -0
  169. /package/dist/web/{marketplace → src/marketplace}/nft-shares.js +0 -0
  170. /package/dist/web/{marketplace → src/marketplace}/offer.d.ts +0 -0
  171. /package/dist/web/{marketplace → src/marketplace}/offer.js +0 -0
  172. /package/dist/web/{marketplace → src/marketplace}/types.d.ts +0 -0
  173. /package/dist/web/{marketplace → src/marketplace}/types.js +0 -0
  174. /package/dist/web/{metadata → src/metadata}/address.d.ts +0 -0
  175. /package/dist/web/{metadata → src/metadata}/address.js +0 -0
  176. /package/dist/web/{metadata → src/metadata}/index.d.ts +0 -0
  177. /package/dist/web/{metadata → src/metadata}/index.js +0 -0
  178. /package/dist/web/{metadata → src/metadata}/metadata.d.ts +0 -0
  179. /package/dist/web/{metadata → src/metadata}/metadata.js +0 -0
  180. /package/dist/web/{metadata → src/metadata}/pin.d.ts +0 -0
  181. /package/dist/web/{metadata → src/metadata}/pin.js +0 -0
  182. /package/dist/web/{metadata → src/metadata}/text.d.ts +0 -0
  183. /package/dist/web/{metadata → src/metadata}/text.js +0 -0
  184. /package/dist/web/{metadata → src/metadata}/tree.d.ts +0 -0
  185. /package/dist/web/{metadata → src/metadata}/tree.js +0 -0
  186. /package/dist/web/{util → src/util}/div.d.ts +0 -0
  187. /package/dist/web/{util → src/util}/div.js +0 -0
  188. /package/dist/web/{util → src/util}/index.d.ts +0 -0
  189. /package/dist/web/{util → src/util}/index.js +0 -0
  190. /package/dist/web/{vk.d.ts → src/vk.d.ts} +0 -0
  191. /package/dist/web/{vk.js → src/vk.js} +0 -0
  192. /package/dist/web/{zkprogram-example → src/zkprogram-example}/game.d.ts +0 -0
  193. /package/dist/web/{zkprogram-example → src/zkprogram-example}/game.js +0 -0
  194. /package/dist/web/{zkprogram-example → src/zkprogram-example}/index.d.ts +0 -0
  195. /package/dist/web/{zkprogram-example → src/zkprogram-example}/index.js +0 -0
  196. /package/dist/web/{zkprogram-example → src/zkprogram-example}/update.d.ts +0 -0
  197. /package/dist/web/{zkprogram-example → src/zkprogram-example}/update.js +0 -0
@@ -0,0 +1,1248 @@
1
+ import { afterEach, beforeEach, describe, it } from "node:test";
2
+ import assert from "node:assert";
3
+ import { Mina, Field, AccountUpdate, UInt32, Bool, Cache, UInt64, fetchLastBlock, PublicKey, Poseidon, UInt8, } from "o1js";
4
+ import { fetchMinaAccount, initBlockchain, accountBalanceMina, Memory, serializeIndexedMap, sendTx, pinJSON, sleep, } from "@silvana-one/mina-utils";
5
+ import { TEST_ACCOUNTS } from "./helpers/config.js";
6
+ import { NFT, NFTAdmin, NFTAdvancedAdmin, CollectionData, fieldFromString, NFTData, MintParams, nftVerificationKeys, UInt64Option, AuctionFactory, Auction, AdminData, TransferParams, NFTTransactionContext, NFTSharesFactory, CollectionFactory, NFTStandardUpdate, } from "../src/index.js";
7
+ import { VerificationKeyUpgradeAuthority, ChainId, ValidatorsList, ValidatorsState, ValidatorsVoting, } from "@silvana-one/upgradable";
8
+ import { processArguments } from "./helpers/utils.js";
9
+ import { randomMetadata } from "./helpers/metadata.js";
10
+ import { Whitelist, Storage } from "@silvana-one/storage";
11
+ let { chain, useAdvancedAdmin, withdraw, noLog, approveTransfer, shares } = processArguments();
12
+ let local;
13
+ let name = "NFT";
14
+ const networkId = chain === "mainnet" ? "mainnet" : "devnet";
15
+ const expectedTxStatus = chain === "zeko" ? "pending" : "included";
16
+ const vk = nftVerificationKeys[networkId].vk;
17
+ const { TestPublicKey } = Mina;
18
+ let nftContractVk;
19
+ let collectionVk;
20
+ let sharesCollectionVk;
21
+ let sharesApprovalVk;
22
+ let adminVk;
23
+ let sharesAdminVk;
24
+ let upgradeAuthorityVk;
25
+ let validatorsVotingVk;
26
+ let offerVk;
27
+ let tokenVk;
28
+ let tokenAdminVk;
29
+ let sharesVk;
30
+ const cache = Cache.FileSystem("./cache");
31
+ const zkNFTKey = TestPublicKey.random();
32
+ const zkCollectionKey = TestPublicKey.random();
33
+ const zkAdminKey = TestPublicKey.random();
34
+ const zkAuctionKey = TestPublicKey.random();
35
+ const zkTokenKey = TestPublicKey.random();
36
+ const zkTokenAdminKey = TestPublicKey.random();
37
+ const zkSharesKey = TestPublicKey.random();
38
+ const upgradeAuthority = TestPublicKey.random();
39
+ const upgradeAuthorityContract = new VerificationKeyUpgradeAuthority(upgradeAuthority);
40
+ export function AuctionContractsFactory(params) {
41
+ const { useAdvancedAdmin, approval } = params;
42
+ let Collection;
43
+ let Approval;
44
+ let Update;
45
+ let Auction;
46
+ let Admin = useAdvancedAdmin ? NFTAdvancedAdmin : NFTAdmin;
47
+ let { NFTSharesAdmin, NFTSharesOwner, FungibleToken } = NFTSharesFactory({
48
+ auctionContract: () => Auction,
49
+ });
50
+ function getCollection() {
51
+ if (!Collection) {
52
+ throw new Error("Collection constructor not set up yet!");
53
+ }
54
+ return Collection;
55
+ }
56
+ function getApproval() {
57
+ if (!Approval) {
58
+ throw new Error("Approval constructor not set up yet!");
59
+ }
60
+ return Approval;
61
+ }
62
+ function getUpdate() {
63
+ if (!Update) {
64
+ throw new Error("Update constructor not set up yet!");
65
+ }
66
+ return Update;
67
+ }
68
+ function getOwner() {
69
+ if (!NFTSharesOwner) {
70
+ throw new Error("Owner constructor not set up yet!");
71
+ }
72
+ return NFTSharesOwner;
73
+ }
74
+ Auction = AuctionFactory({
75
+ collectionContract: getCollection,
76
+ });
77
+ Approval =
78
+ approval === "auction"
79
+ ? Auction
80
+ : NFTSharesOwner;
81
+ Update = NFTStandardUpdate;
82
+ Collection = CollectionFactory({
83
+ adminContract: () => Admin,
84
+ ownerContract: getOwner,
85
+ approvalContract: getApproval,
86
+ updateContract: getUpdate,
87
+ });
88
+ return {
89
+ Collection,
90
+ Approval,
91
+ Admin,
92
+ NFTSharesAdmin,
93
+ FungibleToken,
94
+ NFTSharesOwner,
95
+ };
96
+ }
97
+ const { Collection, Approval, Admin, NFTSharesAdmin, FungibleToken, NFTSharesOwner, } = AuctionContractsFactory({
98
+ useAdvancedAdmin,
99
+ approval: "auction",
100
+ });
101
+ const { Collection: SharesCollection, Admin: SharesAdmin, NFTSharesOwner: NFTSharesOwner2, } = AuctionContractsFactory({
102
+ useAdvancedAdmin,
103
+ approval: "shares",
104
+ });
105
+ const NonFungibleTokenAuctionContract = Approval;
106
+ const collectionContract = new Collection(zkCollectionKey);
107
+ const sharesCollectionContract = new SharesCollection(zkCollectionKey);
108
+ const tokenContract = new FungibleToken(zkTokenKey);
109
+ const tokenAdminContract = new NFTSharesAdmin(zkTokenAdminKey);
110
+ const sharesOwnerContract = new NFTSharesOwner(zkSharesKey);
111
+ const tokenId = collectionContract.deriveTokenId();
112
+ const adminContract = new Admin(zkAdminKey);
113
+ const auctionContract = new NonFungibleTokenAuctionContract(zkAuctionKey);
114
+ const NUMBER_OF_USERS = 8;
115
+ let admin;
116
+ let faucet;
117
+ let users = [];
118
+ const whitelistedUsers = TEST_ACCOUNTS.slice(NUMBER_OF_USERS, NUMBER_OF_USERS * 2).map((account) => TestPublicKey.fromBase58(account.privateKey));
119
+ const validators = [
120
+ TestPublicKey.random(),
121
+ TestPublicKey.random(),
122
+ TestPublicKey.random(),
123
+ ];
124
+ const creator = whitelistedUsers[0];
125
+ const auctioneer = whitelistedUsers[4];
126
+ const sharesAdmin = whitelistedUsers[6];
127
+ let owner = creator;
128
+ const nftParams = [];
129
+ describe(`Auction contracts tests: ${chain} ${withdraw ? "withdraw " : ""}${useAdvancedAdmin ? "advanced " : ""}${approveTransfer ? "approve " : ""}${shares ? "shares " : ""}${noLog ? "noLog" : ""}`, () => {
130
+ const originalConsoleLog = console.log;
131
+ if (noLog) {
132
+ beforeEach(() => {
133
+ console.log = () => { };
134
+ });
135
+ afterEach(() => {
136
+ console.log = originalConsoleLog;
137
+ });
138
+ }
139
+ it("should initialize a blockchain", async () => {
140
+ if (chain === "devnet" || chain === "zeko" || chain === "mainnet") {
141
+ await initBlockchain(chain);
142
+ admin = TestPublicKey.fromBase58(TEST_ACCOUNTS[0].privateKey);
143
+ users = TEST_ACCOUNTS.slice(1).map((account) => TestPublicKey.fromBase58(account.privateKey));
144
+ }
145
+ else if (chain === "local") {
146
+ const { keys } = await initBlockchain(chain, NUMBER_OF_USERS + 2);
147
+ local = Mina.activeInstance;
148
+ faucet = TestPublicKey(keys[0].key);
149
+ admin = TestPublicKey(keys[1].key);
150
+ users = keys.slice(2);
151
+ }
152
+ else if (chain === "lightnet") {
153
+ const { keys } = await initBlockchain(chain, NUMBER_OF_USERS + 2);
154
+ faucet = TestPublicKey(keys[0].key);
155
+ admin = TestPublicKey(keys[1].key);
156
+ users = keys.slice(2);
157
+ }
158
+ owner = creator;
159
+ assert(users.length >= NUMBER_OF_USERS);
160
+ console.log("chain:", chain);
161
+ console.log("networkId:", Mina.getNetworkId());
162
+ console.log("withdraw:", withdraw);
163
+ console.log("advanced:", useAdvancedAdmin);
164
+ console.log("Collection contract address:", zkCollectionKey.toBase58());
165
+ console.log("Admin contract address:", zkAdminKey.toBase58());
166
+ console.log("NFT contract address:", zkNFTKey.toBase58());
167
+ console.log("Upgrade authority contract address:", upgradeAuthority.toBase58());
168
+ console.log("AdvancedAdmin:", useAdvancedAdmin);
169
+ console.log("Auction contract address:", zkAuctionKey.toBase58());
170
+ console.log("Token contract address:", zkTokenKey.toBase58());
171
+ console.log("Token admin contract address:", zkTokenAdminKey.toBase58());
172
+ console.log("Shares NFT owner contract address:", zkSharesKey.toBase58());
173
+ if (chain === "local" || chain === "lightnet") {
174
+ await fetchMinaAccount({ publicKey: faucet, force: true });
175
+ let nonce = Number(Mina.getAccount(faucet).nonce.toBigint());
176
+ let txs = [];
177
+ for (const user of whitelistedUsers) {
178
+ await fetchMinaAccount({ publicKey: user, force: false });
179
+ const balance = await accountBalanceMina(user);
180
+ if (balance > 30) {
181
+ continue;
182
+ }
183
+ const transaction = await Mina.transaction({
184
+ sender: users[0],
185
+ fee: 100_000_000,
186
+ memo: "topup",
187
+ nonce: nonce++,
188
+ }, async () => {
189
+ const senderUpdate = AccountUpdate.createSigned(users[0]);
190
+ if (balance === 0)
191
+ senderUpdate.balance.subInPlace(1000000000);
192
+ senderUpdate.send({ to: user, amount: 100_000_000_000 });
193
+ });
194
+ txs.push(await sendTx({
195
+ tx: transaction.sign([users[0].key]),
196
+ description: "topup",
197
+ wait: false,
198
+ }));
199
+ }
200
+ for (const tx of txs) {
201
+ if (tx?.status === "pending") {
202
+ const txIncluded = await tx.safeWait();
203
+ if (txIncluded.status !== expectedTxStatus) {
204
+ throw new Error("Transaction not included");
205
+ }
206
+ else {
207
+ console.log("Topup tx included:", txIncluded.hash);
208
+ }
209
+ }
210
+ else
211
+ throw new Error("Topup transaction not pending");
212
+ }
213
+ console.log("Topup done");
214
+ }
215
+ console.log("Creator", creator.toBase58(), "balance:", await accountBalanceMina(creator));
216
+ console.log("Auctioneer", auctioneer.toBase58(), "balance:", await accountBalanceMina(auctioneer));
217
+ console.log("Admin ", admin.toBase58(), "balance:", await accountBalanceMina(admin));
218
+ for (let i = 0; i < NUMBER_OF_USERS; i++) {
219
+ console.log(`User ${i} `, users[i].toBase58(), "balance:", await accountBalanceMina(users[i]));
220
+ }
221
+ for (let i = 0; i < NUMBER_OF_USERS; i++) {
222
+ console.log(`Whitelisted User ${i} `, whitelistedUsers[i].toBase58(), "balance:", await accountBalanceMina(whitelistedUsers[i]));
223
+ }
224
+ Memory.info("before compiling");
225
+ });
226
+ it("should compile NFT Contract", async () => {
227
+ console.log("compiling...");
228
+ console.time("compiled NFTContract");
229
+ const { verificationKey } = await NFT.compile({ cache });
230
+ nftContractVk = verificationKey;
231
+ console.timeEnd("compiled NFTContract");
232
+ assert.strictEqual(nftContractVk.hash.toJSON(), vk.NFT.hash);
233
+ assert.strictEqual(nftContractVk.data, vk.NFT.data);
234
+ });
235
+ it("should compile Admin", async () => {
236
+ console.time("compiled Admin");
237
+ const { verificationKey } = await Admin.compile({ cache });
238
+ adminVk = verificationKey;
239
+ console.timeEnd("compiled Admin");
240
+ console.log("Admin vk hash:", adminVk.hash.toJSON());
241
+ });
242
+ it("should compile Shares Admin", async () => {
243
+ console.time("compiled Shares Admin");
244
+ const { verificationKey } = await SharesAdmin.compile({ cache });
245
+ sharesAdminVk = verificationKey;
246
+ console.timeEnd("compiled Shares Admin");
247
+ console.log("Shares Admin vk hash:", sharesAdminVk.hash.toJSON());
248
+ assert.strictEqual(sharesAdminVk.hash.toJSON(), adminVk.hash.toJSON());
249
+ assert.strictEqual(sharesAdminVk.data, adminVk.data);
250
+ });
251
+ it("should compile UpgradeAuthority", { skip: !useAdvancedAdmin }, async () => {
252
+ console.time("compiled UpgradeAuthority");
253
+ const { verificationKey } = await VerificationKeyUpgradeAuthority.compile({
254
+ cache,
255
+ });
256
+ upgradeAuthorityVk = verificationKey;
257
+ console.timeEnd("compiled UpgradeAuthority");
258
+ console.log("UpgradeAuthority vk hash:", upgradeAuthorityVk.hash.toJSON());
259
+ });
260
+ it("should compile Collection", async () => {
261
+ console.time("compiled Collection");
262
+ const { verificationKey } = await Collection.compile({ cache });
263
+ collectionVk = verificationKey;
264
+ console.timeEnd("compiled Collection");
265
+ console.log("Collection vk hash:", collectionVk.hash.toJSON());
266
+ });
267
+ it("should compile Shares Collection", { skip: !shares || withdraw }, async () => {
268
+ console.time("compiled Shares Collection");
269
+ const { verificationKey } = await SharesCollection.compile({ cache });
270
+ sharesCollectionVk = verificationKey;
271
+ console.timeEnd("compiled Shares Collection");
272
+ console.log("Shares Collection vk hash:", sharesCollectionVk.hash.toJSON());
273
+ assert.strictEqual(sharesCollectionVk.hash.toJSON(), collectionVk.hash.toJSON());
274
+ assert.strictEqual(sharesCollectionVk.data, collectionVk.data);
275
+ });
276
+ it("should compile Auction Contract", async () => {
277
+ console.time("compiled Auction Contract");
278
+ const { verificationKey } = await NonFungibleTokenAuctionContract.compile({
279
+ cache,
280
+ });
281
+ offerVk = verificationKey;
282
+ console.timeEnd("compiled Auction Contract");
283
+ console.log("Auction Contract vk hash:", offerVk.hash.toJSON());
284
+ });
285
+ it("should compile Token Admin Contract", { skip: !shares }, async () => {
286
+ console.time("compiled Token Admin Contract");
287
+ const { verificationKey } = await NFTSharesAdmin.compile({ cache });
288
+ tokenAdminVk = verificationKey;
289
+ console.timeEnd("compiled Token Admin Contract");
290
+ console.log("Token Admin Contract vk hash:", tokenAdminVk.hash.toJSON());
291
+ });
292
+ it("should compile Token Contract", { skip: !shares }, async () => {
293
+ console.time("compiled Token Contract");
294
+ const { verificationKey } = await FungibleToken.compile({ cache });
295
+ tokenVk = verificationKey;
296
+ console.timeEnd("compiled Token Contract");
297
+ console.log("Token Contract vk hash:", tokenVk.hash.toJSON());
298
+ });
299
+ it("should compile Shares Owner Contract", { skip: !shares }, async () => {
300
+ console.time("compiled Shares Owner Contract");
301
+ const { verificationKey } = await NFTSharesOwner.compile({ cache });
302
+ sharesVk = verificationKey;
303
+ console.timeEnd("compiled Shares Owner Contract");
304
+ console.log("Shares Owner Contract vk hash:", sharesVk.hash.toJSON());
305
+ });
306
+ it("should compile Shares Owner Contract (2)", { skip: !shares || withdraw }, async () => {
307
+ console.time("compiled Shares Approval Contract");
308
+ const { verificationKey } = await NFTSharesOwner2.compile({ cache });
309
+ sharesApprovalVk = verificationKey;
310
+ console.timeEnd("compiled Shares Approval Contract");
311
+ console.log("Shares Approval Contract vk hash:", sharesApprovalVk.hash.toJSON());
312
+ assert.strictEqual(sharesApprovalVk.hash.toJSON(), sharesVk.hash.toJSON());
313
+ assert.strictEqual(sharesApprovalVk.data, sharesVk.data);
314
+ });
315
+ it("should compile ValidatorsVoting", { skip: !useAdvancedAdmin }, async () => {
316
+ console.time("compiled ValidatorsVoting");
317
+ const { verificationKey } = await ValidatorsVoting.compile({ cache });
318
+ validatorsVotingVk = verificationKey;
319
+ console.timeEnd("compiled ValidatorsVoting");
320
+ console.log("ValidatorsVoting vk hash:", validatorsVotingVk.hash.toJSON());
321
+ });
322
+ it("should deploy an UpgradeAuthority", { skip: !useAdvancedAdmin }, async () => {
323
+ Memory.info("before deploy");
324
+ console.time("deployed UpgradeAuthority");
325
+ const validatorsList = new ValidatorsList();
326
+ const validatorsCount = 2; // majority is 2 validators out of 3
327
+ const list = [
328
+ { key: validators[0], authorizedToVote: true },
329
+ { key: TestPublicKey.random(), authorizedToVote: false },
330
+ { key: validators[1], authorizedToVote: true },
331
+ { key: validators[2], authorizedToVote: true },
332
+ { key: TestPublicKey.random(), authorizedToVote: false },
333
+ ];
334
+ for (let i = 0; i < list.length; i++) {
335
+ const key = Poseidon.hashPacked(PublicKey, list[i].key);
336
+ validatorsList.set(key, Field(Bool(list[i].authorizedToVote).value));
337
+ }
338
+ const data = {
339
+ validators: list.map((v) => ({
340
+ publicKey: v.key.toBase58(),
341
+ authorizedToVote: v.authorizedToVote,
342
+ })),
343
+ validatorsCount,
344
+ root: validatorsList.root.toJSON(),
345
+ map: serializeIndexedMap(validatorsList),
346
+ };
347
+ const ipfs = await pinJSON({
348
+ data,
349
+ name: "upgrade-authority-list",
350
+ });
351
+ if (!ipfs) {
352
+ throw new Error("List IPFS hash is undefined");
353
+ }
354
+ const validatorState = new ValidatorsState({
355
+ chainId: ChainId[chain === "devnet" ? "mina:devnet" : "zeko:devnet"],
356
+ root: validatorsList.root,
357
+ count: UInt32.from(validatorsCount),
358
+ });
359
+ await fetchMinaAccount({ publicKey: admin, force: true });
360
+ const tx = await Mina.transaction({
361
+ sender: admin,
362
+ fee: 100_000_000,
363
+ memo: `Deploy UpgradeAuthority`,
364
+ }, async () => {
365
+ AccountUpdate.fundNewAccount(admin, 1);
366
+ // deploy() and initialize() create 2 account updates for the same publicKey, it is intended
367
+ await upgradeAuthorityContract.deploy();
368
+ await upgradeAuthorityContract.initialize(validatorState, Storage.fromString(ipfs), validatorsVotingVk.hash);
369
+ });
370
+ await tx.prove();
371
+ assert.strictEqual((await sendTx({
372
+ tx: tx.sign([admin.key, upgradeAuthority.key]),
373
+ description: "deploy UpgradeAuthority",
374
+ }))?.status, expectedTxStatus);
375
+ console.timeEnd("deployed UpgradeAuthority");
376
+ });
377
+ it("should deploy a Collection", async () => {
378
+ console.time("deployed Collection");
379
+ const { metadataRoot, ipfsHash, name: nftName, } = await randomMetadata({
380
+ includePrivateTraits: false,
381
+ includeBanner: true,
382
+ });
383
+ if (!ipfsHash) {
384
+ throw new Error("IPFS hash is undefined");
385
+ }
386
+ name = nftName;
387
+ const slot = chain === "local"
388
+ ? Mina.currentSlot()
389
+ : chain === "zeko"
390
+ ? UInt32.zero
391
+ : (await fetchLastBlock()).globalSlotSinceGenesis;
392
+ const expiry = slot.add(UInt32.from(100000));
393
+ const masterNFT = new MintParams({
394
+ name: fieldFromString(name),
395
+ address: zkCollectionKey,
396
+ tokenId,
397
+ data: NFTData.new({
398
+ owner: creator,
399
+ }),
400
+ fee: UInt64.zero,
401
+ metadata: metadataRoot,
402
+ storage: Storage.fromString(ipfsHash),
403
+ metadataVerificationKeyHash: Field(0),
404
+ expiry,
405
+ });
406
+ await fetchMinaAccount({ publicKey: creator, force: true });
407
+ const whitelist = useAdvancedAdmin
408
+ ? (await Whitelist.create({
409
+ list: [
410
+ ...whitelistedUsers.map((user) => ({
411
+ address: user,
412
+ amount: 50_000_000_000,
413
+ })),
414
+ {
415
+ address: zkAuctionKey,
416
+ amount: 50_000_000_000,
417
+ },
418
+ {
419
+ address: zkSharesKey,
420
+ amount: 50_000_000_000,
421
+ },
422
+ ],
423
+ })).whitelist
424
+ : undefined;
425
+ const tx = await Mina.transaction({
426
+ sender: creator,
427
+ fee: 100_000_000,
428
+ memo: `Deploy Collection ${name}`.substring(0, 30),
429
+ }, async () => {
430
+ AccountUpdate.fundNewAccount(creator, 3);
431
+ if (adminContract instanceof NFTAdvancedAdmin) {
432
+ if (!whitelist) {
433
+ throw new Error("Whitelist is undefined");
434
+ }
435
+ await adminContract.deploy({
436
+ admin: creator,
437
+ upgradeAuthority,
438
+ whitelist,
439
+ uri: `AdvancedAdminContract`,
440
+ adminData: AdminData.new(),
441
+ });
442
+ }
443
+ else if (adminContract instanceof NFTAdmin) {
444
+ await adminContract.deploy({
445
+ admin: creator,
446
+ uri: `AdminContract`,
447
+ });
448
+ }
449
+ else {
450
+ throw new Error("Admin contract is not supported");
451
+ }
452
+ // deploy() and initialize() create 2 account updates for the same publicKey, it is intended
453
+ await collectionContract.deploy({
454
+ creator,
455
+ collectionName: fieldFromString(name),
456
+ baseURL: fieldFromString("ipfs"),
457
+ admin: zkAdminKey,
458
+ symbol: "NFT",
459
+ url: `https://${chain}.minanft.io`,
460
+ });
461
+ await collectionContract.initialize(masterNFT, CollectionData.new({
462
+ requireTransferApproval: approveTransfer,
463
+ royaltyFee: 10_000, // 10%
464
+ transferFee: 1_000_000_000, // 1 MINA
465
+ }));
466
+ });
467
+ await tx.prove();
468
+ assert.strictEqual((await sendTx({
469
+ tx: tx.sign([
470
+ creator.key,
471
+ zkCollectionKey.key,
472
+ zkAdminKey.key,
473
+ upgradeAuthority.key,
474
+ ]),
475
+ description: "deploy Collection",
476
+ }))?.status, expectedTxStatus);
477
+ console.timeEnd("deployed Collection");
478
+ });
479
+ it("should mint NFT", async () => {
480
+ Memory.info("before mint");
481
+ console.time("minted NFT");
482
+ const { name, ipfsHash, metadataRoot, privateMetadata } = await randomMetadata();
483
+ if (!ipfsHash) {
484
+ throw new Error("IPFS hash is undefined");
485
+ }
486
+ nftParams.push({
487
+ name,
488
+ address: zkNFTKey,
489
+ collection: zkCollectionKey,
490
+ privateMetadata,
491
+ });
492
+ await fetchMinaAccount({ publicKey: creator, force: true });
493
+ await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
494
+ await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
495
+ owner = creator;
496
+ const slot = chain === "local"
497
+ ? Mina.currentSlot()
498
+ : chain === "zeko"
499
+ ? UInt32.zero
500
+ : (await fetchLastBlock()).globalSlotSinceGenesis;
501
+ const expiry = slot.add(UInt32.from(100000));
502
+ const tx = await Mina.transaction({
503
+ sender: creator,
504
+ fee: 100_000_000,
505
+ memo: `Mint NFT ${name}`.substring(0, 30),
506
+ }, async () => {
507
+ await collectionContract.mintByCreator({
508
+ name: fieldFromString(name),
509
+ address: zkNFTKey,
510
+ tokenId,
511
+ metadata: metadataRoot,
512
+ data: NFTData.new({
513
+ canChangeMetadata: true,
514
+ canPause: true,
515
+ owner,
516
+ }),
517
+ metadataVerificationKeyHash: Field(0),
518
+ expiry,
519
+ fee: UInt64.from(10_000_000_000),
520
+ storage: Storage.fromString(ipfsHash),
521
+ });
522
+ });
523
+ await tx.prove();
524
+ assert.strictEqual((await sendTx({
525
+ tx: tx.sign([creator.key, zkNFTKey.key]),
526
+ description: "mint",
527
+ }))?.status, expectedTxStatus);
528
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
529
+ const nft = new NFT(zkNFTKey, tokenId);
530
+ const dataCheck = NFTData.unpack(nft.packedData.get());
531
+ console.log("owner", owner.toBase58());
532
+ console.log("ownerCheck", dataCheck.owner.toBase58());
533
+ console.log("approvalCheck", dataCheck.approved.toBase58());
534
+ console.log("creator", creator.toBase58());
535
+ assert.strictEqual(dataCheck.owner.equals(creator).toBoolean(), true);
536
+ assert.strictEqual(dataCheck.approved.equals(PublicKey.empty()).toBoolean(), true);
537
+ console.timeEnd("minted NFT");
538
+ owner = creator;
539
+ });
540
+ it("should transfer NFT", async () => {
541
+ Memory.info("before transfer");
542
+ console.time("transferred NFT");
543
+ await fetchMinaAccount({ publicKey: owner, force: true });
544
+ await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
545
+ await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
546
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
547
+ const requireTransferApproval = CollectionData.unpack(collectionContract.packedData.get()).requireTransferApproval.toBoolean();
548
+ console.log("requireTransferApproval", requireTransferApproval);
549
+ const to = whitelistedUsers[1];
550
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
551
+ p.collection.equals(zkCollectionKey).toBoolean());
552
+ if (!nft) {
553
+ throw new Error("NFT not found");
554
+ }
555
+ const { name } = nft;
556
+ const tx = await Mina.transaction({
557
+ sender: owner,
558
+ fee: 100_000_000,
559
+ memo: `Transfer NFT ${name}`.substring(0, 30),
560
+ }, async () => {
561
+ if (requireTransferApproval) {
562
+ await collectionContract.approvedTransferBySignature(new TransferParams({
563
+ address: zkNFTKey,
564
+ from: owner,
565
+ to,
566
+ price: UInt64Option.none(),
567
+ context: NFTTransactionContext.empty(),
568
+ }));
569
+ }
570
+ else {
571
+ await collectionContract.transferBySignature(new TransferParams({
572
+ address: zkNFTKey,
573
+ from: owner,
574
+ to,
575
+ price: UInt64Option.none(),
576
+ context: NFTTransactionContext.empty(),
577
+ }));
578
+ }
579
+ });
580
+ await tx.prove();
581
+ assert.strictEqual((await sendTx({
582
+ tx: tx.sign([owner.key]),
583
+ description: "transfer",
584
+ }))?.status, expectedTxStatus);
585
+ console.timeEnd("transferred NFT");
586
+ owner = to;
587
+ });
588
+ it("should offer NFT for auction", async () => {
589
+ Memory.info("before auction");
590
+ console.time("auctioned NFT");
591
+ const seller = owner;
592
+ await fetchMinaAccount({ publicKey: seller, force: true });
593
+ await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
594
+ await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
595
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
596
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
597
+ p.collection.equals(zkCollectionKey).toBoolean());
598
+ if (!nft) {
599
+ throw new Error("NFT not found");
600
+ }
601
+ const { name } = nft;
602
+ const slot = chain === "local"
603
+ ? Mina.currentSlot()
604
+ : chain === "zeko"
605
+ ? UInt32.zero
606
+ : (await fetchLastBlock()).globalSlotSinceGenesis;
607
+ console.log("slot", slot.toBigint());
608
+ const auctionEndTime = slot.add(UInt32.from((shares ? 20 : 10) * (chain === "lightnet" ? 2 : 1)));
609
+ console.log("auctionEndTime", auctionEndTime.toBigint());
610
+ const tx = await Mina.transaction({
611
+ sender: seller,
612
+ fee: 100_000_000,
613
+ memo: `Auction NFT ${name}`.substring(0, 30),
614
+ }, async () => {
615
+ AccountUpdate.fundNewAccount(seller, 1);
616
+ if (withdraw) {
617
+ await collectionContract.approvedTransferBySignature(new TransferParams({
618
+ address: zkNFTKey,
619
+ from: seller,
620
+ to: zkAuctionKey,
621
+ price: UInt64Option.none(),
622
+ context: NFTTransactionContext.empty(),
623
+ }));
624
+ }
625
+ else {
626
+ await collectionContract.approveAddress(zkNFTKey, zkAuctionKey);
627
+ }
628
+ await auctionContract.deploy({
629
+ collection: zkCollectionKey,
630
+ nft: zkNFTKey,
631
+ owner: seller,
632
+ minimumPrice: UInt64.from(10_000_000_000),
633
+ auctionEndTime,
634
+ auctioneer,
635
+ transferFee: UInt64.from(1_000_000_000),
636
+ saleFee: UInt32.from(15_000),
637
+ withdrawPeriod: UInt32.from(chain === "local" ? 1000 : 2),
638
+ });
639
+ });
640
+ await tx.prove();
641
+ assert.strictEqual((await sendTx({
642
+ tx: tx.sign([seller.key, zkAuctionKey.key]),
643
+ description: "auction",
644
+ }))?.status, expectedTxStatus);
645
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
646
+ const zkNFT = new NFT(zkNFTKey, tokenId);
647
+ const dataCheck = NFTData.unpack(zkNFT.packedData.get());
648
+ console.log("owner", owner.toBase58());
649
+ console.log("ownerCheck", dataCheck.owner.toBase58());
650
+ console.log("approvalCheck", dataCheck.approved.toBase58());
651
+ console.log("whitelisted 1", whitelistedUsers[1].toBase58());
652
+ console.log("creator", creator.toBase58());
653
+ assert.strictEqual(dataCheck.owner
654
+ .equals(withdraw ? zkAuctionKey : whitelistedUsers[1])
655
+ .toBoolean(), true);
656
+ assert.strictEqual(dataCheck.approved
657
+ .equals(withdraw ? PublicKey.empty() : zkAuctionKey)
658
+ .toBoolean(), true);
659
+ console.timeEnd("auctioned NFT");
660
+ });
661
+ it("should deploy NFT Shares Owner", { skip: !shares }, async () => {
662
+ Memory.info("before NFT Shares Owner");
663
+ console.time("NFT Shares Owner");
664
+ await fetchMinaAccount({ publicKey: sharesAdmin, force: true });
665
+ const tx = await Mina.transaction({
666
+ sender: sharesAdmin,
667
+ fee: 100_000_000,
668
+ memo: `NFT Shares Owner ${name}`.substring(0, 30),
669
+ }, async () => {
670
+ AccountUpdate.fundNewAccount(sharesAdmin, 4);
671
+ await tokenAdminContract.deploy({
672
+ admin: sharesAdmin,
673
+ owner: zkSharesKey,
674
+ });
675
+ await tokenContract.deploy({
676
+ symbol: "NFT_SH",
677
+ src: "NFT Shares tokens",
678
+ allowUpdates: true,
679
+ });
680
+ await tokenContract.initialize(zkTokenAdminKey, UInt8.from(9), Bool(false));
681
+ await sharesOwnerContract.deploy({
682
+ admin: sharesAdmin,
683
+ owner: zkTokenKey,
684
+ collection: zkCollectionKey,
685
+ nft: zkNFTKey,
686
+ auction: zkAuctionKey,
687
+ maxBuyPrice: UInt64.from(25_000_000_000),
688
+ minSellPrice: UInt64.from(30_000_000_000),
689
+ uri: "NFT Shares owner",
690
+ });
691
+ });
692
+ await tx.prove();
693
+ assert.strictEqual((await sendTx({
694
+ tx: tx.sign([
695
+ sharesAdmin.key,
696
+ zkSharesKey.key,
697
+ zkTokenKey.key,
698
+ zkTokenAdminKey.key,
699
+ ]),
700
+ description: "NFT Shares Owner",
701
+ }))?.status, expectedTxStatus);
702
+ console.timeEnd("NFT Shares Owner");
703
+ });
704
+ it("should subscribe to NFT Shares", { skip: !shares }, async () => {
705
+ const users = [whitelistedUsers[3], whitelistedUsers[4]];
706
+ Memory.info("before NFT Shares Subscription");
707
+ for (let i = 0; i < users.length; i++) {
708
+ const user = users[i];
709
+ const tokenId = tokenContract.deriveTokenId();
710
+ await fetchMinaAccount({ publicKey: user, force: true });
711
+ await fetchMinaAccount({ publicKey: zkSharesKey, force: true });
712
+ await fetchMinaAccount({ publicKey: zkTokenKey, force: true });
713
+ await fetchMinaAccount({ publicKey: zkTokenKey, tokenId, force: true });
714
+ await fetchMinaAccount({ publicKey: zkTokenAdminKey, force: true });
715
+ const tx = await Mina.transaction({
716
+ sender: user,
717
+ fee: 100_000_000,
718
+ memo: `NFT Shares Subscription (${i + 1})`.substring(0, 30),
719
+ }, async () => {
720
+ AccountUpdate.fundNewAccount(user, 1);
721
+ await tokenContract.mint(user, UInt64.from(10_000_000_000));
722
+ });
723
+ await tx.prove();
724
+ assert.strictEqual((await sendTx({
725
+ tx: tx.sign([user.key]),
726
+ description: `NFT Shares Subscription (${i + 1})`,
727
+ }))?.status, expectedTxStatus);
728
+ }
729
+ });
730
+ it("should bid NFT (1)", async () => {
731
+ Memory.info("before bid 1");
732
+ console.time("bid NFT 1");
733
+ const buyer = whitelistedUsers[2];
734
+ await fetchMinaAccount({ publicKey: buyer, force: true });
735
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
736
+ const slot = chain === "local"
737
+ ? Mina.currentSlot()
738
+ : chain === "zeko"
739
+ ? UInt32.zero
740
+ : (await fetchLastBlock()).globalSlotSinceGenesis;
741
+ console.log("slot", slot.toBigint());
742
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
743
+ p.collection.equals(zkCollectionKey).toBoolean());
744
+ if (!nft) {
745
+ throw new Error("NFT not found");
746
+ }
747
+ const { name } = nft;
748
+ const tx = await Mina.transaction({
749
+ sender: buyer,
750
+ fee: 100_000_000,
751
+ memo: `Bid NFT (1) ${name}`.substring(0, 30),
752
+ }, async () => {
753
+ await auctionContract.bid(UInt64.from(15_000_000_000), buyer);
754
+ });
755
+ await tx.prove();
756
+ assert.strictEqual((await sendTx({
757
+ tx: tx.sign([buyer.key]),
758
+ description: "bid 1",
759
+ }))?.status, expectedTxStatus);
760
+ console.timeEnd("bid NFT 1");
761
+ });
762
+ it("should bid NFT (2) with NFT Shares", { skip: !shares }, async () => {
763
+ Memory.info("before bid 2");
764
+ console.time("bid NFT 2 shares");
765
+ const buyer = whitelistedUsers[3];
766
+ await fetchMinaAccount({ publicKey: sharesAdmin, force: true });
767
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
768
+ await fetchMinaAccount({ publicKey: zkSharesKey, force: true });
769
+ const tokenId = tokenContract.deriveTokenId();
770
+ await fetchMinaAccount({ publicKey: buyer, tokenId, force: true });
771
+ console.log("tokenId", tokenId.toJSON());
772
+ console.log("buyer", buyer.toBase58());
773
+ console.log("zkTokenKey", zkTokenKey.toBase58());
774
+ const slot = chain === "local"
775
+ ? Mina.currentSlot()
776
+ : chain === "zeko"
777
+ ? UInt32.zero
778
+ : (await fetchLastBlock()).globalSlotSinceGenesis;
779
+ console.log("slot", slot.toBigint());
780
+ const outstandingShares = sharesOwnerContract.sharesOutstanding.get();
781
+ console.log("Outstanding shares", outstandingShares.toBigInt() / 1000000000n);
782
+ const sharesBalance = Mina.getAccount(buyer, tokenId).balance;
783
+ console.log("User shares balance", sharesBalance.toBigInt() / 1000000000n, `(${(sharesBalance.toBigInt() * 100n) / outstandingShares.toBigInt()}%, required min 25%)`);
784
+ console.log("Shares balance in MINA", await accountBalanceMina(zkSharesKey));
785
+ const balance = sharesOwnerContract.account.balance.get();
786
+ console.log("Shares balance", balance.toBigInt());
787
+ const tx = await Mina.transaction({
788
+ sender: buyer,
789
+ fee: 100_000_000,
790
+ memo: `Bid with Shares NFT ${name}`.substring(0, 30),
791
+ }, async () => {
792
+ await sharesOwnerContract.bid(UInt64.from(17_000_000_000));
793
+ //await tokenContract.approveAccountUpdate(sharesOwnerContract.self);
794
+ });
795
+ await tx.prove();
796
+ assert.strictEqual((await sendTx({
797
+ tx: tx.sign([buyer.key]),
798
+ description: "bid 2 shares",
799
+ }))?.status, expectedTxStatus);
800
+ console.timeEnd("bid NFT 2 shares");
801
+ await fetchMinaAccount({ publicKey: zkSharesKey, force: true });
802
+ console.log("Shares balance", await accountBalanceMina(zkSharesKey));
803
+ });
804
+ it("should bid NFT (3)", async () => {
805
+ Memory.info("before bid 3");
806
+ console.time("bid NFT 3");
807
+ const buyer = whitelistedUsers[4];
808
+ await fetchMinaAccount({ publicKey: buyer, force: true });
809
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
810
+ const slot = chain === "local"
811
+ ? Mina.currentSlot()
812
+ : chain === "zeko"
813
+ ? UInt32.zero
814
+ : (await fetchLastBlock()).globalSlotSinceGenesis;
815
+ console.log("slot", slot.toBigint());
816
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
817
+ p.collection.equals(zkCollectionKey).toBoolean());
818
+ if (!nft) {
819
+ throw new Error("NFT not found");
820
+ }
821
+ const { name } = nft;
822
+ const tx = await Mina.transaction({
823
+ sender: buyer,
824
+ fee: 100_000_000,
825
+ memo: `Bid NFT (3) ${name}`.substring(0, 30),
826
+ }, async () => {
827
+ await auctionContract.bid(UInt64.from(18_000_000_000), buyer);
828
+ });
829
+ await tx.prove();
830
+ assert.strictEqual((await sendTx({
831
+ tx: tx.sign([buyer.key]),
832
+ description: "bid 3",
833
+ }))?.status, expectedTxStatus);
834
+ console.timeEnd("bid NFT 3");
835
+ });
836
+ it("should bid NFT (4) with NFT Shares", { skip: !shares }, async () => {
837
+ Memory.info("before bid 4");
838
+ console.time("bid NFT 4 shares");
839
+ const buyer = whitelistedUsers[4];
840
+ await fetchMinaAccount({ publicKey: sharesAdmin, force: true });
841
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
842
+ await fetchMinaAccount({ publicKey: zkSharesKey, force: true });
843
+ const tokenId = tokenContract.deriveTokenId();
844
+ await fetchMinaAccount({ publicKey: buyer, tokenId, force: true });
845
+ console.log("tokenId", tokenId.toJSON());
846
+ console.log("buyer", buyer.toBase58());
847
+ console.log("zkTokenKey", zkTokenKey.toBase58());
848
+ const slot = chain === "local"
849
+ ? Mina.currentSlot()
850
+ : chain === "zeko"
851
+ ? UInt32.zero
852
+ : (await fetchLastBlock()).globalSlotSinceGenesis;
853
+ console.log("slot", slot.toBigint());
854
+ const outstandingShares = sharesOwnerContract.sharesOutstanding.get();
855
+ console.log("Outstanding shares", outstandingShares.toBigInt() / 1000000000n);
856
+ const sharesBalance = Mina.getAccount(buyer, tokenId).balance;
857
+ console.log("User shares balance", sharesBalance.toBigInt() / 1000000000n, `(${(sharesBalance.toBigInt() * 100n) / outstandingShares.toBigInt()}%, required min 25%)`);
858
+ console.log("Shares balance in MINA", await accountBalanceMina(zkSharesKey));
859
+ const balance = sharesOwnerContract.account.balance.get();
860
+ console.log("Shares balance", balance.toBigInt());
861
+ const tx = await Mina.transaction({
862
+ sender: buyer,
863
+ fee: 100_000_000,
864
+ memo: `Bid with Shares NFT ${name}`.substring(0, 30),
865
+ }, async () => {
866
+ await sharesOwnerContract.bid(UInt64.from(20_000_000_000));
867
+ //await tokenContract.approveAccountUpdate(sharesOwnerContract.self);
868
+ });
869
+ await tx.prove();
870
+ assert.strictEqual((await sendTx({
871
+ tx: tx.sign([buyer.key]),
872
+ description: "bid 4 shares",
873
+ }))?.status, expectedTxStatus);
874
+ console.timeEnd("bid NFT 4 shares");
875
+ await fetchMinaAccount({ publicKey: zkSharesKey, force: true });
876
+ console.log("Shares balance", await accountBalanceMina(zkSharesKey));
877
+ });
878
+ it("should wait for auction end", async () => {
879
+ Memory.info("before auction end");
880
+ console.time("auction end");
881
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
882
+ const auctionData = auctionContract.auctionData.get();
883
+ const auctionEndTime = Auction.unpack(auctionData).auctionEndTime.add(1);
884
+ const withdrawPeriod = Auction.unpack(auctionData).withdrawPeriod;
885
+ console.log("auctionEndTime", auctionEndTime.toBigint());
886
+ console.log("withdrawPeriod", withdrawPeriod.toBigint());
887
+ const endSlot = withdraw
888
+ ? auctionEndTime.add(withdrawPeriod)
889
+ : auctionEndTime;
890
+ let slot = (chain === "local"
891
+ ? Mina.currentSlot()
892
+ : chain === "zeko"
893
+ ? UInt32.zero
894
+ : (await fetchLastBlock()).globalSlotSinceGenesis).toBigint();
895
+ console.log("slot", slot);
896
+ while (slot <= endSlot.toBigint() + 1n) {
897
+ if (chain === "local") {
898
+ local.incrementGlobalSlot(withdraw ? 3500 : 100);
899
+ slot += withdraw ? 3500n : 100n;
900
+ }
901
+ else {
902
+ await sleep(60000);
903
+ slot = (await fetchLastBlock()).globalSlotSinceGenesis.toBigint();
904
+ }
905
+ console.log("slot", slot);
906
+ }
907
+ console.timeEnd("auction end");
908
+ });
909
+ it("should settle auction", { skip: withdraw }, async () => {
910
+ Memory.info("before settle auction");
911
+ console.time("settled auction");
912
+ const user = whitelistedUsers[4];
913
+ await fetchMinaAccount({ publicKey: user, force: true });
914
+ await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
915
+ await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
916
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
917
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
918
+ console.log("Auction balance", await accountBalanceMina(zkAuctionKey));
919
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
920
+ p.collection.equals(zkCollectionKey).toBoolean());
921
+ if (!nft) {
922
+ throw new Error("NFT not found");
923
+ }
924
+ const { name } = nft;
925
+ const tx = await Mina.transaction({
926
+ sender: user,
927
+ fee: 100_000_000,
928
+ memo: `Settle auction ${name}`.substring(0, 30),
929
+ }, async () => {
930
+ // Any address can settle the auction
931
+ await auctionContract.settleAuction();
932
+ });
933
+ await tx.prove();
934
+ assert.strictEqual((await sendTx({
935
+ tx: tx.sign([user.key]),
936
+ description: "settle auction",
937
+ }))?.status, expectedTxStatus);
938
+ console.timeEnd("settled auction");
939
+ owner = shares ? zkSharesKey : whitelistedUsers[4]; // The auction winner, not the user
940
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
941
+ const zkNFT = new NFT(zkNFTKey, tokenId);
942
+ const dataCheck = NFTData.unpack(zkNFT.packedData.get());
943
+ console.log("owner", owner.toBase58());
944
+ console.log("ownerCheck", dataCheck.owner.toBase58());
945
+ console.log("approvalCheck", dataCheck.approved.toBase58());
946
+ assert.strictEqual(dataCheck.owner.equals(owner).toBoolean(), true);
947
+ assert.strictEqual(dataCheck.approved.equals(PublicKey.empty()).toBoolean(), true);
948
+ });
949
+ it("should withdraw NFT", { skip: !withdraw }, async () => {
950
+ Memory.info("before withdraw NFT");
951
+ console.time("withdrawn NFT");
952
+ const user = whitelistedUsers[4];
953
+ await fetchMinaAccount({ publicKey: user, force: true });
954
+ await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
955
+ await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
956
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
957
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
958
+ console.log("Auction balance", await accountBalanceMina(zkAuctionKey));
959
+ const slot = chain === "local"
960
+ ? Mina.currentSlot()
961
+ : chain === "zeko"
962
+ ? UInt32.zero
963
+ : (await fetchLastBlock()).globalSlotSinceGenesis;
964
+ console.log("slot", slot.toBigint());
965
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
966
+ p.collection.equals(zkCollectionKey).toBoolean());
967
+ if (!nft) {
968
+ throw new Error("NFT not found");
969
+ }
970
+ const { name } = nft;
971
+ const tx = await Mina.transaction({
972
+ sender: user,
973
+ fee: 100_000_000,
974
+ memo: `Withdraw NFT ${name}`.substring(0, 30),
975
+ }, async () => {
976
+ // Any address can settle the auction
977
+ await auctionContract.withdrawNFT();
978
+ });
979
+ await tx.prove();
980
+ assert.strictEqual((await sendTx({
981
+ tx: tx.sign([user.key]),
982
+ description: "withdraw NFT",
983
+ }))?.status, expectedTxStatus);
984
+ console.timeEnd("withdrawn NFT");
985
+ owner = whitelistedUsers[1]; // The auction winner, not the user
986
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
987
+ const zkNFT = new NFT(zkNFTKey, tokenId);
988
+ const dataCheck = NFTData.unpack(zkNFT.packedData.get());
989
+ console.log("whitelisted 1", whitelistedUsers[1].toBase58());
990
+ console.log("ownerCheck", dataCheck.owner.toBase58());
991
+ console.log("approvalCheck", dataCheck.approved.toBase58());
992
+ assert.strictEqual(dataCheck.owner.equals(whitelistedUsers[1]).toBoolean(), true);
993
+ assert.strictEqual(dataCheck.approved.equals(PublicKey.empty()).toBoolean(), true);
994
+ });
995
+ it("should withdraw deposit", { skip: !withdraw }, async () => {
996
+ Memory.info("before withdraw deposit");
997
+ console.time("withdrawn deposit");
998
+ const user = whitelistedUsers[4];
999
+ await fetchMinaAccount({ publicKey: user, force: true });
1000
+ await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
1001
+ await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
1002
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
1003
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
1004
+ console.log("Auction balance", await accountBalanceMina(zkAuctionKey));
1005
+ const slot = chain === "local"
1006
+ ? Mina.currentSlot()
1007
+ : chain === "zeko"
1008
+ ? UInt32.zero
1009
+ : (await fetchLastBlock()).globalSlotSinceGenesis;
1010
+ console.log("slot", slot.toBigint());
1011
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
1012
+ p.collection.equals(zkCollectionKey).toBoolean());
1013
+ if (!nft) {
1014
+ throw new Error("NFT not found");
1015
+ }
1016
+ const { name } = nft;
1017
+ const tx = await Mina.transaction({
1018
+ sender: user,
1019
+ fee: 100_000_000,
1020
+ memo: `Withdraw NFT ${name}`.substring(0, 30),
1021
+ }, async () => {
1022
+ // Any address can withdraw the deposit
1023
+ await auctionContract.withdraw();
1024
+ });
1025
+ await tx.prove();
1026
+ assert.strictEqual((await sendTx({
1027
+ tx: tx.sign([user.key]),
1028
+ description: "withdraw deposit",
1029
+ }))?.status, expectedTxStatus);
1030
+ console.timeEnd("withdrawn deposit");
1031
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
1032
+ console.log("Auction balance", await accountBalanceMina(zkAuctionKey));
1033
+ });
1034
+ it("should settle auction payment", { skip: withdraw }, async () => {
1035
+ Memory.info("before settle auction payment");
1036
+ console.time("settled auction payment");
1037
+ const user = auctioneer;
1038
+ await fetchMinaAccount({ publicKey: user, force: true });
1039
+ await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
1040
+ await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
1041
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
1042
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
1043
+ const auctionData = auctionContract.auctionData.get();
1044
+ const auction = Auction.unpack(auctionData);
1045
+ const balance = auctionContract.account.balance.get();
1046
+ console.log("Auction balance", await accountBalanceMina(zkAuctionKey));
1047
+ const slot = chain === "local"
1048
+ ? Mina.currentSlot()
1049
+ : chain === "zeko"
1050
+ ? UInt32.zero
1051
+ : (await fetchLastBlock()).globalSlotSinceGenesis;
1052
+ console.log("slot", slot.toBigint());
1053
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
1054
+ p.collection.equals(zkCollectionKey).toBoolean());
1055
+ if (!nft) {
1056
+ throw new Error("NFT not found");
1057
+ }
1058
+ const { name } = nft;
1059
+ const tx = await Mina.transaction({
1060
+ sender: user,
1061
+ fee: 100_000_000,
1062
+ memo: `Settle auction payment ${name}`.substring(0, 30),
1063
+ }, async () => {
1064
+ // Any address can settle the auction
1065
+ await auctionContract.settlePayment();
1066
+ });
1067
+ await tx.prove();
1068
+ assert.strictEqual((await sendTx({
1069
+ tx: tx.sign([user.key]),
1070
+ description: "settle auction payment",
1071
+ }))?.status, expectedTxStatus);
1072
+ console.timeEnd("settled auction payment");
1073
+ });
1074
+ it("should settle auctioneer payment", { skip: withdraw }, async () => {
1075
+ Memory.info("before settle auctioneer payment");
1076
+ console.time("settled auctioneer payment");
1077
+ const user = auctioneer;
1078
+ await fetchMinaAccount({ publicKey: user, force: true });
1079
+ await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
1080
+ await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
1081
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
1082
+ await fetchMinaAccount({ publicKey: zkAuctionKey, force: true });
1083
+ const auctionData = auctionContract.auctionData.get();
1084
+ const auction = Auction.unpack(auctionData);
1085
+ const balance = auctionContract.account.balance.get();
1086
+ console.log("Auction balance", await accountBalanceMina(zkAuctionKey));
1087
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
1088
+ p.collection.equals(zkCollectionKey).toBoolean());
1089
+ if (!nft) {
1090
+ throw new Error("NFT not found");
1091
+ }
1092
+ const { name } = nft;
1093
+ const tx = await Mina.transaction({
1094
+ sender: user,
1095
+ fee: 100_000_000,
1096
+ memo: `Settle auctioneer payment ${name}`.substring(0, 30),
1097
+ }, async () => {
1098
+ // Any address can settle the auction
1099
+ await auctionContract.settleAuctioneerPayment(balance);
1100
+ });
1101
+ await tx.prove();
1102
+ assert.strictEqual((await sendTx({
1103
+ tx: tx.sign([user.key]),
1104
+ description: "settle auctioneer payment",
1105
+ }))?.status, expectedTxStatus);
1106
+ console.timeEnd("settled auctioneer payment");
1107
+ });
1108
+ it("should transfer NFT", { skip: shares && !withdraw }, async () => {
1109
+ Memory.info("before transfer");
1110
+ console.time("transferred NFT");
1111
+ await fetchMinaAccount({ publicKey: owner, force: true });
1112
+ await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
1113
+ await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
1114
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
1115
+ const requireTransferApproval = CollectionData.unpack(collectionContract.packedData.get()).requireTransferApproval.toBoolean();
1116
+ console.log("requireTransferApproval", requireTransferApproval);
1117
+ const to = whitelistedUsers[5];
1118
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
1119
+ p.collection.equals(zkCollectionKey).toBoolean());
1120
+ if (!nft) {
1121
+ throw new Error("NFT not found");
1122
+ }
1123
+ const { name } = nft;
1124
+ const tx = await Mina.transaction({
1125
+ sender: owner,
1126
+ fee: 100_000_000,
1127
+ memo: `Transfer NFT ${name}`.substring(0, 30),
1128
+ }, async () => {
1129
+ if (requireTransferApproval) {
1130
+ await collectionContract.approvedTransferBySignature(new TransferParams({
1131
+ address: zkNFTKey,
1132
+ from: owner,
1133
+ to,
1134
+ price: UInt64Option.none(),
1135
+ context: NFTTransactionContext.empty(),
1136
+ }));
1137
+ }
1138
+ else {
1139
+ await collectionContract.transferBySignature(new TransferParams({
1140
+ address: zkNFTKey,
1141
+ from: owner,
1142
+ to,
1143
+ price: UInt64Option.none(),
1144
+ context: NFTTransactionContext.empty(),
1145
+ }));
1146
+ }
1147
+ });
1148
+ await tx.prove();
1149
+ assert.strictEqual((await sendTx({
1150
+ tx: tx.sign([owner.key]),
1151
+ description: "transfer",
1152
+ }))?.status, expectedTxStatus);
1153
+ console.timeEnd("transferred NFT");
1154
+ owner = to;
1155
+ });
1156
+ it("should transfer NFT from NFTSharesOwner", { skip: !shares || withdraw }, async () => {
1157
+ Memory.info("before transfer");
1158
+ console.time("transferred NFT");
1159
+ console.log("zkSharesKey", zkSharesKey.toBase58());
1160
+ const to = whitelistedUsers[7];
1161
+ console.log("to", to.toBase58());
1162
+ await fetchMinaAccount({ publicKey: zkSharesKey, force: true });
1163
+ await fetchMinaAccount({ publicKey: zkCollectionKey, force: true });
1164
+ await fetchMinaAccount({ publicKey: zkAdminKey, force: true });
1165
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
1166
+ await fetchMinaAccount({ publicKey: to, force: true });
1167
+ const requireTransferApproval = CollectionData.unpack(collectionContract.packedData.get()).requireTransferApproval.toBoolean();
1168
+ console.log("requireTransferApproval", requireTransferApproval);
1169
+ console.log("sharesOwner balance", await accountBalanceMina(zkSharesKey));
1170
+ const nft = nftParams.find((p) => p.address.equals(zkNFTKey).toBoolean() &&
1171
+ p.collection.equals(zkCollectionKey).toBoolean());
1172
+ if (!nft) {
1173
+ throw new Error("NFT not found");
1174
+ }
1175
+ const { name } = nft;
1176
+ const tx = await Mina.transaction({
1177
+ sender: to,
1178
+ fee: 100_000_000,
1179
+ memo: `Transfer NFT ${name}`.substring(0, 30),
1180
+ }, async () => {
1181
+ if (requireTransferApproval) {
1182
+ await sharesCollectionContract.approvedTransferByProof(new TransferParams({
1183
+ address: zkNFTKey,
1184
+ from: zkSharesKey,
1185
+ to,
1186
+ price: UInt64Option.fromValue(30000000000n),
1187
+ context: NFTTransactionContext.empty(),
1188
+ }));
1189
+ }
1190
+ else {
1191
+ await sharesCollectionContract.transferByProof(new TransferParams({
1192
+ address: zkNFTKey,
1193
+ from: zkSharesKey,
1194
+ to,
1195
+ price: UInt64Option.fromValue(30000000000n),
1196
+ context: NFTTransactionContext.empty(),
1197
+ }));
1198
+ }
1199
+ });
1200
+ await tx.prove();
1201
+ assert.strictEqual((await sendTx({
1202
+ tx: tx.sign([to.key]),
1203
+ description: "transfer from shares",
1204
+ }))?.status, expectedTxStatus);
1205
+ console.timeEnd("transferred NFT");
1206
+ owner = to;
1207
+ await fetchMinaAccount({ publicKey: zkSharesKey, force: true });
1208
+ console.log("sharesOwner balance", await accountBalanceMina(zkSharesKey));
1209
+ await fetchMinaAccount({ publicKey: zkNFTKey, tokenId, force: true });
1210
+ const zkNFT = new NFT(zkNFTKey, tokenId);
1211
+ const dataCheck = NFTData.unpack(zkNFT.packedData.get());
1212
+ console.log("owner", owner.toBase58());
1213
+ console.log("ownerCheck", dataCheck.owner.toBase58());
1214
+ console.log("approvalCheck", dataCheck.approved.toBase58());
1215
+ assert.strictEqual(dataCheck.owner.equals(owner).toBoolean(), true);
1216
+ assert.strictEqual(dataCheck.approved.equals(PublicKey.empty()).toBoolean(), true);
1217
+ });
1218
+ it("should withdraw proceeds from NFT Shares", { skip: !shares }, async () => {
1219
+ const users = [whitelistedUsers[3], whitelistedUsers[4]];
1220
+ Memory.info("before NFT Shares Withdraw");
1221
+ for (let i = 0; i < users.length; i++) {
1222
+ const user = users[i];
1223
+ const tokenId = tokenContract.deriveTokenId();
1224
+ await fetchMinaAccount({ publicKey: user, force: true });
1225
+ await fetchMinaAccount({ publicKey: zkSharesKey, force: true });
1226
+ await fetchMinaAccount({ publicKey: zkTokenKey, force: true });
1227
+ await fetchMinaAccount({ publicKey: zkTokenKey, tokenId, force: true });
1228
+ await fetchMinaAccount({ publicKey: zkTokenAdminKey, force: true });
1229
+ console.log(`${user.toBase58()} balance`, await accountBalanceMina(user));
1230
+ const tx = await Mina.transaction({
1231
+ sender: user,
1232
+ fee: 100_000_000,
1233
+ memo: `Withdraw NFT Shares (${i + 1})`.substring(0, 30),
1234
+ }, async () => {
1235
+ await sharesOwnerContract.withdraw(UInt64.from(10_000_000_000));
1236
+ });
1237
+ await tx.prove();
1238
+ assert.strictEqual((await sendTx({
1239
+ tx: tx.sign([user.key]),
1240
+ description: `NFT Shares Withdraw (${i + 1})`,
1241
+ }))?.status, expectedTxStatus);
1242
+ console.log(`${user.toBase58()} balance`, await accountBalanceMina(user));
1243
+ }
1244
+ await fetchMinaAccount({ publicKey: zkSharesKey, force: true });
1245
+ console.log("sharesOwner balance", await accountBalanceMina(zkSharesKey));
1246
+ });
1247
+ });
1248
+ //# sourceMappingURL=auction.test.js.map