@silvana-one/abi 0.1.18 → 0.1.20
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.
- package/dist/node/index.cjs +160 -1
- package/dist/node/nft/build.d.ts +26 -3
- package/dist/node/nft/build.js +430 -1
- package/dist/node/nft/build.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsconfig.web.tsbuildinfo +1 -1
- package/dist/web/nft/build.d.ts +26 -3
- package/dist/web/nft/build.js +430 -1
- package/dist/web/nft/build.js.map +1 -1
- package/package.json +9 -9
- package/src/nft/build.ts +515 -0
package/src/nft/build.ts
CHANGED
|
@@ -12,6 +12,14 @@ import {
|
|
|
12
12
|
LaunchNftCollectionStandardAdminParams,
|
|
13
13
|
LaunchNftCollectionAdvancedAdminParams,
|
|
14
14
|
NftMintTransactionParams,
|
|
15
|
+
NftSellTransactionParams,
|
|
16
|
+
NftBuyTransactionParams,
|
|
17
|
+
NftTransferTransactionParams,
|
|
18
|
+
NftApproveTransactionParams,
|
|
19
|
+
NftMintParams,
|
|
20
|
+
NftSellParams,
|
|
21
|
+
NftBuyParams,
|
|
22
|
+
NftTransferParams,
|
|
15
23
|
} from "@silvana-one/api";
|
|
16
24
|
import { blockchain } from "../types.js";
|
|
17
25
|
import { fetchMinaAccount } from "../fetch.js";
|
|
@@ -29,6 +37,9 @@ import {
|
|
|
29
37
|
MintParams,
|
|
30
38
|
NFTData,
|
|
31
39
|
fieldToString,
|
|
40
|
+
TransferParams,
|
|
41
|
+
UInt64Option,
|
|
42
|
+
NFTTransactionContext,
|
|
32
43
|
} from "@silvana-one/nft";
|
|
33
44
|
import { tokenVerificationKeys } from "../vk/index.js";
|
|
34
45
|
import {
|
|
@@ -328,6 +339,7 @@ export async function buildNftTransaction(params: {
|
|
|
328
339
|
NftTransactionParams,
|
|
329
340
|
| LaunchNftCollectionStandardAdminParams
|
|
330
341
|
| LaunchNftCollectionAdvancedAdminParams
|
|
342
|
+
| NftMintTransactionParams
|
|
331
343
|
>;
|
|
332
344
|
developerAddress?: string;
|
|
333
345
|
provingKey?: string;
|
|
@@ -337,6 +349,7 @@ export async function buildNftTransaction(params: {
|
|
|
337
349
|
NftTransactionParams,
|
|
338
350
|
| LaunchNftCollectionStandardAdminParams
|
|
339
351
|
| LaunchNftCollectionAdvancedAdminParams
|
|
352
|
+
| NftMintTransactionParams
|
|
340
353
|
>;
|
|
341
354
|
tx: Transaction<false, false>;
|
|
342
355
|
adminType: NftAdminType;
|
|
@@ -349,6 +362,484 @@ export async function buildNftTransaction(params: {
|
|
|
349
362
|
storage: string;
|
|
350
363
|
privateMetadata?: string;
|
|
351
364
|
map?: IndexedMapSerialized;
|
|
365
|
+
}> {
|
|
366
|
+
const { chain, args } = params;
|
|
367
|
+
const { nonce, txType } = args;
|
|
368
|
+
if (nonce === undefined) throw new Error("Nonce is required");
|
|
369
|
+
if (typeof nonce !== "number") throw new Error("Nonce must be a number");
|
|
370
|
+
if (txType === undefined) throw new Error("Tx type is required");
|
|
371
|
+
if (typeof txType !== "string") throw new Error("Tx type must be a string");
|
|
372
|
+
if (args.sender === undefined || typeof args.sender !== "string")
|
|
373
|
+
throw new Error("Sender is required");
|
|
374
|
+
if (
|
|
375
|
+
args.collectionAddress === undefined ||
|
|
376
|
+
typeof args.collectionAddress !== "string"
|
|
377
|
+
)
|
|
378
|
+
throw new Error("Collection address is required");
|
|
379
|
+
if (args.nftAddress === undefined || typeof args.nftAddress !== "string")
|
|
380
|
+
throw new Error("NFT address is required");
|
|
381
|
+
const sender = PublicKey.fromBase58(args.sender);
|
|
382
|
+
const collectionAddress = PublicKey.fromBase58(args.collectionAddress);
|
|
383
|
+
if (txType === "nft:transfer" && args.nftTransferParams === undefined) {
|
|
384
|
+
throw new Error("NFT transfer params are required");
|
|
385
|
+
}
|
|
386
|
+
if (txType === "nft:sell" && args.nftSellParams === undefined) {
|
|
387
|
+
throw new Error("NFT sell params are required");
|
|
388
|
+
}
|
|
389
|
+
if (txType === "nft:buy" && args.nftBuyParams === undefined) {
|
|
390
|
+
throw new Error("NFT buy params are required");
|
|
391
|
+
}
|
|
392
|
+
const nftAddress = PublicKey.fromBase58(args.nftAddress);
|
|
393
|
+
|
|
394
|
+
// const offerAddress =
|
|
395
|
+
// "offerAddress" in args && args.offerAddress
|
|
396
|
+
// ? PublicKey.fromBase58(args.offerAddress)
|
|
397
|
+
// : undefined;
|
|
398
|
+
// if (
|
|
399
|
+
// !offerAddress &&
|
|
400
|
+
// (txType === "token:offer:create" ||
|
|
401
|
+
// txType === "token:offer:buy" ||
|
|
402
|
+
// txType === "token:offer:withdraw")
|
|
403
|
+
// )
|
|
404
|
+
// throw new Error("Offer address is required");
|
|
405
|
+
|
|
406
|
+
// const bidAddress =
|
|
407
|
+
// "bidAddress" in args && args.bidAddress
|
|
408
|
+
// ? PublicKey.fromBase58(args.bidAddress)
|
|
409
|
+
// : undefined;
|
|
410
|
+
// if (
|
|
411
|
+
// !bidAddress &&
|
|
412
|
+
// (txType === "token:bid:create" ||
|
|
413
|
+
// txType === "token:bid:sell" ||
|
|
414
|
+
// txType === "token:bid:withdraw")
|
|
415
|
+
// )
|
|
416
|
+
// throw new Error("Bid address is required");
|
|
417
|
+
|
|
418
|
+
const to =
|
|
419
|
+
"nftTransferParams" in args &&
|
|
420
|
+
args.nftTransferParams &&
|
|
421
|
+
args.nftTransferParams.to &&
|
|
422
|
+
typeof args.nftTransferParams.to === "string"
|
|
423
|
+
? PublicKey.fromBase58(args.nftTransferParams.to)
|
|
424
|
+
: undefined;
|
|
425
|
+
if (!to && txType === "nft:transfer")
|
|
426
|
+
throw new Error("To address is required");
|
|
427
|
+
|
|
428
|
+
let buyer =
|
|
429
|
+
"nftBuyParams" in args &&
|
|
430
|
+
args.nftBuyParams &&
|
|
431
|
+
args.nftBuyParams.buyer &&
|
|
432
|
+
typeof args.nftBuyParams.buyer === "string"
|
|
433
|
+
? PublicKey.fromBase58(args.nftBuyParams.buyer)
|
|
434
|
+
: undefined;
|
|
435
|
+
if (!buyer && txType === "nft:buy") buyer = sender;
|
|
436
|
+
|
|
437
|
+
const from =
|
|
438
|
+
"nftTransferParams" in args &&
|
|
439
|
+
args.nftTransferParams &&
|
|
440
|
+
args.nftTransferParams.from &&
|
|
441
|
+
typeof args.nftTransferParams.from === "string"
|
|
442
|
+
? PublicKey.fromBase58(args.nftTransferParams.from)
|
|
443
|
+
: undefined;
|
|
444
|
+
if (!from && txType === "nft:transfer")
|
|
445
|
+
throw new Error("From address is required for nft:transfer");
|
|
446
|
+
|
|
447
|
+
const price =
|
|
448
|
+
"nftSellParams" in args
|
|
449
|
+
? args.nftSellParams &&
|
|
450
|
+
args.nftSellParams.price &&
|
|
451
|
+
typeof args.nftSellParams.price === "number"
|
|
452
|
+
? UInt64.from(Math.round(args.nftSellParams.price * 1_000_000_000))
|
|
453
|
+
: undefined
|
|
454
|
+
: "nftTransferParams" in args &&
|
|
455
|
+
args.nftTransferParams &&
|
|
456
|
+
args.nftTransferParams.price &&
|
|
457
|
+
typeof args.nftTransferParams.price === "number"
|
|
458
|
+
? UInt64.from(Math.round(args.nftTransferParams.price * 1_000_000_000))
|
|
459
|
+
: undefined;
|
|
460
|
+
|
|
461
|
+
if (price === undefined && txType === "nft:sell")
|
|
462
|
+
throw new Error("Price is required for nft:sell");
|
|
463
|
+
|
|
464
|
+
await fetchMinaAccount({
|
|
465
|
+
publicKey: sender,
|
|
466
|
+
force: true,
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
if (!Mina.hasAccount(sender)) {
|
|
470
|
+
throw new Error("Sender does not have account");
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
const {
|
|
474
|
+
symbol,
|
|
475
|
+
adminContractAddress,
|
|
476
|
+
adminType,
|
|
477
|
+
verificationKeyHashes,
|
|
478
|
+
collectionName,
|
|
479
|
+
nftName,
|
|
480
|
+
storage,
|
|
481
|
+
metadataRoot,
|
|
482
|
+
} = await getNftSymbolAndAdmin({
|
|
483
|
+
txType,
|
|
484
|
+
collectionAddress,
|
|
485
|
+
chain,
|
|
486
|
+
nftAddress,
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
if (storage === undefined)
|
|
490
|
+
throw new Error("storage is required, but not provided");
|
|
491
|
+
if (metadataRoot === undefined) throw new Error("metadataRoot is required");
|
|
492
|
+
if (nftName === undefined) throw new Error("nftName is required");
|
|
493
|
+
|
|
494
|
+
const memo = args.memo ?? `${txType.split(":")[1]} ${symbol} ${nftName}`;
|
|
495
|
+
const fee = 100_000_000;
|
|
496
|
+
const provingKey = params.provingKey
|
|
497
|
+
? PublicKey.fromBase58(params.provingKey)
|
|
498
|
+
: sender;
|
|
499
|
+
const provingFee = params.provingFee
|
|
500
|
+
? UInt64.from(Math.round(params.provingFee))
|
|
501
|
+
: undefined;
|
|
502
|
+
const developerFee = args.developerFee
|
|
503
|
+
? UInt64.from(Math.round(args.developerFee))
|
|
504
|
+
: undefined;
|
|
505
|
+
const developerAddress = params.developerAddress
|
|
506
|
+
? PublicKey.fromBase58(params.developerAddress)
|
|
507
|
+
: undefined;
|
|
508
|
+
|
|
509
|
+
//const adminContract = new FungibleTokenAdmin(adminContractAddress);
|
|
510
|
+
const advancedAdminContract = new NFTAdvancedAdmin(adminContractAddress);
|
|
511
|
+
const adminContract = new NFTAdmin(adminContractAddress);
|
|
512
|
+
const collectionContract =
|
|
513
|
+
adminType === "advanced" ? AdvancedCollection : Collection;
|
|
514
|
+
|
|
515
|
+
// if (
|
|
516
|
+
// (txType === "token:admin:whitelist" ||
|
|
517
|
+
// txType === "token:bid:whitelist" ||
|
|
518
|
+
// txType === "token:offer:whitelist") &&
|
|
519
|
+
// !args.whitelist
|
|
520
|
+
// ) {
|
|
521
|
+
// throw new Error("Whitelist is required");
|
|
522
|
+
// }
|
|
523
|
+
|
|
524
|
+
// const whitelist =
|
|
525
|
+
// "whitelist" in args && args.whitelist
|
|
526
|
+
// ? typeof args.whitelist === "string"
|
|
527
|
+
// ? Whitelist.fromString(args.whitelist)
|
|
528
|
+
// : (await Whitelist.create({ list: args.whitelist, name: symbol }))
|
|
529
|
+
// .whitelist
|
|
530
|
+
// : Whitelist.empty();
|
|
531
|
+
|
|
532
|
+
const zkCollection = new collectionContract(collectionAddress);
|
|
533
|
+
const tokenId = zkCollection.deriveTokenId();
|
|
534
|
+
|
|
535
|
+
// if (
|
|
536
|
+
// txType === "nft:mint" &&
|
|
537
|
+
// adminType === "standard" &&
|
|
538
|
+
// adminAddress.toBase58() !== sender.toBase58()
|
|
539
|
+
// )
|
|
540
|
+
// throw new Error(
|
|
541
|
+
// "Invalid sender for FungibleToken mint with standard admin"
|
|
542
|
+
// );
|
|
543
|
+
|
|
544
|
+
// await fetchMinaAccount({
|
|
545
|
+
// publicKey: nftAddress,
|
|
546
|
+
// tokenId,
|
|
547
|
+
// force: (
|
|
548
|
+
// ["nft:transfer"] satisfies NftTransactionType[] as NftTransactionType[]
|
|
549
|
+
// ).includes(txType),
|
|
550
|
+
// });
|
|
551
|
+
|
|
552
|
+
// if (to) {
|
|
553
|
+
// await fetchMinaAccount({
|
|
554
|
+
// publicKey: to,
|
|
555
|
+
// force: false,
|
|
556
|
+
// });
|
|
557
|
+
// }
|
|
558
|
+
|
|
559
|
+
// if (from) {
|
|
560
|
+
// await fetchMinaAccount({
|
|
561
|
+
// publicKey: from,
|
|
562
|
+
// tokenId,
|
|
563
|
+
// force: false,
|
|
564
|
+
// });
|
|
565
|
+
// }
|
|
566
|
+
|
|
567
|
+
// if (offerAddress)
|
|
568
|
+
// await fetchMinaAccount({
|
|
569
|
+
// publicKey: offerAddress,
|
|
570
|
+
// tokenId,
|
|
571
|
+
// force: (
|
|
572
|
+
// [
|
|
573
|
+
// "token:offer:whitelist",
|
|
574
|
+
// "token:offer:buy",
|
|
575
|
+
// "token:offer:withdraw",
|
|
576
|
+
// ] satisfies TokenTransactionType[] as TokenTransactionType[]
|
|
577
|
+
// ).includes(txType),
|
|
578
|
+
// });
|
|
579
|
+
// if (bidAddress)
|
|
580
|
+
// await fetchMinaAccount({
|
|
581
|
+
// publicKey: bidAddress,
|
|
582
|
+
// force: (
|
|
583
|
+
// [
|
|
584
|
+
// "token:bid:whitelist",
|
|
585
|
+
// "token:bid:sell",
|
|
586
|
+
// "token:bid:withdraw",
|
|
587
|
+
// ] satisfies TokenTransactionType[] as TokenTransactionType[]
|
|
588
|
+
// ).includes(txType),
|
|
589
|
+
// });
|
|
590
|
+
|
|
591
|
+
// const offerContract = offerAddress
|
|
592
|
+
// ? new FungibleTokenOfferContract(offerAddress, tokenId)
|
|
593
|
+
// : undefined;
|
|
594
|
+
|
|
595
|
+
// const bidContract = bidAddress
|
|
596
|
+
// ? new FungibleTokenBidContract(bidAddress)
|
|
597
|
+
// : undefined;
|
|
598
|
+
// const offerContractDeployment = offerAddress
|
|
599
|
+
// ? new FungibleTokenOfferContract(offerAddress, tokenId)
|
|
600
|
+
// : undefined;
|
|
601
|
+
// const bidContractDeployment = bidAddress
|
|
602
|
+
// ? new FungibleTokenBidContract(bidAddress)
|
|
603
|
+
// : undefined;
|
|
604
|
+
const vk =
|
|
605
|
+
tokenVerificationKeys[chain === "mainnet" ? "mainnet" : "devnet"].vk;
|
|
606
|
+
if (
|
|
607
|
+
!vk ||
|
|
608
|
+
!vk.Collection ||
|
|
609
|
+
!vk.Collection.hash ||
|
|
610
|
+
!vk.Collection.data ||
|
|
611
|
+
!vk.AdvancedCollection ||
|
|
612
|
+
!vk.AdvancedCollection.hash ||
|
|
613
|
+
!vk.AdvancedCollection.data ||
|
|
614
|
+
!vk.NFT ||
|
|
615
|
+
!vk.NFT.hash ||
|
|
616
|
+
!vk.NFT.data ||
|
|
617
|
+
!vk.NFTAdmin ||
|
|
618
|
+
!vk.NFTAdmin.hash ||
|
|
619
|
+
!vk.NFTAdmin.data ||
|
|
620
|
+
!vk.NFTAdvancedAdmin ||
|
|
621
|
+
!vk.NFTAdvancedAdmin.hash ||
|
|
622
|
+
!vk.NFTAdvancedAdmin.data
|
|
623
|
+
)
|
|
624
|
+
throw new Error("Cannot get verification key from vk");
|
|
625
|
+
|
|
626
|
+
// const offerVerificationKey = FungibleTokenOfferContract._verificationKey ?? {
|
|
627
|
+
// hash: Field(vk.FungibleTokenOfferContract.hash),
|
|
628
|
+
// data: vk.FungibleTokenOfferContract.data,
|
|
629
|
+
// };
|
|
630
|
+
// const bidVerificationKey = FungibleTokenBidContract._verificationKey ?? {
|
|
631
|
+
// hash: Field(vk.FungibleTokenBidContract.hash),
|
|
632
|
+
// data: vk.FungibleTokenBidContract.data,
|
|
633
|
+
// };
|
|
634
|
+
|
|
635
|
+
// const isNewBidOfferAccount =
|
|
636
|
+
// txType === "token:offer:create" && offerAddress
|
|
637
|
+
// ? !Mina.hasAccount(offerAddress, tokenId)
|
|
638
|
+
// : txType === "token:bid:create" && bidAddress
|
|
639
|
+
// ? !Mina.hasAccount(bidAddress)
|
|
640
|
+
// : false;
|
|
641
|
+
|
|
642
|
+
// const isNewBuyAccount =
|
|
643
|
+
// txType === "token:offer:buy" ? !Mina.hasAccount(sender, tokenId) : false;
|
|
644
|
+
// let isNewSellAccount: boolean = false;
|
|
645
|
+
// if (txType === "token:bid:sell") {
|
|
646
|
+
// if (!bidAddress || !bidContract) throw new Error("Bid address is required");
|
|
647
|
+
// await fetchMinaAccount({
|
|
648
|
+
// publicKey: bidAddress,
|
|
649
|
+
// force: true,
|
|
650
|
+
// });
|
|
651
|
+
// const buyer = bidContract.buyer.get();
|
|
652
|
+
// await fetchMinaAccount({
|
|
653
|
+
// publicKey: buyer,
|
|
654
|
+
// tokenId,
|
|
655
|
+
// force: false,
|
|
656
|
+
// });
|
|
657
|
+
// isNewSellAccount = !Mina.hasAccount(buyer, tokenId);
|
|
658
|
+
// }
|
|
659
|
+
|
|
660
|
+
// if (txType === "token:burn") {
|
|
661
|
+
// await fetchMinaAccount({
|
|
662
|
+
// publicKey: sender,
|
|
663
|
+
// force: true,
|
|
664
|
+
// });
|
|
665
|
+
// await fetchMinaAccount({
|
|
666
|
+
// publicKey: sender,
|
|
667
|
+
// tokenId,
|
|
668
|
+
// force: false,
|
|
669
|
+
// });
|
|
670
|
+
// if (!Mina.hasAccount(sender, tokenId))
|
|
671
|
+
// throw new Error("Sender does not have tokens to burn");
|
|
672
|
+
// }
|
|
673
|
+
|
|
674
|
+
// const isNewTransferMintAccount =
|
|
675
|
+
// (txType === "token:transfer" ||
|
|
676
|
+
// txType === "token:airdrop" ||
|
|
677
|
+
// txType === "token:mint") &&
|
|
678
|
+
// to
|
|
679
|
+
// ? !Mina.hasAccount(to, tokenId)
|
|
680
|
+
// : false;
|
|
681
|
+
|
|
682
|
+
// const accountCreationFee =
|
|
683
|
+
// (isNewBidOfferAccount ? 1_000_000_000 : 0) +
|
|
684
|
+
// (isNewBuyAccount ? 1_000_000_000 : 0) +
|
|
685
|
+
// (isNewSellAccount ? 1_000_000_000 : 0) +
|
|
686
|
+
// (isNewTransferMintAccount ? 1_000_000_000 : 0) +
|
|
687
|
+
// (isToNewAccount &&
|
|
688
|
+
// txType === "token:mint" &&
|
|
689
|
+
// adminType === "advanced" &&
|
|
690
|
+
// advancedAdminContract.whitelist.get().isSome().toBoolean()
|
|
691
|
+
// ? 1_000_000_000
|
|
692
|
+
// : 0);
|
|
693
|
+
// console.log("accountCreationFee", accountCreationFee / 1_000_000_000);
|
|
694
|
+
|
|
695
|
+
// switch (txType) {
|
|
696
|
+
// case "token:offer:buy":
|
|
697
|
+
// case "token:offer:withdraw":
|
|
698
|
+
// case "token:offer:whitelist":
|
|
699
|
+
// if (offerContract === undefined)
|
|
700
|
+
// throw new Error("Offer contract is required");
|
|
701
|
+
// if (
|
|
702
|
+
// Mina.getAccount(
|
|
703
|
+
// offerContract.address,
|
|
704
|
+
// tokenId
|
|
705
|
+
// ).zkapp?.verificationKey?.hash.toJSON() !==
|
|
706
|
+
// vk.FungibleTokenOfferContract.hash
|
|
707
|
+
// )
|
|
708
|
+
// throw new Error(
|
|
709
|
+
// "Invalid offer verification key, offer contract has to be upgraded"
|
|
710
|
+
// );
|
|
711
|
+
// break;
|
|
712
|
+
// }
|
|
713
|
+
// switch (txType) {
|
|
714
|
+
// case "token:bid:sell":
|
|
715
|
+
// case "token:bid:withdraw":
|
|
716
|
+
// case "token:bid:whitelist":
|
|
717
|
+
// if (bidContract === undefined)
|
|
718
|
+
// throw new Error("Bid contract is required");
|
|
719
|
+
// if (
|
|
720
|
+
// Mina.getAccount(
|
|
721
|
+
// bidContract.address
|
|
722
|
+
// ).zkapp?.verificationKey?.hash.toJSON() !==
|
|
723
|
+
// vk.FungibleTokenBidContract.hash
|
|
724
|
+
// )
|
|
725
|
+
// throw new Error(
|
|
726
|
+
// "Invalid bid verification key, bid contract has to be upgraded"
|
|
727
|
+
// );
|
|
728
|
+
// break;
|
|
729
|
+
// }
|
|
730
|
+
|
|
731
|
+
// switch (txType) {
|
|
732
|
+
// case "token:mint":
|
|
733
|
+
// case "token:burn":
|
|
734
|
+
// case "token:redeem":
|
|
735
|
+
// case "token:transfer":
|
|
736
|
+
// case "token:airdrop":
|
|
737
|
+
// case "token:offer:create":
|
|
738
|
+
// case "token:bid:create":
|
|
739
|
+
// case "token:offer:buy":
|
|
740
|
+
// case "token:offer:withdraw":
|
|
741
|
+
// case "token:bid:sell":
|
|
742
|
+
// if (
|
|
743
|
+
// Mina.getAccount(
|
|
744
|
+
// zkToken.address
|
|
745
|
+
// ).zkapp?.verificationKey?.hash.toJSON() !== vk.FungibleToken.hash
|
|
746
|
+
// )
|
|
747
|
+
// throw new Error(
|
|
748
|
+
// "Invalid token verification key, token contract has to be upgraded"
|
|
749
|
+
// );
|
|
750
|
+
// break;
|
|
751
|
+
// }
|
|
752
|
+
|
|
753
|
+
const accountCreationFee = 0;
|
|
754
|
+
|
|
755
|
+
const tx = await Mina.transaction({ sender, fee, memo, nonce }, async () => {
|
|
756
|
+
const feeAccountUpdate = AccountUpdate.createSigned(sender);
|
|
757
|
+
if (accountCreationFee > 0) {
|
|
758
|
+
feeAccountUpdate.balance.subInPlace(accountCreationFee);
|
|
759
|
+
}
|
|
760
|
+
if (provingKey && provingFee)
|
|
761
|
+
feeAccountUpdate.send({
|
|
762
|
+
to: provingKey,
|
|
763
|
+
amount: provingFee,
|
|
764
|
+
});
|
|
765
|
+
if (developerAddress && developerFee) {
|
|
766
|
+
feeAccountUpdate.send({
|
|
767
|
+
to: developerAddress,
|
|
768
|
+
amount: developerFee,
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
switch (txType) {
|
|
773
|
+
case "nft:transfer":
|
|
774
|
+
if (!from || !to)
|
|
775
|
+
throw new Error("From and to are required for nft:transfer");
|
|
776
|
+
const context = args.nftTransferParams?.context?.custom
|
|
777
|
+
? new NFTTransactionContext({
|
|
778
|
+
custom: args.nftTransferParams.context.custom.map((x) =>
|
|
779
|
+
Field.fromJSON(x)
|
|
780
|
+
),
|
|
781
|
+
})
|
|
782
|
+
: new NFTTransactionContext({
|
|
783
|
+
custom: [Field(0), Field(0), Field(0)],
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
const transferParams: TransferParams = {
|
|
787
|
+
address: nftAddress,
|
|
788
|
+
from,
|
|
789
|
+
to,
|
|
790
|
+
price: price ? UInt64Option.from(price) : UInt64Option.none(),
|
|
791
|
+
context,
|
|
792
|
+
};
|
|
793
|
+
if (args.nftTransferParams.requireApproval === true)
|
|
794
|
+
await zkCollection.approvedTransferBySignature(transferParams);
|
|
795
|
+
else await zkCollection.transferBySignature(transferParams);
|
|
796
|
+
break;
|
|
797
|
+
|
|
798
|
+
case "nft:approve":
|
|
799
|
+
if (!to) throw new Error("To address is required for nft:approve");
|
|
800
|
+
|
|
801
|
+
await zkCollection.approveAddress(nftAddress, to);
|
|
802
|
+
break;
|
|
803
|
+
|
|
804
|
+
default:
|
|
805
|
+
throw new Error(`Unknown transaction type: ${txType}`);
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
return {
|
|
809
|
+
request: args,
|
|
810
|
+
tx,
|
|
811
|
+
adminType,
|
|
812
|
+
adminContractAddress,
|
|
813
|
+
symbol,
|
|
814
|
+
collectionName,
|
|
815
|
+
nftName,
|
|
816
|
+
verificationKeyHashes,
|
|
817
|
+
metadataRoot,
|
|
818
|
+
privateMetadata: undefined,
|
|
819
|
+
storage,
|
|
820
|
+
map: undefined,
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
export async function buildNftMintTransaction(params: {
|
|
825
|
+
chain: blockchain;
|
|
826
|
+
args: NftMintTransactionParams;
|
|
827
|
+
developerAddress?: string;
|
|
828
|
+
provingKey?: string;
|
|
829
|
+
provingFee?: number;
|
|
830
|
+
}): Promise<{
|
|
831
|
+
request: NftMintTransactionParams;
|
|
832
|
+
tx: Transaction<false, false>;
|
|
833
|
+
adminType: NftAdminType;
|
|
834
|
+
adminContractAddress: PublicKey;
|
|
835
|
+
symbol: string;
|
|
836
|
+
collectionName: string;
|
|
837
|
+
nftName: string;
|
|
838
|
+
verificationKeyHashes: string[];
|
|
839
|
+
metadataRoot: string;
|
|
840
|
+
storage: string;
|
|
841
|
+
privateMetadata?: string;
|
|
842
|
+
map?: IndexedMapSerialized;
|
|
352
843
|
}> {
|
|
353
844
|
const { chain, args } = params;
|
|
354
845
|
const { nonce, txType } = args;
|
|
@@ -803,11 +1294,17 @@ export async function getNftSymbolAndAdmin(params: {
|
|
|
803
1294
|
collectionName: string;
|
|
804
1295
|
adminType: NftAdminType;
|
|
805
1296
|
verificationKeyHashes: string[];
|
|
1297
|
+
nftName?: string;
|
|
1298
|
+
storage?: string;
|
|
1299
|
+
metadataRoot?: string;
|
|
806
1300
|
}> {
|
|
807
1301
|
const { txType, collectionAddress, chain, nftAddress } = params;
|
|
808
1302
|
const vk =
|
|
809
1303
|
tokenVerificationKeys[chain === "mainnet" ? "mainnet" : "devnet"].vk;
|
|
810
1304
|
let verificationKeyHashes: string[] = [];
|
|
1305
|
+
let nftName: string | undefined = undefined;
|
|
1306
|
+
let storage: string | undefined = undefined;
|
|
1307
|
+
let metadataRoot: string | undefined = undefined;
|
|
811
1308
|
// if (bidAddress) {
|
|
812
1309
|
// verificationKeyHashes.push(vk.FungibleTokenBidContract.hash);
|
|
813
1310
|
// }
|
|
@@ -829,6 +1326,21 @@ export async function getNftSymbolAndAdmin(params: {
|
|
|
829
1326
|
if (!Mina.hasAccount(nftAddress, tokenId)) {
|
|
830
1327
|
throw new Error("NFT account not found");
|
|
831
1328
|
}
|
|
1329
|
+
const nftAccount = Mina.getAccount(nftAddress, tokenId);
|
|
1330
|
+
const verificationKey = nftAccount.zkapp?.verificationKey;
|
|
1331
|
+
if (!verificationKey) {
|
|
1332
|
+
throw new Error("NFT contract verification key not found");
|
|
1333
|
+
}
|
|
1334
|
+
if (!verificationKeyHashes.includes(verificationKey.hash.toJSON())) {
|
|
1335
|
+
verificationKeyHashes.push(verificationKey.hash.toJSON());
|
|
1336
|
+
}
|
|
1337
|
+
if (nftAccount.zkapp?.appState === undefined) {
|
|
1338
|
+
throw new Error("NFT contract state not found");
|
|
1339
|
+
}
|
|
1340
|
+
const nft = new NFT(nftAddress, tokenId);
|
|
1341
|
+
nftName = fieldToString(nft.name.get());
|
|
1342
|
+
storage = nft.storage.get().toString();
|
|
1343
|
+
metadataRoot = nft.metadata.get().toJSON();
|
|
832
1344
|
}
|
|
833
1345
|
|
|
834
1346
|
const account = Mina.getAccount(collectionAddress);
|
|
@@ -942,5 +1454,8 @@ export async function getNftSymbolAndAdmin(params: {
|
|
|
942
1454
|
collectionName,
|
|
943
1455
|
adminType,
|
|
944
1456
|
verificationKeyHashes,
|
|
1457
|
+
nftName,
|
|
1458
|
+
storage,
|
|
1459
|
+
metadataRoot,
|
|
945
1460
|
};
|
|
946
1461
|
}
|