@arcanetech/privacy-sdk-stellar 0.5.2 → 0.6.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.
- package/README.md +1 -0
- package/dist/index.d.ts +85 -25
- package/dist/index.js +1081 -258
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +25 -1
- package/dist/node.js +1082 -267
- package/dist/node.js.map +1 -1
- package/dist/state/index.d.ts +31 -1
- package/dist/state/index.js +10 -2
- package/dist/state/index.js.map +1 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/transact/index.d.ts +50 -6
- package/dist/transact/index.js +975 -264
- package/dist/transact/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -452,13 +452,26 @@ function buildPrivateRecordFromDeposit(input) {
|
|
|
452
452
|
};
|
|
453
453
|
}
|
|
454
454
|
|
|
455
|
-
// src/transact/
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
455
|
+
// src/transact/merkle/lean-imt-api.ts
|
|
456
|
+
function asLeanImtSessionApi(sdk) {
|
|
457
|
+
const candidate = sdk;
|
|
458
|
+
if (typeof candidate.importLeanImtFromState !== "function") {
|
|
459
|
+
return void 0;
|
|
460
|
+
}
|
|
461
|
+
if (typeof candidate.insertTwoLeanImt !== "function") {
|
|
462
|
+
return void 0;
|
|
463
|
+
}
|
|
464
|
+
if (typeof candidate.exportLeanImt !== "function") {
|
|
465
|
+
return void 0;
|
|
466
|
+
}
|
|
467
|
+
if (typeof candidate.dropLeanImt !== "function") {
|
|
468
|
+
return void 0;
|
|
469
|
+
}
|
|
470
|
+
if (typeof candidate.buildWithdrawMerkleWitnessFromHandle !== "function") {
|
|
471
|
+
return void 0;
|
|
472
|
+
}
|
|
473
|
+
return candidate;
|
|
474
|
+
}
|
|
462
475
|
|
|
463
476
|
// src/transact/merkle/field-decimal.ts
|
|
464
477
|
import { Buffer as Buffer4 } from "buffer";
|
|
@@ -474,6 +487,230 @@ function merkleRootBufferToFrDecimal(root) {
|
|
|
474
487
|
const hex = Buffer4.from(root).toString("hex");
|
|
475
488
|
return (BigInt(`0x${hex}`) % BN254).toString(DECIMAL_STRING_RADIX);
|
|
476
489
|
}
|
|
490
|
+
var MERKLE_ROOT_HEX_PATTERN = /^[0-9a-fA-F]{64}$/;
|
|
491
|
+
function merkleRootHexToFrDecimal(merkleRootHex) {
|
|
492
|
+
const trimmed = merkleRootHex.trim();
|
|
493
|
+
if (!MERKLE_ROOT_HEX_PATTERN.test(trimmed)) {
|
|
494
|
+
return void 0;
|
|
495
|
+
}
|
|
496
|
+
return merkleRootBufferToFrDecimal(Buffer4.from(trimmed, "hex"));
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// src/transact/merkle/state-file.ts
|
|
500
|
+
function merkleSnapshotToStateFile(input) {
|
|
501
|
+
const root = merkleRootHexToFrDecimal(input.merkleRootHex);
|
|
502
|
+
const nodes = input.nodes;
|
|
503
|
+
if (!nodes || nodes.length === 0 || root === void 0) {
|
|
504
|
+
return { commitments: input.commitments };
|
|
505
|
+
}
|
|
506
|
+
return {
|
|
507
|
+
commitments: input.commitments,
|
|
508
|
+
nodes,
|
|
509
|
+
root
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// src/transact/merkle/extend-snapshot.ts
|
|
514
|
+
function isEvenLeafCount(count) {
|
|
515
|
+
return count % 2 === 0;
|
|
516
|
+
}
|
|
517
|
+
function importHandle(sdk, state) {
|
|
518
|
+
try {
|
|
519
|
+
return sdk.importLeanImtFromState(state);
|
|
520
|
+
} catch {
|
|
521
|
+
return void 0;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function insertNewPairs(input) {
|
|
525
|
+
for (let index = input.prefixLength; index < input.commitments.length; index += 2) {
|
|
526
|
+
const leafA = input.commitments.at(index);
|
|
527
|
+
const leafB = input.commitments.at(index + 1);
|
|
528
|
+
if (leafA === void 0 || leafB === void 0) {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
try {
|
|
532
|
+
input.sdk.insertTwoLeanImt(input.handle, leafA, leafB);
|
|
533
|
+
} catch {
|
|
534
|
+
return false;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
return true;
|
|
538
|
+
}
|
|
539
|
+
function snapshotNodes(sdk, handle) {
|
|
540
|
+
try {
|
|
541
|
+
return sdk.exportLeanImt(handle).nodes;
|
|
542
|
+
} catch {
|
|
543
|
+
return void 0;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function prefixSnapshotState(input) {
|
|
547
|
+
const prefixLength = input.cachedState?.nodes ? input.cachedState.commitments.length : 0;
|
|
548
|
+
return merkleSnapshotToStateFile({
|
|
549
|
+
commitments: input.commitments.slice(0, prefixLength),
|
|
550
|
+
merkleRootHex: input.cachedState?.merkleRootHex ?? input.merkleRootHex,
|
|
551
|
+
...input.cachedState?.nodes ? { nodes: input.cachedState.nodes } : {}
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
function importSnapshotState(input) {
|
|
555
|
+
if (input.prefixState.nodes && input.prefixState.commitments.length > 0) {
|
|
556
|
+
return input.prefixState;
|
|
557
|
+
}
|
|
558
|
+
return merkleSnapshotToStateFile({
|
|
559
|
+
commitments: input.commitments,
|
|
560
|
+
merkleRootHex: input.merkleRootHex
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
function exportExtendedNodes(input) {
|
|
564
|
+
const inserted = input.prefixState.nodes ? insertNewPairs({
|
|
565
|
+
sdk: input.sdk,
|
|
566
|
+
handle: input.handle,
|
|
567
|
+
prefixLength: input.prefixState.commitments.length,
|
|
568
|
+
commitments: input.commitments
|
|
569
|
+
}) : true;
|
|
570
|
+
if (!inserted) {
|
|
571
|
+
input.sdk.dropLeanImt(input.handle);
|
|
572
|
+
return void 0;
|
|
573
|
+
}
|
|
574
|
+
const nodes = snapshotNodes(input.sdk, input.handle);
|
|
575
|
+
if (!nodes) {
|
|
576
|
+
input.sdk.dropLeanImt(input.handle);
|
|
577
|
+
}
|
|
578
|
+
return nodes;
|
|
579
|
+
}
|
|
580
|
+
function extendMerkleSnapshotNodes(input) {
|
|
581
|
+
if (!isEvenLeafCount(input.commitments.length)) {
|
|
582
|
+
return {};
|
|
583
|
+
}
|
|
584
|
+
const prefixState = prefixSnapshotState(input);
|
|
585
|
+
const handle = importHandle(
|
|
586
|
+
input.sdk,
|
|
587
|
+
importSnapshotState({ ...input, prefixState })
|
|
588
|
+
);
|
|
589
|
+
if (handle === void 0) {
|
|
590
|
+
return {};
|
|
591
|
+
}
|
|
592
|
+
const nodes = exportExtendedNodes({
|
|
593
|
+
sdk: input.sdk,
|
|
594
|
+
handle,
|
|
595
|
+
prefixState,
|
|
596
|
+
commitments: input.commitments
|
|
597
|
+
});
|
|
598
|
+
if (!nodes) {
|
|
599
|
+
return {};
|
|
600
|
+
}
|
|
601
|
+
return { nodes, handle };
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// src/transact/merkle/tree-session.ts
|
|
605
|
+
var merkleSdkHost;
|
|
606
|
+
function registerMerkleSessionSdkHost(host) {
|
|
607
|
+
merkleSdkHost = host;
|
|
608
|
+
}
|
|
609
|
+
async function loadSessionSdk() {
|
|
610
|
+
const host = merkleSdkHost;
|
|
611
|
+
if (typeof host?.getInitializedSdk !== "function") {
|
|
612
|
+
return void 0;
|
|
613
|
+
}
|
|
614
|
+
try {
|
|
615
|
+
return asLeanImtSessionApi(await host.getInitializedSdk());
|
|
616
|
+
} catch {
|
|
617
|
+
return void 0;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
var sessionsByPool = /* @__PURE__ */ new Map();
|
|
621
|
+
var handlesByKey = /* @__PURE__ */ new Map();
|
|
622
|
+
function merkleSessionKey(state) {
|
|
623
|
+
const root = state.root?.trim();
|
|
624
|
+
if (root) {
|
|
625
|
+
return `${state.commitments.length}:${root}`;
|
|
626
|
+
}
|
|
627
|
+
const first = state.commitments[0] ?? "";
|
|
628
|
+
const last = state.commitments.at(-1) ?? "";
|
|
629
|
+
return `${state.commitments.length}:${first}:${last}`;
|
|
630
|
+
}
|
|
631
|
+
function rememberHandle(poolContract, key, handle) {
|
|
632
|
+
const existing = sessionsByPool.get(poolContract);
|
|
633
|
+
if (existing && existing.handle !== handle) {
|
|
634
|
+
handlesByKey.delete(existing.key);
|
|
635
|
+
}
|
|
636
|
+
sessionsByPool.set(poolContract, { handle, key });
|
|
637
|
+
handlesByKey.set(key, handle);
|
|
638
|
+
}
|
|
639
|
+
function importHandle2(sdk, state) {
|
|
640
|
+
try {
|
|
641
|
+
return sdk.importLeanImtFromState(state);
|
|
642
|
+
} catch {
|
|
643
|
+
return void 0;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
function merkleTreeHandleForState(state) {
|
|
647
|
+
return handlesByKey.get(merkleSessionKey(state));
|
|
648
|
+
}
|
|
649
|
+
function bindImportedMerkleTree(input) {
|
|
650
|
+
rememberHandle(input.poolContract, merkleSessionKey(input.state), input.handle);
|
|
651
|
+
}
|
|
652
|
+
async function bindPoolMerkleTree(state) {
|
|
653
|
+
const sdk = await loadSessionSdk();
|
|
654
|
+
if (!sdk) {
|
|
655
|
+
return void 0;
|
|
656
|
+
}
|
|
657
|
+
const snapshot = merkleSnapshotToStateFile(state);
|
|
658
|
+
const key = merkleSessionKey(snapshot);
|
|
659
|
+
const existing = sessionsByPool.get(state.poolContract);
|
|
660
|
+
if (existing?.key === key) {
|
|
661
|
+
return existing.handle;
|
|
662
|
+
}
|
|
663
|
+
const handle = importHandle2(sdk, snapshot);
|
|
664
|
+
if (handle === void 0) {
|
|
665
|
+
return void 0;
|
|
666
|
+
}
|
|
667
|
+
if (existing) {
|
|
668
|
+
sdk.dropLeanImt(existing.handle);
|
|
669
|
+
}
|
|
670
|
+
rememberHandle(state.poolContract, key, handle);
|
|
671
|
+
return handle;
|
|
672
|
+
}
|
|
673
|
+
async function resolveExtendedMerkleNodes(input) {
|
|
674
|
+
const cached = input.cachedState;
|
|
675
|
+
if (cached && cached.commitments.length === input.commitments.length && cached.merkleRootHex === input.merkleRootHex) {
|
|
676
|
+
return cached.nodes;
|
|
677
|
+
}
|
|
678
|
+
const sdk = await loadSessionSdk();
|
|
679
|
+
if (!sdk) {
|
|
680
|
+
return void 0;
|
|
681
|
+
}
|
|
682
|
+
const extended = extendMerkleSnapshotNodes({
|
|
683
|
+
sdk,
|
|
684
|
+
commitments: input.commitments,
|
|
685
|
+
merkleRootHex: input.merkleRootHex,
|
|
686
|
+
...cached ? { cachedState: cached } : {}
|
|
687
|
+
});
|
|
688
|
+
if (extended.handle !== void 0) {
|
|
689
|
+
bindImportedMerkleTree({
|
|
690
|
+
poolContract: input.poolContract,
|
|
691
|
+
handle: extended.handle,
|
|
692
|
+
state: merkleSnapshotToStateFile({
|
|
693
|
+
commitments: input.commitments,
|
|
694
|
+
merkleRootHex: input.merkleRootHex,
|
|
695
|
+
...extended.nodes ? { nodes: extended.nodes } : {}
|
|
696
|
+
})
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
return extended.nodes;
|
|
700
|
+
}
|
|
701
|
+
function withdrawMerkleWitnessFromTree(input) {
|
|
702
|
+
const session = asLeanImtSessionApi(input.sdk);
|
|
703
|
+
const handle = merkleTreeHandleForState(input.state);
|
|
704
|
+
if (session && handle !== void 0) {
|
|
705
|
+
return session.buildWithdrawMerkleWitnessFromHandle(input.coin, handle);
|
|
706
|
+
}
|
|
707
|
+
return input.sdk.buildWithdrawMerkleWitness(input.coin, input.state);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// src/transact/pool/service.ts
|
|
711
|
+
import {
|
|
712
|
+
decodeDecodedEphemeralKey
|
|
713
|
+
} from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
477
714
|
|
|
478
715
|
// src/transact/private-address/codec.ts
|
|
479
716
|
import {
|
|
@@ -704,7 +941,7 @@ var MIN_CONFIDENTIAL_TRANSFER_STROOPS = 1n;
|
|
|
704
941
|
var ZERO_STROOPS = 0n;
|
|
705
942
|
function withdrawWitnessForCoin(parameters) {
|
|
706
943
|
const { sdk, coin, state } = parameters;
|
|
707
|
-
const witness = sdk
|
|
944
|
+
const witness = withdrawMerkleWitnessFromTree({ sdk, coin, state });
|
|
708
945
|
const withdrawApplicationId = coin.application_id ?? parameters.applicationId;
|
|
709
946
|
const withdrawObject = withdrawObjectFromMerkleWitness(
|
|
710
947
|
witness,
|
|
@@ -746,14 +983,144 @@ function requireChangeRecipientWhenPartial(changeStroops, selfPrivateAddressStpl
|
|
|
746
983
|
}
|
|
747
984
|
}
|
|
748
985
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
986
|
+
|
|
987
|
+
// src/transact/fees/quote-request-body.ts
|
|
988
|
+
function presentInstructedAmount(amount) {
|
|
989
|
+
const trimmed = amount?.trim() ?? "";
|
|
990
|
+
if (!trimmed || trimmed === "0") {
|
|
991
|
+
return void 0;
|
|
992
|
+
}
|
|
993
|
+
return trimmed;
|
|
994
|
+
}
|
|
995
|
+
function feeQuoteRequestBody(request) {
|
|
996
|
+
const publicDepositAmount = presentInstructedAmount(request.publicDepositAmount);
|
|
997
|
+
const transferInstructedAmount = presentInstructedAmount(
|
|
998
|
+
request.transferInstructedAmount
|
|
999
|
+
);
|
|
1000
|
+
const publicWithdrawalAmount = presentInstructedAmount(
|
|
1001
|
+
request.publicWithdrawalAmount
|
|
1002
|
+
);
|
|
1003
|
+
return {
|
|
1004
|
+
feeAsset: request.feeAsset,
|
|
1005
|
+
spendsNotes: request.spendsNotes,
|
|
1006
|
+
...publicDepositAmount === void 0 ? {} : { publicDepositAmount },
|
|
1007
|
+
...transferInstructedAmount === void 0 ? {} : { transferInstructedAmount },
|
|
1008
|
+
...publicWithdrawalAmount === void 0 ? {} : { publicWithdrawalAmount }
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
// src/transact/fees/quote-required-fee.ts
|
|
1013
|
+
function quoteHeaders(inspectAuthorization) {
|
|
1014
|
+
const token = inspectAuthorization?.trim();
|
|
1015
|
+
return {
|
|
1016
|
+
"content-type": "application/json",
|
|
1017
|
+
...token ? { authorization: `Bearer ${token}` } : {}
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
function parseRequiredFee(raw) {
|
|
1021
|
+
const text = `${raw ?? ""}`.trim();
|
|
1022
|
+
if (!/^\d+$/u.test(text)) {
|
|
1023
|
+
throw new Error("Fee Quote Required Fee must be an integer minor-unit string.");
|
|
752
1024
|
}
|
|
753
|
-
|
|
754
|
-
|
|
1025
|
+
return BigInt(text);
|
|
1026
|
+
}
|
|
1027
|
+
function requireQuoteString(raw, field) {
|
|
1028
|
+
const text = `${raw ?? ""}`.trim();
|
|
1029
|
+
if (!text) {
|
|
1030
|
+
throw new Error(`Fee Quote is missing ${field}.`);
|
|
755
1031
|
}
|
|
756
|
-
return
|
|
1032
|
+
return text;
|
|
1033
|
+
}
|
|
1034
|
+
function parseQuotePayload(payload) {
|
|
1035
|
+
return {
|
|
1036
|
+
requiredFee: parseRequiredFee(payload.requiredFee),
|
|
1037
|
+
feeAsset: requireQuoteString(payload.feeAsset, "Fee Asset"),
|
|
1038
|
+
feeCollectorPrivateAddress: requireQuoteString(
|
|
1039
|
+
payload.feeCollectorPrivateAddress,
|
|
1040
|
+
"Fee Collector Private Address"
|
|
1041
|
+
),
|
|
1042
|
+
feeRate: requireQuoteString(payload.feeRate, "Fee Rate")
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
async function quoteRequiredFee(input) {
|
|
1046
|
+
const response = await fetch(
|
|
1047
|
+
`${input.transactEnvironment.kyt.apiBaseUrl}/kyt/fees/quote`,
|
|
1048
|
+
{
|
|
1049
|
+
method: "POST",
|
|
1050
|
+
headers: quoteHeaders(input.transactEnvironment.kyt.inspectAuthorization),
|
|
1051
|
+
body: JSON.stringify(feeQuoteRequestBody(input.request))
|
|
1052
|
+
}
|
|
1053
|
+
);
|
|
1054
|
+
const payload = await response.json();
|
|
1055
|
+
if (!response.ok) {
|
|
1056
|
+
throw new Error(`Fee Quote failed: ${JSON.stringify(payload)}`);
|
|
1057
|
+
}
|
|
1058
|
+
return parseQuotePayload(payload);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
// src/transact/fees/should-attach-fee-output.ts
|
|
1062
|
+
function shouldAttachFeeOutput(input) {
|
|
1063
|
+
if (input.spendSource === "escrow" && input.escrowSend !== true) {
|
|
1064
|
+
return false;
|
|
1065
|
+
}
|
|
1066
|
+
return input.kind === "deposit" || input.kind === "transfer" || input.kind === "withdraw";
|
|
1067
|
+
}
|
|
1068
|
+
function feeOutputKindFromPrepared(prepared) {
|
|
1069
|
+
return {
|
|
1070
|
+
kind: prepared.kind,
|
|
1071
|
+
...prepared.transactArtifacts?.spendSource ? { spendSource: prepared.transactArtifacts.spendSource } : {},
|
|
1072
|
+
...prepared.transactArtifacts?.escrowSend ? { escrowSend: true } : {}
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
// src/transact/fees/quote-fee-output-for-prepared.ts
|
|
1077
|
+
function instructedMinorUnits(prepared) {
|
|
1078
|
+
return prepared.intent.amount.toString();
|
|
1079
|
+
}
|
|
1080
|
+
function quoteRequestForPrepared(input) {
|
|
1081
|
+
const amount = instructedMinorUnits(input.prepared);
|
|
1082
|
+
if (input.prepared.kind === "deposit") {
|
|
1083
|
+
return {
|
|
1084
|
+
feeAsset: input.tokenAddress,
|
|
1085
|
+
publicDepositAmount: amount,
|
|
1086
|
+
spendsNotes: false
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
if (input.prepared.kind === "withdraw") {
|
|
1090
|
+
return {
|
|
1091
|
+
feeAsset: input.tokenAddress,
|
|
1092
|
+
publicWithdrawalAmount: amount,
|
|
1093
|
+
spendsNotes: true
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1096
|
+
return {
|
|
1097
|
+
feeAsset: input.tokenAddress,
|
|
1098
|
+
transferInstructedAmount: amount,
|
|
1099
|
+
spendsNotes: true
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
async function quoteFeeOutputForPrepared(input) {
|
|
1103
|
+
if (!shouldAttachFeeOutput(feeOutputKindFromPrepared(input.prepared))) {
|
|
1104
|
+
return void 0;
|
|
1105
|
+
}
|
|
1106
|
+
const quote = await quoteRequiredFee({
|
|
1107
|
+
transactEnvironment: input.environment,
|
|
1108
|
+
request: quoteRequestForPrepared(input)
|
|
1109
|
+
});
|
|
1110
|
+
if (quote.requiredFee <= 0n) {
|
|
1111
|
+
return void 0;
|
|
1112
|
+
}
|
|
1113
|
+
return {
|
|
1114
|
+
requiredFee: quote.requiredFee,
|
|
1115
|
+
feeCollectorPrivateAddress: quote.feeCollectorPrivateAddress
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
function remainingAfterRequiredFee(input) {
|
|
1119
|
+
const remaining = input.available - input.instructed - input.requiredFee;
|
|
1120
|
+
if (remaining < 0n) {
|
|
1121
|
+
throw new Error("Instructed amount and Required Fee exceed available note value");
|
|
1122
|
+
}
|
|
1123
|
+
return remaining;
|
|
757
1124
|
}
|
|
758
1125
|
|
|
759
1126
|
// src/transact/audit/parameters.ts
|
|
@@ -894,6 +1261,32 @@ function privKeyScalarDecimalFromRecipientScalarHex(hexInput) {
|
|
|
894
1261
|
return canonicalBabyJubScalarFromInteger(value).toString(DECIMAL_RADIX2);
|
|
895
1262
|
}
|
|
896
1263
|
|
|
1264
|
+
// src/transact/fees/append-fee-output.ts
|
|
1265
|
+
function feeCoinFromSlot(slot) {
|
|
1266
|
+
return {
|
|
1267
|
+
commitment_hex: slot.commitment_hex,
|
|
1268
|
+
coin: slot.coin,
|
|
1269
|
+
depositScalarHex: slot.depositScalarHex,
|
|
1270
|
+
precommitementHex: slot.precommitementHex
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
async function appendFeeOutputSlot(input) {
|
|
1274
|
+
const requiredFee = input.feeOutput?.requiredFee ?? ZERO_STROOPS;
|
|
1275
|
+
const collector = input.feeOutput?.feeCollectorPrivateAddress.trim() ?? "";
|
|
1276
|
+
if (requiredFee <= ZERO_STROOPS || !collector) {
|
|
1277
|
+
return { deposits: input.deposits };
|
|
1278
|
+
}
|
|
1279
|
+
const slot = await input.buildAlignedDepositSlot({
|
|
1280
|
+
privateAddressStpl1: collector,
|
|
1281
|
+
amountStroops: requiredFee,
|
|
1282
|
+
tokenAddress: input.tokenAddress
|
|
1283
|
+
});
|
|
1284
|
+
return {
|
|
1285
|
+
deposits: [...input.deposits, slot.deposit],
|
|
1286
|
+
feeCoin: feeCoinFromSlot(slot)
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
|
|
897
1290
|
// src/transact/proofs/withdraw/helpers.ts
|
|
898
1291
|
function destinationWithdrawFrAndScalar(parameters) {
|
|
899
1292
|
const pkHex = ed25519PublicKeyHexFromStellarAccount(
|
|
@@ -948,14 +1341,15 @@ async function resolveWithdrawChangeDeposits(parameters) {
|
|
|
948
1341
|
}
|
|
949
1342
|
};
|
|
950
1343
|
}
|
|
951
|
-
function validateDualWithdrawAmounts(withdrawAmountStroops, totalNotes, changePrivateAddressStpl1) {
|
|
1344
|
+
function validateDualWithdrawAmounts(withdrawAmountStroops, totalNotes, changePrivateAddressStpl1, requiredFee) {
|
|
952
1345
|
if (withdrawAmountStroops < MIN_CONFIDENTIAL_TRANSFER_STROOPS) {
|
|
953
1346
|
throw new Error("Withdraw amount must be positive");
|
|
954
1347
|
}
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1348
|
+
const changeStroops = remainingAfterRequiredFee({
|
|
1349
|
+
available: totalNotes,
|
|
1350
|
+
instructed: withdrawAmountStroops,
|
|
1351
|
+
requiredFee
|
|
1352
|
+
});
|
|
959
1353
|
requireChangeRecipientWhenPartial(changeStroops, changePrivateAddressStpl1);
|
|
960
1354
|
return changeStroops;
|
|
961
1355
|
}
|
|
@@ -968,11 +1362,31 @@ function buildDualWithdrawPublicInput(parameters) {
|
|
|
968
1362
|
publicWithdrawalAmount: parameters.publicWithdrawalAmount
|
|
969
1363
|
});
|
|
970
1364
|
}
|
|
1365
|
+
async function withdrawOutputsWithOptionalFee(parameters) {
|
|
1366
|
+
const { deposits: changeDeposits, changeCoin } = await resolveWithdrawChangeDeposits({
|
|
1367
|
+
changeStroops: parameters.changeStroops,
|
|
1368
|
+
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
1369
|
+
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
1370
|
+
tokenAddress: parameters.tokenAddress
|
|
1371
|
+
});
|
|
1372
|
+
const withFee = await appendFeeOutputSlot({
|
|
1373
|
+
deposits: changeDeposits,
|
|
1374
|
+
tokenAddress: parameters.tokenAddress,
|
|
1375
|
+
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
1376
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1377
|
+
});
|
|
1378
|
+
return {
|
|
1379
|
+
deposits: withFee.deposits,
|
|
1380
|
+
...changeCoin ? { changeCoin } : {},
|
|
1381
|
+
...withFee.feeCoin ? { feeCoin: withFee.feeCoin } : {}
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
971
1384
|
async function prepareDualWithdrawProofInputs(parameters) {
|
|
972
1385
|
const changeStroops = validateDualWithdrawAmounts(
|
|
973
1386
|
parameters.withdrawAmountStroops,
|
|
974
1387
|
BigInt(parameters.coinA.value) + BigInt(parameters.coinB.value),
|
|
975
|
-
parameters.changePrivateAddressStpl1
|
|
1388
|
+
parameters.changePrivateAddressStpl1,
|
|
1389
|
+
parameters.feeOutput?.requiredFee ?? 0n
|
|
976
1390
|
);
|
|
977
1391
|
const { legA, legB } = dualWithdrawLegsWithSharedRoot({
|
|
978
1392
|
sdk: parameters.sdk,
|
|
@@ -987,11 +1401,12 @@ async function prepareDualWithdrawProofInputs(parameters) {
|
|
|
987
1401
|
),
|
|
988
1402
|
applicationId: parameters.applicationId
|
|
989
1403
|
});
|
|
990
|
-
const { deposits, changeCoin } = await
|
|
1404
|
+
const { deposits, changeCoin, feeCoin } = await withdrawOutputsWithOptionalFee({
|
|
991
1405
|
changeStroops,
|
|
992
1406
|
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
993
1407
|
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
994
|
-
tokenAddress: parameters.tokenAddress
|
|
1408
|
+
tokenAddress: parameters.tokenAddress,
|
|
1409
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
995
1410
|
});
|
|
996
1411
|
const publicInput = buildDualWithdrawPublicInput({
|
|
997
1412
|
destinationStellarAddress: parameters.destinationStellarAddress,
|
|
@@ -1010,19 +1425,55 @@ async function prepareDualWithdrawProofInputs(parameters) {
|
|
|
1010
1425
|
audit,
|
|
1011
1426
|
deposits,
|
|
1012
1427
|
withdrawLegs: [legA.withdrawObject, legB.withdrawObject],
|
|
1013
|
-
...changeCoin ? { changeCoin } : {}
|
|
1428
|
+
...changeCoin ? { changeCoin } : {},
|
|
1429
|
+
...feeCoin ? { feeCoin } : {}
|
|
1014
1430
|
};
|
|
1015
1431
|
}
|
|
1016
1432
|
|
|
1433
|
+
// src/transact/proofs/withdraw/fee-deposits.ts
|
|
1434
|
+
async function withdrawDepositsWithFee(parameters) {
|
|
1435
|
+
const { deposits, changeCoin } = await resolveWithdrawChangeDeposits({
|
|
1436
|
+
changeStroops: parameters.changeStroops,
|
|
1437
|
+
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
1438
|
+
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
1439
|
+
tokenAddress: parameters.tokenAddress
|
|
1440
|
+
});
|
|
1441
|
+
const withFee = await appendFeeOutputSlot({
|
|
1442
|
+
deposits,
|
|
1443
|
+
tokenAddress: parameters.tokenAddress,
|
|
1444
|
+
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
1445
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1446
|
+
});
|
|
1447
|
+
return {
|
|
1448
|
+
deposits: withFee.deposits,
|
|
1449
|
+
...changeCoin ? { changeCoin } : {},
|
|
1450
|
+
...withFee.feeCoin ? { feeCoin: withFee.feeCoin } : {}
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
function withdrawOutputApplicationIds(input) {
|
|
1454
|
+
const outputIds = [];
|
|
1455
|
+
if (input.hasChange) {
|
|
1456
|
+
outputIds.push(input.applicationId);
|
|
1457
|
+
}
|
|
1458
|
+
if (input.hasFeeOutput) {
|
|
1459
|
+
outputIds.push(input.applicationId);
|
|
1460
|
+
}
|
|
1461
|
+
if (outputIds.length === 0) {
|
|
1462
|
+
outputIds.push("0");
|
|
1463
|
+
}
|
|
1464
|
+
return outputIds;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1017
1467
|
// src/transact/proofs/withdraw/transact-proof.ts
|
|
1018
|
-
function validateSingleWithdrawAmounts(withdrawAmountStroops, noteStroops) {
|
|
1468
|
+
function validateSingleWithdrawAmounts(withdrawAmountStroops, noteStroops, requiredFee) {
|
|
1019
1469
|
if (withdrawAmountStroops < MIN_CONFIDENTIAL_TRANSFER_STROOPS) {
|
|
1020
1470
|
throw new Error("Withdraw amount must be positive");
|
|
1021
1471
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1472
|
+
return remainingAfterRequiredFee({
|
|
1473
|
+
available: noteStroops,
|
|
1474
|
+
instructed: withdrawAmountStroops,
|
|
1475
|
+
requiredFee
|
|
1476
|
+
});
|
|
1026
1477
|
}
|
|
1027
1478
|
async function proveSingleWithdrawTransaction(parameters) {
|
|
1028
1479
|
return parameters.sdk.proveTransaction(
|
|
@@ -1040,10 +1491,11 @@ async function proveSingleWithdrawTransaction(parameters) {
|
|
|
1040
1491
|
);
|
|
1041
1492
|
}
|
|
1042
1493
|
function buildPrimaryWithdrawForCoin(parameters) {
|
|
1043
|
-
const witness =
|
|
1044
|
-
parameters.
|
|
1045
|
-
parameters.
|
|
1046
|
-
|
|
1494
|
+
const witness = withdrawMerkleWitnessFromTree({
|
|
1495
|
+
sdk: parameters.sdk,
|
|
1496
|
+
coin: parameters.coin,
|
|
1497
|
+
state: parameters.state
|
|
1498
|
+
});
|
|
1047
1499
|
const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
|
|
1048
1500
|
parameters.privKeyScalarHex
|
|
1049
1501
|
);
|
|
@@ -1061,7 +1513,8 @@ function buildPrimaryWithdrawForCoin(parameters) {
|
|
|
1061
1513
|
async function prepareSingleWithdrawProofInputs(parameters) {
|
|
1062
1514
|
const changeStroops = validateSingleWithdrawAmounts(
|
|
1063
1515
|
parameters.withdrawAmountStroops,
|
|
1064
|
-
BigInt(parameters.coin.value)
|
|
1516
|
+
BigInt(parameters.coin.value),
|
|
1517
|
+
parameters.feeOutput?.requiredFee ?? 0n
|
|
1065
1518
|
);
|
|
1066
1519
|
const { witness, primaryWithdraw } = buildPrimaryWithdrawForCoin({
|
|
1067
1520
|
sdk: parameters.sdk,
|
|
@@ -1070,11 +1523,12 @@ async function prepareSingleWithdrawProofInputs(parameters) {
|
|
|
1070
1523
|
state: parameters.state,
|
|
1071
1524
|
privKeyScalarHex: parameters.privKeyScalarHex
|
|
1072
1525
|
});
|
|
1073
|
-
const { deposits, changeCoin } = await
|
|
1526
|
+
const { deposits, changeCoin, feeCoin } = await withdrawDepositsWithFee({
|
|
1074
1527
|
changeStroops,
|
|
1075
1528
|
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
1076
1529
|
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
1077
|
-
tokenAddress: parameters.tokenAddress
|
|
1530
|
+
tokenAddress: parameters.tokenAddress,
|
|
1531
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1078
1532
|
});
|
|
1079
1533
|
const publicInput = buildWithdrawPublicInput({
|
|
1080
1534
|
stateRoot: witness.stateRoot,
|
|
@@ -1087,6 +1541,7 @@ async function prepareSingleWithdrawProofInputs(parameters) {
|
|
|
1087
1541
|
primaryWithdraw,
|
|
1088
1542
|
deposits,
|
|
1089
1543
|
changeCoin,
|
|
1544
|
+
feeCoin,
|
|
1090
1545
|
publicInput,
|
|
1091
1546
|
audit: buildPoolTransactionAuditParameters({
|
|
1092
1547
|
applicationId: parameters.applicationId,
|
|
@@ -1096,7 +1551,7 @@ async function prepareSingleWithdrawProofInputs(parameters) {
|
|
|
1096
1551
|
};
|
|
1097
1552
|
}
|
|
1098
1553
|
async function proveWithdrawTransact(parameters) {
|
|
1099
|
-
const { primaryWithdraw, deposits, changeCoin, publicInput, audit } = await prepareSingleWithdrawProofInputs(parameters);
|
|
1554
|
+
const { primaryWithdraw, deposits, changeCoin, feeCoin, publicInput, audit } = await prepareSingleWithdrawProofInputs(parameters);
|
|
1100
1555
|
const proof = await proveSingleWithdrawTransaction({
|
|
1101
1556
|
sdk: parameters.sdk,
|
|
1102
1557
|
publicInput,
|
|
@@ -1111,13 +1566,17 @@ async function proveWithdrawTransact(parameters) {
|
|
|
1111
1566
|
applicationIdsPlaintext: buildApplicationIdHints({
|
|
1112
1567
|
sdk: parameters.sdk,
|
|
1113
1568
|
inputIds: [parameters.applicationId],
|
|
1114
|
-
outputIds:
|
|
1569
|
+
outputIds: withdrawOutputApplicationIds({
|
|
1570
|
+
applicationId: parameters.applicationId,
|
|
1571
|
+
hasChange: Boolean(changeCoin),
|
|
1572
|
+
hasFeeOutput: Boolean(feeCoin)
|
|
1573
|
+
})
|
|
1115
1574
|
}),
|
|
1116
1575
|
...changeCoin ? { changeCoin } : {}
|
|
1117
1576
|
};
|
|
1118
1577
|
}
|
|
1119
1578
|
async function proveWithdrawTransactDual(parameters) {
|
|
1120
|
-
const { publicInput, audit, withdrawLegs, deposits, changeCoin } = await prepareDualWithdrawProofInputs(parameters);
|
|
1579
|
+
const { publicInput, audit, withdrawLegs, deposits, changeCoin, feeCoin } = await prepareDualWithdrawProofInputs(parameters);
|
|
1121
1580
|
const proof = await parameters.sdk.proveTransaction(
|
|
1122
1581
|
publicInput,
|
|
1123
1582
|
padPublicLegsToLayout(
|
|
@@ -1136,7 +1595,11 @@ async function proveWithdrawTransactDual(parameters) {
|
|
|
1136
1595
|
applicationIdsPlaintext: buildApplicationIdHints({
|
|
1137
1596
|
sdk: parameters.sdk,
|
|
1138
1597
|
inputIds: [audit.applicationId, audit.applicationId],
|
|
1139
|
-
outputIds:
|
|
1598
|
+
outputIds: withdrawOutputApplicationIds({
|
|
1599
|
+
applicationId: audit.applicationId,
|
|
1600
|
+
hasChange: Boolean(changeCoin),
|
|
1601
|
+
hasFeeOutput: Boolean(feeCoin)
|
|
1602
|
+
})
|
|
1140
1603
|
}),
|
|
1141
1604
|
...changeCoin ? { changeCoin } : {}
|
|
1142
1605
|
};
|
|
@@ -1160,6 +1623,9 @@ var DEFAULT_ZK_CONFIG_NONCE = BINDING_ZK_NONCE;
|
|
|
1160
1623
|
function resolveZkConfigNonce(transactEnvironment) {
|
|
1161
1624
|
return transactEnvironment.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
|
|
1162
1625
|
}
|
|
1626
|
+
function transactNonceFromArtifacts(artifacts, transactEnvironment) {
|
|
1627
|
+
return artifacts?.zkConfigNonce ?? resolveZkConfigNonce(transactEnvironment);
|
|
1628
|
+
}
|
|
1163
1629
|
|
|
1164
1630
|
// src/transact/zk/browser-artifact-cache.ts
|
|
1165
1631
|
import { ZK_ARTIFACT_VERSION } from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
@@ -1412,6 +1878,105 @@ async function buildAlignedDepositSlotForSdk(sdk, applicationId, parameters) {
|
|
|
1412
1878
|
};
|
|
1413
1879
|
}
|
|
1414
1880
|
|
|
1881
|
+
// src/transact/pool/initialize-sdk.ts
|
|
1882
|
+
import { PrivacyPoolSDK as PrivacyPoolSDK2 } from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
1883
|
+
async function initializePrivacyPoolSdk(input, nonce) {
|
|
1884
|
+
const zkConfigNonce = nonce ?? input.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
|
|
1885
|
+
const zkCircuits = await materializeSelectedZkCircuit(
|
|
1886
|
+
input.zkCircuits,
|
|
1887
|
+
zkConfigNonce,
|
|
1888
|
+
input.zkArtifactBaseUrl
|
|
1889
|
+
);
|
|
1890
|
+
return PrivacyPoolSDK2.init({
|
|
1891
|
+
wasmBinary: input.assets.sdkWasm,
|
|
1892
|
+
zkCircuits,
|
|
1893
|
+
zkConfigNonce,
|
|
1894
|
+
...optionalZkArtifactBaseUrl(input.zkArtifactBaseUrl)
|
|
1895
|
+
});
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
// src/transact/fees/zk-config-nonce-for-kind.ts
|
|
1899
|
+
function configuredNonceSpread(zkConfigNonce) {
|
|
1900
|
+
if (zkConfigNonce === void 0) {
|
|
1901
|
+
return {};
|
|
1902
|
+
}
|
|
1903
|
+
return { configuredNonce: zkConfigNonce };
|
|
1904
|
+
}
|
|
1905
|
+
function zkConfigNonceForFeeBearingKind(input) {
|
|
1906
|
+
if (input.configuredNonce === SIX_BY_SIX_BINDING_ZK_NONCE) {
|
|
1907
|
+
return SIX_BY_SIX_BINDING_ZK_NONCE;
|
|
1908
|
+
}
|
|
1909
|
+
if (input.kind === "transfer" && shouldAttachFeeOutput(input)) {
|
|
1910
|
+
return SIX_BY_SIX_BINDING_ZK_NONCE;
|
|
1911
|
+
}
|
|
1912
|
+
return input.configuredNonce ?? BINDING_ZK_NONCE;
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
// src/transact/pool/prepare-deposit-proof.ts
|
|
1916
|
+
import {
|
|
1917
|
+
randomFrDecimal253,
|
|
1918
|
+
scalarHexToFrDecimal as scalarHexToFrDecimal2
|
|
1919
|
+
} from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
1920
|
+
function userDepositSlot(input) {
|
|
1921
|
+
return {
|
|
1922
|
+
value: input.coin.value,
|
|
1923
|
+
nullifier: input.coin.nullifier,
|
|
1924
|
+
ephemeralKeyScalar: scalarHexToFrDecimal2(input.depositScalarHex),
|
|
1925
|
+
asset: [input.coin.asset_hi, input.coin.asset_lo],
|
|
1926
|
+
applicationId: input.applicationId,
|
|
1927
|
+
recipientPublicKeys: recipientPublicKeysDecimalFromPrivateAddress(
|
|
1928
|
+
input.privateAddressStpl1
|
|
1929
|
+
)
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
function outputApplicationIds(input) {
|
|
1933
|
+
if (input.hasFeeOutput) {
|
|
1934
|
+
return [input.applicationId, input.applicationId];
|
|
1935
|
+
}
|
|
1936
|
+
return [input.applicationId];
|
|
1937
|
+
}
|
|
1938
|
+
async function proveDepositTransact(input) {
|
|
1939
|
+
const publicDeposit = (input.publicDepositStroops ?? BigInt(input.coin.value)).toString();
|
|
1940
|
+
const withFee = await appendFeeOutputSlot({
|
|
1941
|
+
deposits: [userDepositSlot(input)],
|
|
1942
|
+
tokenAddress: input.tokenAddress,
|
|
1943
|
+
buildAlignedDepositSlot: input.buildAlignedDepositSlot,
|
|
1944
|
+
...input.feeOutput ? { feeOutput: input.feeOutput } : {}
|
|
1945
|
+
});
|
|
1946
|
+
const audit = buildPoolTransactionAuditParameters({
|
|
1947
|
+
applicationId: input.applicationId,
|
|
1948
|
+
nAuditSlots: input.sdk.getLayout().nAuditSlots,
|
|
1949
|
+
...input.auditPublicKey ? { auditPublicKey: input.auditPublicKey } : {}
|
|
1950
|
+
});
|
|
1951
|
+
const proof = await input.sdk.proveTransaction(
|
|
1952
|
+
withTokenAddressPublicInputs(
|
|
1953
|
+
{
|
|
1954
|
+
stateRoot: merkleRootBufferToFrDecimal(input.merkleRootBytes),
|
|
1955
|
+
privKeyScalar: randomFrDecimal253()
|
|
1956
|
+
},
|
|
1957
|
+
input.tokenAddress
|
|
1958
|
+
),
|
|
1959
|
+
padPublicLegsToLayout(
|
|
1960
|
+
input.sdk,
|
|
1961
|
+
buildPublicDepositLegs(input.tokenAddress, publicDeposit)
|
|
1962
|
+
),
|
|
1963
|
+
padWithdrawSlotsToLayout(input.sdk, []),
|
|
1964
|
+
padDepositSlotsToLayout(input.sdk, withFee.deposits),
|
|
1965
|
+
audit
|
|
1966
|
+
);
|
|
1967
|
+
return {
|
|
1968
|
+
...proof,
|
|
1969
|
+
applicationIdsPlaintext: buildApplicationIdHints({
|
|
1970
|
+
sdk: input.sdk,
|
|
1971
|
+
inputIds: [],
|
|
1972
|
+
outputIds: outputApplicationIds({
|
|
1973
|
+
applicationId: input.applicationId,
|
|
1974
|
+
hasFeeOutput: Boolean(withFee.feeCoin)
|
|
1975
|
+
})
|
|
1976
|
+
})
|
|
1977
|
+
};
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1415
1980
|
// src/transact/pool/service.ts
|
|
1416
1981
|
var PrivacyPoolService = class {
|
|
1417
1982
|
constructor(assets, applicationId, auditPublicKey, zkCircuits, zkConfigNonce, zkArtifactBaseUrl) {
|
|
@@ -1428,42 +1993,50 @@ var PrivacyPoolService = class {
|
|
|
1428
1993
|
zkCircuits;
|
|
1429
1994
|
zkConfigNonce;
|
|
1430
1995
|
zkArtifactBaseUrl;
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
async
|
|
1434
|
-
|
|
1435
|
-
|
|
1996
|
+
sdks = /* @__PURE__ */ new Map();
|
|
1997
|
+
initPromises = /* @__PURE__ */ new Map();
|
|
1998
|
+
async getInitializedSdk(nonce) {
|
|
1999
|
+
const zkConfigNonce = nonce ?? this.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
|
|
2000
|
+
const key = zkConfigNonce.toString();
|
|
2001
|
+
const existing = this.sdks.get(key);
|
|
2002
|
+
if (existing) {
|
|
2003
|
+
return existing;
|
|
1436
2004
|
}
|
|
1437
|
-
|
|
1438
|
-
|
|
2005
|
+
const pending = this.initPromises.get(key);
|
|
2006
|
+
if (pending) {
|
|
2007
|
+
return pending;
|
|
2008
|
+
}
|
|
2009
|
+
const started = this.initializeSdk(zkConfigNonce);
|
|
2010
|
+
this.initPromises.set(key, started);
|
|
2011
|
+
try {
|
|
2012
|
+
const sdk = await started;
|
|
2013
|
+
this.sdks.set(key, sdk);
|
|
2014
|
+
return sdk;
|
|
2015
|
+
} finally {
|
|
2016
|
+
this.initPromises.delete(key);
|
|
1439
2017
|
}
|
|
1440
|
-
this.initPromise = (async () => {
|
|
1441
|
-
if (!this.assets) {
|
|
1442
|
-
throw new Error(
|
|
1443
|
-
"PrivacyPoolService requires browser ZK assets before initialization."
|
|
1444
|
-
);
|
|
1445
|
-
}
|
|
1446
|
-
const zkConfigNonce = this.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
|
|
1447
|
-
const zkCircuits = await materializeSelectedZkCircuit(
|
|
1448
|
-
this.zkCircuits,
|
|
1449
|
-
zkConfigNonce,
|
|
1450
|
-
this.zkArtifactBaseUrl
|
|
1451
|
-
);
|
|
1452
|
-
this.sdk = await PrivacyPoolSDK2.init({
|
|
1453
|
-
wasmBinary: this.assets.sdkWasm,
|
|
1454
|
-
zkCircuits,
|
|
1455
|
-
zkConfigNonce,
|
|
1456
|
-
...optionalZkArtifactBaseUrl(this.zkArtifactBaseUrl)
|
|
1457
|
-
});
|
|
1458
|
-
})();
|
|
1459
|
-
return this.initPromise;
|
|
1460
2018
|
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
2019
|
+
feeBearingZkConfigNonce(input) {
|
|
2020
|
+
return zkConfigNonceForFeeBearingKind({
|
|
2021
|
+
...input,
|
|
2022
|
+
...configuredNonceSpread(this.zkConfigNonce)
|
|
2023
|
+
});
|
|
2024
|
+
}
|
|
2025
|
+
async initializeSdk(nonce) {
|
|
2026
|
+
if (!this.assets) {
|
|
2027
|
+
throw new Error(
|
|
2028
|
+
"PrivacyPoolService requires browser ZK assets before initialization."
|
|
2029
|
+
);
|
|
1465
2030
|
}
|
|
1466
|
-
return
|
|
2031
|
+
return initializePrivacyPoolSdk(
|
|
2032
|
+
{
|
|
2033
|
+
assets: this.assets,
|
|
2034
|
+
...this.zkCircuits ? { zkCircuits: this.zkCircuits } : {},
|
|
2035
|
+
...this.zkConfigNonce === void 0 ? {} : { zkConfigNonce: this.zkConfigNonce },
|
|
2036
|
+
...optionalZkArtifactBaseUrl(this.zkArtifactBaseUrl)
|
|
2037
|
+
},
|
|
2038
|
+
nonce
|
|
2039
|
+
);
|
|
1467
2040
|
}
|
|
1468
2041
|
getAuditPublicKey() {
|
|
1469
2042
|
return this.auditPublicKey;
|
|
@@ -1496,65 +2069,51 @@ var PrivacyPoolService = class {
|
|
|
1496
2069
|
return { commitment_hex, coin, depositScalarHex, precommitementHex };
|
|
1497
2070
|
}
|
|
1498
2071
|
async prepareDepositTransactProof(parameters) {
|
|
1499
|
-
const sdk = await this.getInitializedSdk(
|
|
1500
|
-
|
|
1501
|
-
const recipientPublicKeys = recipientPublicKeysDecimalFromPrivateAddress(
|
|
1502
|
-
parameters.privateAddressStpl1
|
|
1503
|
-
);
|
|
1504
|
-
const applicationId = this.getApplicationId();
|
|
1505
|
-
const audit = buildPoolTransactionAuditParameters({
|
|
1506
|
-
applicationId,
|
|
1507
|
-
nAuditSlots: sdk.getLayout().nAuditSlots,
|
|
1508
|
-
...this.auditPublicKey ? { auditPublicKey: this.auditPublicKey } : {}
|
|
1509
|
-
});
|
|
1510
|
-
const deposit = {
|
|
1511
|
-
value: parameters.coin.value,
|
|
1512
|
-
nullifier: parameters.coin.nullifier,
|
|
1513
|
-
ephemeralKeyScalar: scalarHexToFrDecimal2(parameters.depositScalarHex),
|
|
1514
|
-
asset: [parameters.coin.asset_hi, parameters.coin.asset_lo],
|
|
1515
|
-
applicationId,
|
|
1516
|
-
recipientPublicKeys
|
|
1517
|
-
};
|
|
1518
|
-
const publicInput = withTokenAddressPublicInputs(
|
|
1519
|
-
{
|
|
1520
|
-
stateRoot,
|
|
1521
|
-
privKeyScalar: randomFrDecimal253()
|
|
1522
|
-
},
|
|
1523
|
-
parameters.tokenAddress
|
|
1524
|
-
);
|
|
1525
|
-
const proof = await sdk.proveTransaction(
|
|
1526
|
-
publicInput,
|
|
1527
|
-
padPublicLegsToLayout(
|
|
1528
|
-
sdk,
|
|
1529
|
-
buildPublicDepositLegs(parameters.tokenAddress, parameters.coin.value)
|
|
1530
|
-
),
|
|
1531
|
-
padWithdrawSlotsToLayout(sdk, []),
|
|
1532
|
-
padDepositSlotsToLayout(sdk, [deposit]),
|
|
1533
|
-
audit
|
|
2072
|
+
const sdk = await this.getInitializedSdk(
|
|
2073
|
+
this.feeBearingZkConfigNonce({ kind: "deposit" })
|
|
1534
2074
|
);
|
|
1535
|
-
|
|
2075
|
+
return proveDepositTransact({
|
|
1536
2076
|
sdk,
|
|
1537
|
-
|
|
1538
|
-
|
|
2077
|
+
applicationId: this.getApplicationId(),
|
|
2078
|
+
privateAddressStpl1: parameters.privateAddressStpl1,
|
|
2079
|
+
coin: parameters.coin,
|
|
2080
|
+
depositScalarHex: parameters.depositScalarHex,
|
|
2081
|
+
merkleRootBytes: parameters.merkleRootBytes,
|
|
2082
|
+
tokenAddress: parameters.tokenAddress,
|
|
2083
|
+
buildAlignedDepositSlot: (input) => this.buildAlignedDepositSlot(input),
|
|
2084
|
+
...this.auditPublicKey ? { auditPublicKey: this.auditPublicKey } : {},
|
|
2085
|
+
...parameters.publicDepositStroops === void 0 ? {} : { publicDepositStroops: parameters.publicDepositStroops },
|
|
2086
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1539
2087
|
});
|
|
1540
|
-
return { ...proof, applicationIdsPlaintext };
|
|
1541
2088
|
}
|
|
1542
2089
|
async calculateNullifierHash(nullifier, privKeyScalar) {
|
|
1543
2090
|
const sdk = await this.getInitializedSdk();
|
|
1544
2091
|
return sdk.calculateNullifierHash(nullifier, privKeyScalar);
|
|
1545
2092
|
}
|
|
1546
2093
|
async prepareWithdrawTransactProof(parameters) {
|
|
1547
|
-
const sdk = await this.getInitializedSdk(
|
|
2094
|
+
const sdk = await this.getInitializedSdk(
|
|
2095
|
+
this.feeBearingZkConfigNonce({ kind: "withdraw" })
|
|
2096
|
+
);
|
|
1548
2097
|
return proveWithdrawTransact({
|
|
1549
2098
|
sdk,
|
|
1550
2099
|
applicationId: this.getApplicationId(),
|
|
1551
2100
|
buildAlignedDepositSlot: (input) => this.buildAlignedDepositSlot(input),
|
|
1552
2101
|
...this.auditPublicKey ? { auditPublicKey: this.auditPublicKey } : {},
|
|
1553
|
-
|
|
2102
|
+
coin: parameters.coin,
|
|
2103
|
+
state: parameters.state,
|
|
2104
|
+
destinationStellarAddress: parameters.destinationStellarAddress,
|
|
2105
|
+
privKeyScalarHex: parameters.privKeyScalarHex,
|
|
2106
|
+
depositorEphemeralKey: parameters.depositorEphemeralKey,
|
|
2107
|
+
withdrawAmountStroops: parameters.withdrawAmountStroops,
|
|
2108
|
+
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
2109
|
+
tokenAddress: parameters.tokenAddress,
|
|
2110
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1554
2111
|
});
|
|
1555
2112
|
}
|
|
1556
2113
|
async prepareWithdrawTransactProofDual(parameters) {
|
|
1557
|
-
const sdk = await this.getInitializedSdk(
|
|
2114
|
+
const sdk = await this.getInitializedSdk(
|
|
2115
|
+
this.feeBearingZkConfigNonce({ kind: "withdraw" })
|
|
2116
|
+
);
|
|
1558
2117
|
return proveWithdrawTransactDual({
|
|
1559
2118
|
sdk,
|
|
1560
2119
|
applicationId: this.getApplicationId(),
|
|
@@ -1569,7 +2128,8 @@ var PrivacyPoolService = class {
|
|
|
1569
2128
|
ephemeralBKey: parameters.depositorEphemeralBKey,
|
|
1570
2129
|
withdrawAmountStroops: parameters.withdrawAmountStroops,
|
|
1571
2130
|
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
1572
|
-
tokenAddress: parameters.tokenAddress
|
|
2131
|
+
tokenAddress: parameters.tokenAddress,
|
|
2132
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1573
2133
|
});
|
|
1574
2134
|
}
|
|
1575
2135
|
};
|
|
@@ -1588,6 +2148,7 @@ function createPrivacyPoolService(input) {
|
|
|
1588
2148
|
var configuredPrivacyPoolService;
|
|
1589
2149
|
function configurePrivacyPoolService(service) {
|
|
1590
2150
|
configuredPrivacyPoolService = service;
|
|
2151
|
+
registerMerkleSessionSdkHost(service);
|
|
1591
2152
|
}
|
|
1592
2153
|
function getPrivacyPoolService() {
|
|
1593
2154
|
if (!configuredPrivacyPoolService) {
|
|
@@ -1606,7 +2167,8 @@ function poolMerkleStateToCachedView(state) {
|
|
|
1606
2167
|
return {
|
|
1607
2168
|
commitments: state.commitments,
|
|
1608
2169
|
updatedAt: state.updatedAt,
|
|
1609
|
-
merkleRootHex: state.merkleRootHex
|
|
2170
|
+
merkleRootHex: state.merkleRootHex,
|
|
2171
|
+
...state.nodes ? { nodes: state.nodes } : {}
|
|
1610
2172
|
};
|
|
1611
2173
|
}
|
|
1612
2174
|
|
|
@@ -1739,6 +2301,65 @@ function reuseCachedCommitments(input) {
|
|
|
1739
2301
|
return cachedCommitments;
|
|
1740
2302
|
}
|
|
1741
2303
|
|
|
2304
|
+
// src/transact/merkle/persist-fetched.ts
|
|
2305
|
+
function cachedMerkleUnchanged(cachedState, commitments, merkleRootHex) {
|
|
2306
|
+
if (!cachedState) {
|
|
2307
|
+
return false;
|
|
2308
|
+
}
|
|
2309
|
+
if (cachedState.commitments.length !== commitments.length) {
|
|
2310
|
+
return false;
|
|
2311
|
+
}
|
|
2312
|
+
return cachedState.merkleRootHex === merkleRootHex;
|
|
2313
|
+
}
|
|
2314
|
+
function viewFromCachedMerkle(cachedState, merkleRootHex) {
|
|
2315
|
+
return {
|
|
2316
|
+
commitments: cachedState.commitments,
|
|
2317
|
+
updatedAt: cachedState.updatedAt,
|
|
2318
|
+
merkleRootHex: cachedState.merkleRootHex ?? merkleRootHex,
|
|
2319
|
+
commitmentCount: cachedState.commitments.length,
|
|
2320
|
+
...cachedState.nodes ? { nodes: cachedState.nodes } : {}
|
|
2321
|
+
};
|
|
2322
|
+
}
|
|
2323
|
+
function merkleStateForPersist(input) {
|
|
2324
|
+
return {
|
|
2325
|
+
poolContract: input.poolContractId,
|
|
2326
|
+
commitments: input.commitments,
|
|
2327
|
+
commitmentCount: input.commitments.length,
|
|
2328
|
+
merkleRootHex: input.merkleRootHex,
|
|
2329
|
+
updatedAt: input.updatedAt,
|
|
2330
|
+
...input.nodes ? { nodes: input.nodes } : {}
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2333
|
+
async function persistFetchedMerkleState(input) {
|
|
2334
|
+
const cachedState = input.cachedState;
|
|
2335
|
+
if (cachedMerkleUnchanged(cachedState, input.commitments, input.merkleRootHex) && cachedState) {
|
|
2336
|
+
return viewFromCachedMerkle(cachedState, input.merkleRootHex);
|
|
2337
|
+
}
|
|
2338
|
+
const nodes = await resolveExtendedMerkleNodes({
|
|
2339
|
+
poolContract: input.poolContractId,
|
|
2340
|
+
commitments: input.commitments,
|
|
2341
|
+
merkleRootHex: input.merkleRootHex,
|
|
2342
|
+
...cachedState ? { cachedState } : {}
|
|
2343
|
+
});
|
|
2344
|
+
const updatedAt = Date.now();
|
|
2345
|
+
await input.poolMerkleState?.set(
|
|
2346
|
+
merkleStateForPersist({
|
|
2347
|
+
poolContractId: input.poolContractId,
|
|
2348
|
+
commitments: input.commitments,
|
|
2349
|
+
merkleRootHex: input.merkleRootHex,
|
|
2350
|
+
updatedAt,
|
|
2351
|
+
...nodes ? { nodes } : {}
|
|
2352
|
+
})
|
|
2353
|
+
);
|
|
2354
|
+
return {
|
|
2355
|
+
commitments: input.commitments,
|
|
2356
|
+
updatedAt,
|
|
2357
|
+
merkleRootHex: input.merkleRootHex,
|
|
2358
|
+
commitmentCount: input.commitments.length,
|
|
2359
|
+
...nodes ? { nodes } : {}
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2362
|
+
|
|
1742
2363
|
// src/transact/merkle/fetch-contract.ts
|
|
1743
2364
|
async function fetchAndMergeMerkleState(parameters) {
|
|
1744
2365
|
const client = createPoolClient(parameters);
|
|
@@ -1831,43 +2452,6 @@ async function loadCommitments(input) {
|
|
|
1831
2452
|
});
|
|
1832
2453
|
return [...reused, ...fetched];
|
|
1833
2454
|
}
|
|
1834
|
-
async function persistFetchedMerkleState(input) {
|
|
1835
|
-
const cachedState = input.cachedState;
|
|
1836
|
-
if (cachedState && cachedMerkleUnchanged(cachedState, input.commitments, input.merkleRootHex)) {
|
|
1837
|
-
return viewFromCachedMerkle(cachedState, input.merkleRootHex);
|
|
1838
|
-
}
|
|
1839
|
-
const updatedAt = Date.now();
|
|
1840
|
-
await input.poolMerkleState?.set({
|
|
1841
|
-
poolContract: input.poolContractId,
|
|
1842
|
-
commitments: input.commitments,
|
|
1843
|
-
commitmentCount: input.commitments.length,
|
|
1844
|
-
merkleRootHex: input.merkleRootHex,
|
|
1845
|
-
updatedAt
|
|
1846
|
-
});
|
|
1847
|
-
return {
|
|
1848
|
-
commitments: input.commitments,
|
|
1849
|
-
updatedAt,
|
|
1850
|
-
merkleRootHex: input.merkleRootHex,
|
|
1851
|
-
commitmentCount: input.commitments.length
|
|
1852
|
-
};
|
|
1853
|
-
}
|
|
1854
|
-
function viewFromCachedMerkle(cachedState, merkleRootHex) {
|
|
1855
|
-
return {
|
|
1856
|
-
commitments: cachedState.commitments,
|
|
1857
|
-
updatedAt: cachedState.updatedAt,
|
|
1858
|
-
merkleRootHex: cachedState.merkleRootHex ?? merkleRootHex,
|
|
1859
|
-
commitmentCount: cachedState.commitments.length
|
|
1860
|
-
};
|
|
1861
|
-
}
|
|
1862
|
-
function cachedMerkleUnchanged(cachedState, commitments, merkleRootHex) {
|
|
1863
|
-
if (!cachedState) {
|
|
1864
|
-
return false;
|
|
1865
|
-
}
|
|
1866
|
-
if ((cachedState.merkleRootHex ?? merkleRootHex) !== merkleRootHex) {
|
|
1867
|
-
return false;
|
|
1868
|
-
}
|
|
1869
|
-
return cachedState.commitments.join(",") === commitments.join(",");
|
|
1870
|
-
}
|
|
1871
2455
|
|
|
1872
2456
|
// src/transact/engine/prepare/shared.ts
|
|
1873
2457
|
async function resolveTokenContractId2(environment, assetId) {
|
|
@@ -1942,7 +2526,11 @@ async function loadMerkleState(environment, walletPublicKey) {
|
|
|
1942
2526
|
transactEnvironment: environment,
|
|
1943
2527
|
...environment.poolMerkleState ? { poolMerkleState: environment.poolMerkleState } : {}
|
|
1944
2528
|
});
|
|
1945
|
-
return {
|
|
2529
|
+
return merkleSnapshotToStateFile({
|
|
2530
|
+
commitments: merged.commitments,
|
|
2531
|
+
merkleRootHex: merged.merkleRootHex,
|
|
2532
|
+
...merged.nodes ? { nodes: merged.nodes } : {}
|
|
2533
|
+
});
|
|
1946
2534
|
}
|
|
1947
2535
|
function enrichPreparedOperation(prepared, outputRecords, artifacts) {
|
|
1948
2536
|
return {
|
|
@@ -2157,6 +2745,13 @@ async function filterUnspentPrivateRecords(input) {
|
|
|
2157
2745
|
}
|
|
2158
2746
|
return unspent;
|
|
2159
2747
|
}
|
|
2748
|
+
function spendAmountCoveringProtocolFee(amount) {
|
|
2749
|
+
if (amount <= 0n) {
|
|
2750
|
+
return amount;
|
|
2751
|
+
}
|
|
2752
|
+
const hundredths = (amount + 99n) / 100n;
|
|
2753
|
+
return amount + (hundredths === 0n ? 1n : hundredths);
|
|
2754
|
+
}
|
|
2160
2755
|
function pickRecordsForSpendAmount(input) {
|
|
2161
2756
|
let selectedTotal = 0n;
|
|
2162
2757
|
const selected = [];
|
|
@@ -2210,7 +2805,7 @@ async function selectPrivateRecords(input) {
|
|
|
2210
2805
|
return pickRecordsForSpendAmount({
|
|
2211
2806
|
available,
|
|
2212
2807
|
kind: input.kind,
|
|
2213
|
-
amount: input.intent.amount
|
|
2808
|
+
amount: spendAmountCoveringProtocolFee(input.intent.amount)
|
|
2214
2809
|
});
|
|
2215
2810
|
}
|
|
2216
2811
|
function sumRecordAmounts(records) {
|
|
@@ -2444,13 +3039,19 @@ var walletPrivateAddressRecordSchema = z.object({
|
|
|
2444
3039
|
privateAddress: z.string().min(1),
|
|
2445
3040
|
createdAt: z.number()
|
|
2446
3041
|
});
|
|
3042
|
+
var leanImtNodeSchema = z.object({
|
|
3043
|
+
level: z.number().int().nonnegative(),
|
|
3044
|
+
index: z.number().int().nonnegative(),
|
|
3045
|
+
value: z.string().min(1)
|
|
3046
|
+
});
|
|
2447
3047
|
var poolMerkleStateSchema = z.object({
|
|
2448
3048
|
poolContract: z.string().min(1),
|
|
2449
3049
|
commitments: z.array(z.string()),
|
|
2450
3050
|
commitmentCount: z.number().int().nonnegative(),
|
|
2451
3051
|
merkleRootHex: z.string().min(1),
|
|
2452
3052
|
updatedAt: z.number(),
|
|
2453
|
-
syncedLedger: z.number().int().optional()
|
|
3053
|
+
syncedLedger: z.number().int().optional(),
|
|
3054
|
+
nodes: z.array(leanImtNodeSchema).optional()
|
|
2454
3055
|
});
|
|
2455
3056
|
var leafEphemeralSchema = z.object({
|
|
2456
3057
|
poolContract: z.string().min(1),
|
|
@@ -4009,6 +4610,7 @@ function createPoolMerkleService(context) {
|
|
|
4009
4610
|
async appendPoolCommitments(input) {
|
|
4010
4611
|
const current = await this.getPoolMerkleState(input.poolContract);
|
|
4011
4612
|
const mergedCommitments = [...current?.commitments ?? [], ...input.commitments];
|
|
4613
|
+
const nodes = input.nodes ?? (input.commitments.length === 0 ? current?.nodes : void 0);
|
|
4012
4614
|
await this.setPoolMerkleState(
|
|
4013
4615
|
withoutUndefinedFields({
|
|
4014
4616
|
poolContract: input.poolContract,
|
|
@@ -4016,7 +4618,8 @@ function createPoolMerkleService(context) {
|
|
|
4016
4618
|
commitmentCount: mergedCommitments.length,
|
|
4017
4619
|
merkleRootHex: input.merkleRootHex,
|
|
4018
4620
|
updatedAt: Date.now(),
|
|
4019
|
-
syncedLedger: input.syncedLedger ?? current?.syncedLedger
|
|
4621
|
+
syncedLedger: input.syncedLedger ?? current?.syncedLedger,
|
|
4622
|
+
nodes
|
|
4020
4623
|
})
|
|
4021
4624
|
);
|
|
4022
4625
|
}
|
|
@@ -5286,12 +5889,46 @@ function createDeliveriesStateDelegates(state) {
|
|
|
5286
5889
|
};
|
|
5287
5890
|
}
|
|
5288
5891
|
|
|
5892
|
+
// src/transact/merkle/write-snapshot.ts
|
|
5893
|
+
async function writePoolMerkleState(input) {
|
|
5894
|
+
await input.setPoolMerkleState(input.state);
|
|
5895
|
+
await bindPoolMerkleTree(input.state);
|
|
5896
|
+
}
|
|
5897
|
+
async function appendPoolMerkleCommitments(input) {
|
|
5898
|
+
const current = await input.getPoolMerkleState(input.payload.poolContract);
|
|
5899
|
+
const merged = [...current?.commitments ?? [], ...input.payload.commitments];
|
|
5900
|
+
const nodes = input.payload.nodes ?? await resolveExtendedMerkleNodes({
|
|
5901
|
+
poolContract: input.payload.poolContract,
|
|
5902
|
+
commitments: merged,
|
|
5903
|
+
merkleRootHex: input.payload.merkleRootHex,
|
|
5904
|
+
...current ? { cachedState: poolMerkleStateToCachedView(current) } : {}
|
|
5905
|
+
});
|
|
5906
|
+
await input.appendPoolCommitments({
|
|
5907
|
+
poolContract: input.payload.poolContract,
|
|
5908
|
+
commitments: input.payload.commitments,
|
|
5909
|
+
merkleRootHex: input.payload.merkleRootHex,
|
|
5910
|
+
...input.payload.syncedLedger === void 0 ? {} : { syncedLedger: input.payload.syncedLedger },
|
|
5911
|
+
...nodes ? { nodes } : {}
|
|
5912
|
+
});
|
|
5913
|
+
const written = await input.getPoolMerkleState(input.payload.poolContract);
|
|
5914
|
+
if (written) {
|
|
5915
|
+
await bindPoolMerkleTree(written);
|
|
5916
|
+
}
|
|
5917
|
+
}
|
|
5918
|
+
|
|
5289
5919
|
// src/client/state-delegates/pool.ts
|
|
5290
5920
|
function createPoolStateDelegates(state) {
|
|
5291
5921
|
return {
|
|
5292
5922
|
getPoolMerkleState: (poolContract) => state.getPoolMerkleState(poolContract),
|
|
5293
|
-
setPoolMerkleState: (poolState) =>
|
|
5294
|
-
|
|
5923
|
+
setPoolMerkleState: (poolState) => writePoolMerkleState({
|
|
5924
|
+
setPoolMerkleState: (next) => state.setPoolMerkleState(next),
|
|
5925
|
+
state: poolState
|
|
5926
|
+
}),
|
|
5927
|
+
appendPoolCommitments: (input) => appendPoolMerkleCommitments({
|
|
5928
|
+
getPoolMerkleState: (poolContract) => state.getPoolMerkleState(poolContract),
|
|
5929
|
+
appendPoolCommitments: (payload) => state.appendPoolCommitments(payload),
|
|
5930
|
+
payload: input
|
|
5931
|
+
}),
|
|
5295
5932
|
getLeafEphemeral: (input) => state.getLeafEphemeral(input),
|
|
5296
5933
|
setLeafEphemeral: (ephemeral) => state.setLeafEphemeral(ephemeral)
|
|
5297
5934
|
};
|
|
@@ -5344,12 +5981,42 @@ function createStateDelegates(state) {
|
|
|
5344
5981
|
};
|
|
5345
5982
|
}
|
|
5346
5983
|
|
|
5984
|
+
// src/client/hydrate-state.ts
|
|
5985
|
+
async function hydratePoolMerkleStates(client, states) {
|
|
5986
|
+
for (const poolState of states ?? []) {
|
|
5987
|
+
await client.setPoolMerkleState(poolState);
|
|
5988
|
+
}
|
|
5989
|
+
}
|
|
5990
|
+
async function hydrateWalletAddresses(client, snapshot) {
|
|
5991
|
+
for (const record of snapshot.walletPrivateAddressRecords ?? []) {
|
|
5992
|
+
await client.saveWalletPrivateAddressRecord(record);
|
|
5993
|
+
}
|
|
5994
|
+
for (const scalar of snapshot.walletPrivateAddressScalars ?? []) {
|
|
5995
|
+
await client.saveWalletPrivateAddressScalar(scalar);
|
|
5996
|
+
}
|
|
5997
|
+
for (const entry of snapshot.walletDefaultPrivateAddressNonces ?? []) {
|
|
5998
|
+
await client.setWalletDefaultPrivateAddressNonce(entry);
|
|
5999
|
+
}
|
|
6000
|
+
}
|
|
6001
|
+
async function hydrateStellarPrivacyState(client, snapshot) {
|
|
6002
|
+
if (snapshot.assets && snapshot.assets.length > 0) {
|
|
6003
|
+
await client.replaceAssets(snapshot.assets);
|
|
6004
|
+
}
|
|
6005
|
+
await hydratePoolMerkleStates(client, snapshot.poolMerkleStates);
|
|
6006
|
+
if (snapshot.privateRecords && snapshot.privateRecords.length > 0) {
|
|
6007
|
+
await client.upsertPrivateRecords(snapshot.privateRecords);
|
|
6008
|
+
}
|
|
6009
|
+
await hydrateWalletAddresses(client, snapshot);
|
|
6010
|
+
}
|
|
6011
|
+
|
|
5347
6012
|
// src/client/client.ts
|
|
5348
6013
|
function createStellarPrivacyClientInstance(config) {
|
|
5349
6014
|
const composed = composeStellarPrivacyClient(config);
|
|
6015
|
+
const stateDelegates = createStateDelegates(composed.state);
|
|
5350
6016
|
return {
|
|
5351
6017
|
state: composed.state,
|
|
5352
|
-
...
|
|
6018
|
+
...stateDelegates,
|
|
6019
|
+
hydrateState: (snapshot) => hydrateStellarPrivacyState(stateDelegates, snapshot),
|
|
5353
6020
|
deposit: (intent) => composed.operations.deposit(intent),
|
|
5354
6021
|
transfer: (intent) => composed.operations.transfer(intent),
|
|
5355
6022
|
withdraw: (intent) => composed.operations.withdraw(intent),
|
|
@@ -5465,7 +6132,7 @@ function createStellarPrivacyClientFromResolvedConfig(config) {
|
|
|
5465
6132
|
}
|
|
5466
6133
|
|
|
5467
6134
|
// src/transact/engine/default-factory.ts
|
|
5468
|
-
import { PrivacyPoolSDK as
|
|
6135
|
+
import { PrivacyPoolSDK as PrivacyPoolSDK4 } from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
5469
6136
|
|
|
5470
6137
|
// src/transact/pool/proof-types.ts
|
|
5471
6138
|
function ciphertextArtifactsFromProof(proof) {
|
|
@@ -5480,9 +6147,15 @@ function ciphertextArtifactsFromProof(proof) {
|
|
|
5480
6147
|
// src/transact/engine/prepare/deposit.ts
|
|
5481
6148
|
var STROOPS_PER_UNIT = 10000000n;
|
|
5482
6149
|
async function createAlignedDepositWithProof(parameters) {
|
|
6150
|
+
const feeOutput = await quoteFeeOutputForPrepared(parameters);
|
|
6151
|
+
const instructed = parameters.prepared.intent.amount;
|
|
6152
|
+
const userAmount = instructed - (feeOutput?.requiredFee ?? 0n);
|
|
6153
|
+
if (userAmount <= 0n) {
|
|
6154
|
+
throw new Error("Required Fee leaves no spendable deposit note");
|
|
6155
|
+
}
|
|
5483
6156
|
const aligned = await parameters.poolService.createAlignedShieldCoinData({
|
|
5484
6157
|
privateAddressStpl1: parameters.prepared.intent.to,
|
|
5485
|
-
amountStroops:
|
|
6158
|
+
amountStroops: userAmount,
|
|
5486
6159
|
tokenAddress: parameters.tokenAddress
|
|
5487
6160
|
});
|
|
5488
6161
|
const poolClient = readPoolClientFactory(parameters.environment)({
|
|
@@ -5497,7 +6170,9 @@ async function createAlignedDepositWithProof(parameters) {
|
|
|
5497
6170
|
coin: aligned.coin,
|
|
5498
6171
|
depositScalarHex: aligned.depositScalarHex,
|
|
5499
6172
|
merkleRootBytes: merkleTx.result,
|
|
5500
|
-
tokenAddress: parameters.tokenAddress
|
|
6173
|
+
tokenAddress: parameters.tokenAddress,
|
|
6174
|
+
publicDepositStroops: instructed,
|
|
6175
|
+
...feeOutput ? { feeOutput } : {}
|
|
5501
6176
|
});
|
|
5502
6177
|
return { ...aligned, proof };
|
|
5503
6178
|
}
|
|
@@ -5516,8 +6191,8 @@ async function prepareDepositOperation(prepared, environment, poolService) {
|
|
|
5516
6191
|
privateAddress: prepared.intent.to,
|
|
5517
6192
|
assetId: prepared.intent.asset,
|
|
5518
6193
|
poolContract: environment.network.poolContract,
|
|
5519
|
-
amount:
|
|
5520
|
-
amountDisplay: Number(
|
|
6194
|
+
amount: BigInt(depositProof.coin.value),
|
|
6195
|
+
amountDisplay: Number(depositProof.coin.value) / Number(STROOPS_PER_UNIT),
|
|
5521
6196
|
commitmentHex: depositProof.commitment_hex,
|
|
5522
6197
|
coin: depositProof.coin,
|
|
5523
6198
|
depositScalarHex: depositProof.depositScalarHex,
|
|
@@ -5533,7 +6208,11 @@ async function prepareDepositOperation(prepared, environment, poolService) {
|
|
|
5533
6208
|
depositScalarHex: depositProof.depositScalarHex,
|
|
5534
6209
|
precommitementHex: depositProof.precommitementHex,
|
|
5535
6210
|
commitmentHex: depositProof.commitment_hex,
|
|
5536
|
-
walletPublicKey
|
|
6211
|
+
walletPublicKey,
|
|
6212
|
+
zkConfigNonce: zkConfigNonceForFeeBearingKind({
|
|
6213
|
+
kind: "deposit",
|
|
6214
|
+
...configuredNonceSpread(environment.zkConfigNonce)
|
|
6215
|
+
})
|
|
5537
6216
|
});
|
|
5538
6217
|
}
|
|
5539
6218
|
|
|
@@ -5658,7 +6337,8 @@ async function buildSpendProofContextAtExecute(input) {
|
|
|
5658
6337
|
input.prepared.intent.asset
|
|
5659
6338
|
);
|
|
5660
6339
|
const coin = requireCoinNoteFromRecord(primaryRecord);
|
|
5661
|
-
const
|
|
6340
|
+
const merkleState = await loadMerkleState(input.environment, walletPublicKey);
|
|
6341
|
+
const commitments = merkleState.commitments;
|
|
5662
6342
|
const leafIndex = findCommitmentLeafIndex(commitments, coin.commitment);
|
|
5663
6343
|
if (leafIndex < 0) {
|
|
5664
6344
|
throw new Error("Coin commitment not found in on-chain Merkle state.");
|
|
@@ -5675,6 +6355,7 @@ async function buildSpendProofContextAtExecute(input) {
|
|
|
5675
6355
|
tokenAddress,
|
|
5676
6356
|
coin,
|
|
5677
6357
|
commitments,
|
|
6358
|
+
merkleState,
|
|
5678
6359
|
ephemeral,
|
|
5679
6360
|
senderPrivKeyScalarHex,
|
|
5680
6361
|
recipientPrivateAddressStpl1: input.recipientPrivateAddressStpl1
|
|
@@ -5707,9 +6388,6 @@ function escrowOutputFields(input) {
|
|
|
5707
6388
|
recipientLo: input.escrowSend.recipientLo
|
|
5708
6389
|
};
|
|
5709
6390
|
}
|
|
5710
|
-
function paddingDepositPair(recipientDeposit) {
|
|
5711
|
-
return [recipientDeposit, "dummy"];
|
|
5712
|
-
}
|
|
5713
6391
|
async function buildChangeDepositPair(parameters) {
|
|
5714
6392
|
const changeSlot = await getPrivacyPoolService().buildAlignedDepositSlot({
|
|
5715
6393
|
privateAddressStpl1: parameters.selfPrivateAddressStpl1ForChange.trim(),
|
|
@@ -5726,34 +6404,54 @@ async function buildChangeDepositPair(parameters) {
|
|
|
5726
6404
|
}
|
|
5727
6405
|
};
|
|
5728
6406
|
}
|
|
6407
|
+
function recipientOnlyDeposits(recipientDeposit, hasFeeOutput) {
|
|
6408
|
+
if (hasFeeOutput) {
|
|
6409
|
+
return [recipientDeposit];
|
|
6410
|
+
}
|
|
6411
|
+
return [recipientDeposit, "dummy"];
|
|
6412
|
+
}
|
|
6413
|
+
async function depositsWithoutFee(input) {
|
|
6414
|
+
if (input.changeStroops <= ZERO_STROOPS) {
|
|
6415
|
+
return {
|
|
6416
|
+
deposits: recipientOnlyDeposits(input.recipientDeposit, input.hasFeeOutput)
|
|
6417
|
+
};
|
|
6418
|
+
}
|
|
6419
|
+
return buildChangeDepositPair({
|
|
6420
|
+
selfPrivateAddressStpl1ForChange: input.selfPrivateAddressStpl1ForChange,
|
|
6421
|
+
changeStroops: input.changeStroops,
|
|
6422
|
+
tokenAddress: input.tokenAddress,
|
|
6423
|
+
recipientDeposit: input.recipientDeposit
|
|
6424
|
+
});
|
|
6425
|
+
}
|
|
5729
6426
|
async function buildRecipientAndOptionalChangeDeposits(parameters) {
|
|
5730
6427
|
const escrow = {
|
|
5731
6428
|
...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
|
|
5732
6429
|
...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
|
|
5733
6430
|
};
|
|
5734
|
-
const recipientPrivateAddress = parameters.recipientPrivateAddressStpl1.trim();
|
|
5735
6431
|
const recipientSlot = await getPrivacyPoolService().buildAlignedDepositSlot({
|
|
5736
|
-
privateAddressStpl1:
|
|
6432
|
+
privateAddressStpl1: parameters.recipientPrivateAddressStpl1.trim(),
|
|
5737
6433
|
amountStroops: parameters.transferStroops,
|
|
5738
6434
|
tokenAddress: parameters.tokenAddress,
|
|
5739
6435
|
...escrowOutputFields(escrow)
|
|
5740
6436
|
});
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
recipientSlot,
|
|
5744
|
-
deposits: paddingDepositPair(recipientSlot.deposit)
|
|
5745
|
-
};
|
|
5746
|
-
}
|
|
5747
|
-
const changeResult = await buildChangeDepositPair({
|
|
5748
|
-
selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
|
|
6437
|
+
const withoutFee = await depositsWithoutFee({
|
|
6438
|
+
recipientDeposit: recipientSlot.deposit,
|
|
5749
6439
|
changeStroops: parameters.changeStroops,
|
|
6440
|
+
selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
|
|
5750
6441
|
tokenAddress: parameters.tokenAddress,
|
|
5751
|
-
|
|
6442
|
+
hasFeeOutput: (parameters.feeOutput?.requiredFee ?? ZERO_STROOPS) > ZERO_STROOPS
|
|
6443
|
+
});
|
|
6444
|
+
const withFee = await appendFeeOutputSlot({
|
|
6445
|
+
deposits: withoutFee.deposits,
|
|
6446
|
+
tokenAddress: parameters.tokenAddress,
|
|
6447
|
+
buildAlignedDepositSlot: (aligned) => getPrivacyPoolService().buildAlignedDepositSlot(aligned),
|
|
6448
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
5752
6449
|
});
|
|
5753
6450
|
return {
|
|
5754
6451
|
recipientSlot,
|
|
5755
|
-
deposits:
|
|
5756
|
-
changeCoin:
|
|
6452
|
+
deposits: withFee.deposits,
|
|
6453
|
+
..."changeCoin" in withoutFee ? { changeCoin: withoutFee.changeCoin } : {},
|
|
6454
|
+
...withFee.feeCoin ? { feeCoin: withFee.feeCoin } : {}
|
|
5757
6455
|
};
|
|
5758
6456
|
}
|
|
5759
6457
|
|
|
@@ -5806,14 +6504,15 @@ function sweepOutputOwnerFields(parameters) {
|
|
|
5806
6504
|
return { sweepOutputOwnerPubX, sweepOutputOwnerPubY };
|
|
5807
6505
|
}
|
|
5808
6506
|
async function buildTransferDepositsAndPublicInput(parameters) {
|
|
5809
|
-
const { recipientSlot, deposits, changeCoin } = await buildRecipientAndOptionalChangeDeposits({
|
|
6507
|
+
const { recipientSlot, deposits, changeCoin, feeCoin } = await buildRecipientAndOptionalChangeDeposits({
|
|
5810
6508
|
recipientPrivateAddressStpl1: parameters.recipientPrivateAddressStpl1,
|
|
5811
6509
|
transferStroops: parameters.transferStroops,
|
|
5812
6510
|
changeStroops: parameters.changeStroops,
|
|
5813
6511
|
selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
|
|
5814
6512
|
tokenAddress: parameters.tokenAddress,
|
|
5815
6513
|
...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
|
|
5816
|
-
...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
|
|
6514
|
+
...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {},
|
|
6515
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
5817
6516
|
});
|
|
5818
6517
|
const publicInput = withTokenAddressPublicInputs(
|
|
5819
6518
|
{
|
|
@@ -5828,6 +6527,7 @@ async function buildTransferDepositsAndPublicInput(parameters) {
|
|
|
5828
6527
|
recipientSlot,
|
|
5829
6528
|
deposits,
|
|
5830
6529
|
...changeCoin ? { changeCoin } : {},
|
|
6530
|
+
...feeCoin ? { feeCoin } : {},
|
|
5831
6531
|
publicInput
|
|
5832
6532
|
};
|
|
5833
6533
|
}
|
|
@@ -5843,7 +6543,8 @@ async function buildSenderTransferDepositsAndPublicInput(parameters) {
|
|
|
5843
6543
|
parameters.senderPrivKeyScalarHex
|
|
5844
6544
|
),
|
|
5845
6545
|
...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
|
|
5846
|
-
...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
|
|
6546
|
+
...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {},
|
|
6547
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
5847
6548
|
});
|
|
5848
6549
|
}
|
|
5849
6550
|
|
|
@@ -5867,11 +6568,20 @@ function stampDualWithdrawLegs(legs, parameters) {
|
|
|
5867
6568
|
}
|
|
5868
6569
|
};
|
|
5869
6570
|
}
|
|
5870
|
-
function buildDualTransferApplicationIds(sdk, applicationId, changeCoin) {
|
|
6571
|
+
function buildDualTransferApplicationIds(sdk, applicationId, changeCoin, feeCoin) {
|
|
6572
|
+
const outputIds = [applicationId];
|
|
6573
|
+
if (changeCoin) {
|
|
6574
|
+
outputIds.push(applicationId);
|
|
6575
|
+
} else if (!feeCoin) {
|
|
6576
|
+
outputIds.push("0");
|
|
6577
|
+
}
|
|
6578
|
+
if (feeCoin) {
|
|
6579
|
+
outputIds.push(applicationId);
|
|
6580
|
+
}
|
|
5871
6581
|
return buildApplicationIdHints({
|
|
5872
6582
|
sdk,
|
|
5873
6583
|
inputIds: [applicationId, applicationId],
|
|
5874
|
-
outputIds
|
|
6584
|
+
outputIds
|
|
5875
6585
|
});
|
|
5876
6586
|
}
|
|
5877
6587
|
async function proveDualConfidentialTransfer(parameters) {
|
|
@@ -5891,16 +6601,24 @@ async function proveDualConfidentialTransfer(parameters) {
|
|
|
5891
6601
|
audit
|
|
5892
6602
|
);
|
|
5893
6603
|
}
|
|
5894
|
-
|
|
6604
|
+
function dualTransferChangeStroops(parameters) {
|
|
5895
6605
|
const totalNotes = BigInt(parameters.coinA.value) + BigInt(parameters.coinB.value);
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
6606
|
+
if (parameters.transferStroops < MIN_CONFIDENTIAL_TRANSFER_STROOPS) {
|
|
6607
|
+
throw new Error("Transfer amount must be positive");
|
|
6608
|
+
}
|
|
6609
|
+
const changeStroops = remainingAfterRequiredFee({
|
|
6610
|
+
available: totalNotes,
|
|
6611
|
+
instructed: parameters.transferStroops,
|
|
6612
|
+
requiredFee: parameters.feeOutput?.requiredFee ?? 0n
|
|
6613
|
+
});
|
|
5900
6614
|
requireChangeRecipientWhenPartial(
|
|
5901
6615
|
changeStroops,
|
|
5902
6616
|
parameters.selfPrivateAddressStpl1ForChange
|
|
5903
6617
|
);
|
|
6618
|
+
return changeStroops;
|
|
6619
|
+
}
|
|
6620
|
+
async function buildDualTransferProofContext(parameters, applicationId, sdk) {
|
|
6621
|
+
const changeStroops = dualTransferChangeStroops(parameters);
|
|
5904
6622
|
const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
|
|
5905
6623
|
parameters.senderPrivKeyScalarHex
|
|
5906
6624
|
);
|
|
@@ -5927,15 +6645,21 @@ async function buildDualTransferProofContext(parameters, applicationId, sdk) {
|
|
|
5927
6645
|
selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
|
|
5928
6646
|
tokenAddress: parameters.tokenAddress,
|
|
5929
6647
|
stateRoot: legA.witness.stateRoot,
|
|
5930
|
-
...confidentialEscrowFields(parameters)
|
|
6648
|
+
...confidentialEscrowFields(parameters),
|
|
6649
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
5931
6650
|
});
|
|
5932
6651
|
return { legA, legB, applicationId, ...transferInputs };
|
|
5933
6652
|
}
|
|
5934
6653
|
async function prepareConfidentialTransferProofDual(parameters) {
|
|
5935
6654
|
const poolService = getPrivacyPoolService();
|
|
5936
|
-
const sdk = await poolService.getInitializedSdk(
|
|
6655
|
+
const sdk = await poolService.getInitializedSdk(
|
|
6656
|
+
poolService.feeBearingZkConfigNonce({
|
|
6657
|
+
kind: "transfer",
|
|
6658
|
+
...parameters.escrowClaimantLimbs ? { spendSource: "escrow" } : {}
|
|
6659
|
+
})
|
|
6660
|
+
);
|
|
5937
6661
|
const applicationId = poolService.getApplicationId();
|
|
5938
|
-
const { legA, legB, recipientSlot, deposits, changeCoin, publicInput } = await buildDualTransferProofContext(parameters, applicationId, sdk);
|
|
6662
|
+
const { legA, legB, recipientSlot, deposits, changeCoin, feeCoin, publicInput } = await buildDualTransferProofContext(parameters, applicationId, sdk);
|
|
5939
6663
|
const auditPublicKey = poolService.getAuditPublicKey();
|
|
5940
6664
|
const proof = await (auditPublicKey ? proveDualConfidentialTransfer({
|
|
5941
6665
|
sdk,
|
|
@@ -5958,7 +6682,8 @@ async function prepareConfidentialTransferProofDual(parameters) {
|
|
|
5958
6682
|
applicationIdsPlaintext: buildDualTransferApplicationIds(
|
|
5959
6683
|
sdk,
|
|
5960
6684
|
applicationId,
|
|
5961
|
-
changeCoin
|
|
6685
|
+
changeCoin,
|
|
6686
|
+
feeCoin
|
|
5962
6687
|
),
|
|
5963
6688
|
recipientCoin: generatedOutputCoinFromSlot(recipientSlot),
|
|
5964
6689
|
...changeCoin ? { changeCoin } : {}
|
|
@@ -5966,22 +6691,32 @@ async function prepareConfidentialTransferProofDual(parameters) {
|
|
|
5966
6691
|
}
|
|
5967
6692
|
|
|
5968
6693
|
// src/transact/proofs/confidential/single.ts
|
|
5969
|
-
function validateSingleCoinTransferAmounts(transferStroops, noteStroops, selfPrivateAddressStpl1ForChange) {
|
|
6694
|
+
function validateSingleCoinTransferAmounts(transferStroops, noteStroops, selfPrivateAddressStpl1ForChange, requiredFee) {
|
|
5970
6695
|
if (transferStroops < MIN_CONFIDENTIAL_TRANSFER_STROOPS) {
|
|
5971
6696
|
throw new Error("Transfer amount must be positive");
|
|
5972
6697
|
}
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
6698
|
+
const changeStroops = remainingAfterRequiredFee({
|
|
6699
|
+
available: noteStroops,
|
|
6700
|
+
instructed: transferStroops,
|
|
6701
|
+
requiredFee
|
|
6702
|
+
});
|
|
5977
6703
|
requireChangeRecipientWhenPartial(changeStroops, selfPrivateAddressStpl1ForChange);
|
|
5978
6704
|
return changeStroops;
|
|
5979
6705
|
}
|
|
5980
|
-
function buildSingleTransferApplicationIds(sdk, applicationId, changeCoin) {
|
|
6706
|
+
function buildSingleTransferApplicationIds(sdk, applicationId, changeCoin, feeCoin) {
|
|
6707
|
+
const outputIds = [applicationId];
|
|
6708
|
+
if (changeCoin) {
|
|
6709
|
+
outputIds.push(applicationId);
|
|
6710
|
+
} else if (!feeCoin) {
|
|
6711
|
+
outputIds.push("0");
|
|
6712
|
+
}
|
|
6713
|
+
if (feeCoin) {
|
|
6714
|
+
outputIds.push(applicationId);
|
|
6715
|
+
}
|
|
5981
6716
|
return buildApplicationIdHints({
|
|
5982
6717
|
sdk,
|
|
5983
6718
|
inputIds: [applicationId],
|
|
5984
|
-
outputIds
|
|
6719
|
+
outputIds
|
|
5985
6720
|
});
|
|
5986
6721
|
}
|
|
5987
6722
|
function buildTransferAuditParameters(parameters) {
|
|
@@ -6007,11 +6742,25 @@ function confidentialEscrowFields2(input) {
|
|
|
6007
6742
|
...input.escrowClaimantLimbs ? { escrowClaimantLimbs: input.escrowClaimantLimbs } : {}
|
|
6008
6743
|
};
|
|
6009
6744
|
}
|
|
6745
|
+
function transferDepositInputFromProof(input, changeStroops, stateRoot) {
|
|
6746
|
+
return {
|
|
6747
|
+
senderPrivKeyScalarHex: input.senderPrivKeyScalarHex,
|
|
6748
|
+
recipientPrivateAddressStpl1: input.recipientPrivateAddressStpl1,
|
|
6749
|
+
transferStroops: input.transferStroops,
|
|
6750
|
+
changeStroops,
|
|
6751
|
+
selfPrivateAddressStpl1ForChange: input.selfPrivateAddressStpl1ForChange,
|
|
6752
|
+
tokenAddress: input.tokenAddress,
|
|
6753
|
+
stateRoot,
|
|
6754
|
+
...confidentialEscrowFields2(input),
|
|
6755
|
+
...input.feeOutput ? { feeOutput: input.feeOutput } : {}
|
|
6756
|
+
};
|
|
6757
|
+
}
|
|
6010
6758
|
async function buildTransferProofInputs(parameters) {
|
|
6011
6759
|
const changeStroops = validateSingleCoinTransferAmounts(
|
|
6012
6760
|
parameters.input.transferStroops,
|
|
6013
6761
|
parameters.noteStroops,
|
|
6014
|
-
parameters.input.selfPrivateAddressStpl1ForChange
|
|
6762
|
+
parameters.input.selfPrivateAddressStpl1ForChange,
|
|
6763
|
+
parameters.input.feeOutput?.requiredFee ?? 0n
|
|
6015
6764
|
);
|
|
6016
6765
|
const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
|
|
6017
6766
|
parameters.input.senderPrivKeyScalarHex
|
|
@@ -6030,31 +6779,30 @@ async function buildTransferProofInputs(parameters) {
|
|
|
6030
6779
|
withdrawObject,
|
|
6031
6780
|
sweepWithdrawStamp(confidentialEscrowFields2(parameters.input))
|
|
6032
6781
|
);
|
|
6033
|
-
const { recipientSlot, deposits, changeCoin, publicInput } = await buildSenderTransferDepositsAndPublicInput(
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
transferStroops: parameters.input.transferStroops,
|
|
6037
|
-
changeStroops,
|
|
6038
|
-
selfPrivateAddressStpl1ForChange: parameters.input.selfPrivateAddressStpl1ForChange,
|
|
6039
|
-
tokenAddress: parameters.input.tokenAddress,
|
|
6040
|
-
stateRoot: witness.stateRoot,
|
|
6041
|
-
...confidentialEscrowFields2(parameters.input)
|
|
6042
|
-
});
|
|
6782
|
+
const { recipientSlot, deposits, changeCoin, feeCoin, publicInput } = await buildSenderTransferDepositsAndPublicInput(
|
|
6783
|
+
transferDepositInputFromProof(parameters.input, changeStroops, witness.stateRoot)
|
|
6784
|
+
);
|
|
6043
6785
|
return {
|
|
6044
6786
|
witness,
|
|
6045
6787
|
withdrawObject: stampedWithdraw,
|
|
6046
6788
|
recipientSlot,
|
|
6047
6789
|
deposits,
|
|
6048
6790
|
changeCoin,
|
|
6791
|
+
feeCoin,
|
|
6049
6792
|
publicInput
|
|
6050
6793
|
};
|
|
6051
6794
|
}
|
|
6052
6795
|
async function prepareConfidentialTransferProof(parameters) {
|
|
6053
6796
|
const poolService = getPrivacyPoolService();
|
|
6054
|
-
const sdk = await poolService.getInitializedSdk(
|
|
6797
|
+
const sdk = await poolService.getInitializedSdk(
|
|
6798
|
+
poolService.feeBearingZkConfigNonce({
|
|
6799
|
+
kind: "transfer",
|
|
6800
|
+
...parameters.escrowClaimantLimbs ? { spendSource: "escrow" } : {}
|
|
6801
|
+
})
|
|
6802
|
+
);
|
|
6055
6803
|
const applicationId = poolService.getApplicationId();
|
|
6056
6804
|
const noteStroops = BigInt(parameters.coin.value);
|
|
6057
|
-
const { withdrawObject, recipientSlot, deposits, changeCoin, publicInput } = await buildTransferProofInputs({
|
|
6805
|
+
const { withdrawObject, recipientSlot, deposits, changeCoin, feeCoin, publicInput } = await buildTransferProofInputs({
|
|
6058
6806
|
sdk,
|
|
6059
6807
|
applicationId,
|
|
6060
6808
|
input: parameters,
|
|
@@ -6077,7 +6825,8 @@ async function prepareConfidentialTransferProof(parameters) {
|
|
|
6077
6825
|
applicationIdsPlaintext: buildSingleTransferApplicationIds(
|
|
6078
6826
|
sdk,
|
|
6079
6827
|
applicationId,
|
|
6080
|
-
changeCoin
|
|
6828
|
+
changeCoin,
|
|
6829
|
+
feeCoin
|
|
6081
6830
|
),
|
|
6082
6831
|
recipientCoin: generatedOutputCoinFromSlot(recipientSlot),
|
|
6083
6832
|
...changeCoin ? { changeCoin } : {}
|
|
@@ -6100,10 +6849,15 @@ function proofEscrowFields(input) {
|
|
|
6100
6849
|
}
|
|
6101
6850
|
async function buildSingleTransferProofAtExecute(input) {
|
|
6102
6851
|
const context = await buildSpendProofContextAtExecute(input);
|
|
6103
|
-
const
|
|
6852
|
+
const feeOutput = await quoteFeeOutputForPrepared({
|
|
6853
|
+
prepared: input.prepared,
|
|
6854
|
+
environment: input.environment,
|
|
6855
|
+
tokenAddress: context.tokenAddress
|
|
6856
|
+
});
|
|
6857
|
+
const changeStroops = BigInt(context.coin.value) - input.prepared.intent.amount - (feeOutput?.requiredFee ?? 0n);
|
|
6104
6858
|
const proof = await prepareConfidentialTransferProof({
|
|
6105
6859
|
coin: context.coin,
|
|
6106
|
-
state:
|
|
6860
|
+
state: context.merkleState,
|
|
6107
6861
|
senderPrivKeyScalarHex: context.senderPrivKeyScalarHex,
|
|
6108
6862
|
depositorEphemeralKey: serializeEphemeralKeyString({
|
|
6109
6863
|
xHex: context.ephemeral.xHex,
|
|
@@ -6113,7 +6867,8 @@ async function buildSingleTransferProofAtExecute(input) {
|
|
|
6113
6867
|
recipientPrivateAddressStpl1: context.recipientPrivateAddressStpl1,
|
|
6114
6868
|
selfPrivateAddressStpl1ForChange: readChangeRecipient(input, changeStroops),
|
|
6115
6869
|
tokenAddress: context.tokenAddress,
|
|
6116
|
-
...proofEscrowFields(input)
|
|
6870
|
+
...proofEscrowFields(input),
|
|
6871
|
+
...feeOutput ? { feeOutput } : {}
|
|
6117
6872
|
});
|
|
6118
6873
|
return { context, proof };
|
|
6119
6874
|
}
|
|
@@ -6130,11 +6885,16 @@ async function buildDualTransferProofAtExecute(input) {
|
|
|
6130
6885
|
commitments: context.commitments
|
|
6131
6886
|
});
|
|
6132
6887
|
const totalNotes = BigInt(context.coin.value) + BigInt(secondary.coin.value);
|
|
6133
|
-
const
|
|
6888
|
+
const feeOutput = await quoteFeeOutputForPrepared({
|
|
6889
|
+
prepared: input.prepared,
|
|
6890
|
+
environment: input.environment,
|
|
6891
|
+
tokenAddress: context.tokenAddress
|
|
6892
|
+
});
|
|
6893
|
+
const changeStroops = totalNotes - input.prepared.intent.amount - (feeOutput?.requiredFee ?? 0n);
|
|
6134
6894
|
const proof = await prepareConfidentialTransferProofDual({
|
|
6135
6895
|
coinA: context.coin,
|
|
6136
6896
|
coinB: secondary.coin,
|
|
6137
|
-
state:
|
|
6897
|
+
state: context.merkleState,
|
|
6138
6898
|
senderPrivKeyScalarHex: context.senderPrivKeyScalarHex,
|
|
6139
6899
|
ephemeralAKey: serializeEphemeralKeyString({
|
|
6140
6900
|
xHex: context.ephemeral.xHex,
|
|
@@ -6148,7 +6908,8 @@ async function buildDualTransferProofAtExecute(input) {
|
|
|
6148
6908
|
recipientPrivateAddressStpl1: context.recipientPrivateAddressStpl1,
|
|
6149
6909
|
selfPrivateAddressStpl1ForChange: readChangeRecipient(input, changeStroops),
|
|
6150
6910
|
tokenAddress: context.tokenAddress,
|
|
6151
|
-
...proofEscrowFields(input)
|
|
6911
|
+
...proofEscrowFields(input),
|
|
6912
|
+
...feeOutput ? { feeOutput } : {}
|
|
6152
6913
|
});
|
|
6153
6914
|
return { context, proof };
|
|
6154
6915
|
}
|
|
@@ -6280,11 +7041,17 @@ async function runTransferFinalizeSteps(input) {
|
|
|
6280
7041
|
walletPublicKey: input.walletPublicKey,
|
|
6281
7042
|
...recipient.escrowSend ? { escrowSendPrivateAddress: recipient.recipientPrivateAddressStpl1 } : {}
|
|
6282
7043
|
});
|
|
6283
|
-
return
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
7044
|
+
return {
|
|
7045
|
+
...buildTransferFinalizeArtifacts({
|
|
7046
|
+
proof,
|
|
7047
|
+
context,
|
|
7048
|
+
...sweepFinalizeStamp(input.prepared, recipient)
|
|
7049
|
+
}),
|
|
7050
|
+
zkConfigNonce: zkConfigNonceForFeeBearingKind({
|
|
7051
|
+
...feeOutputKindFromPrepared(input.prepared),
|
|
7052
|
+
...configuredNonceSpread(input.environment.zkConfigNonce)
|
|
7053
|
+
})
|
|
7054
|
+
};
|
|
6288
7055
|
}
|
|
6289
7056
|
function sweepArtifactStamp(artifacts) {
|
|
6290
7057
|
return {
|
|
@@ -6312,6 +7079,24 @@ async function finalizeTransferAtExecute(prepared, environment) {
|
|
|
6312
7079
|
return runTransferFinalizeSteps({ prepared, environment, walletPublicKey });
|
|
6313
7080
|
}
|
|
6314
7081
|
|
|
7082
|
+
// src/transact/engine/withdraw-fee.ts
|
|
7083
|
+
async function withdrawFeeProofFields(input) {
|
|
7084
|
+
const feeOutput = await quoteFeeOutputForPrepared({
|
|
7085
|
+
prepared: input.prepared,
|
|
7086
|
+
environment: input.environment,
|
|
7087
|
+
tokenAddress: input.tokenAddress
|
|
7088
|
+
});
|
|
7089
|
+
const changeStroops = remainingAfterRequiredFee({
|
|
7090
|
+
available: input.available,
|
|
7091
|
+
instructed: input.prepared.intent.amount,
|
|
7092
|
+
requiredFee: feeOutput?.requiredFee ?? 0n
|
|
7093
|
+
});
|
|
7094
|
+
return {
|
|
7095
|
+
...feeOutput ? { feeOutput } : {},
|
|
7096
|
+
...changeStroops > 0n ? { changePrivateAddressStpl1: input.withdrawFrom } : {}
|
|
7097
|
+
};
|
|
7098
|
+
}
|
|
7099
|
+
|
|
6315
7100
|
// src/transact/engine/execute.ts
|
|
6316
7101
|
function enrichWithdrawOutputRecords(prepared, proof) {
|
|
6317
7102
|
if (!proof.changeCoin || prepared.outputRecords.length === 0) {
|
|
@@ -6327,7 +7112,7 @@ function enrichWithdrawOutputRecords(prepared, proof) {
|
|
|
6327
7112
|
precommitementHex: changeCoin.precommitementHex
|
|
6328
7113
|
}));
|
|
6329
7114
|
}
|
|
6330
|
-
function buildWithdrawFinalizeArtifacts(proof, context) {
|
|
7115
|
+
function buildWithdrawFinalizeArtifacts(proof, context, environment) {
|
|
6331
7116
|
return {
|
|
6332
7117
|
proofHex: proof.proof_hex,
|
|
6333
7118
|
publicHex: proof.public_hex,
|
|
@@ -6335,7 +7120,11 @@ function buildWithdrawFinalizeArtifacts(proof, context) {
|
|
|
6335
7120
|
applicationIdsPlaintext: proof.applicationIdsPlaintext,
|
|
6336
7121
|
tokenAddress: context.tokenAddress,
|
|
6337
7122
|
walletPublicKey: context.walletPublicKey,
|
|
6338
|
-
executeFinalizeRequired: false
|
|
7123
|
+
executeFinalizeRequired: false,
|
|
7124
|
+
zkConfigNonce: zkConfigNonceForFeeBearingKind({
|
|
7125
|
+
kind: "withdraw",
|
|
7126
|
+
...configuredNonceSpread(environment.zkConfigNonce)
|
|
7127
|
+
})
|
|
6339
7128
|
};
|
|
6340
7129
|
}
|
|
6341
7130
|
async function finalizeSingleWithdrawAtExecute(prepared, environment, poolService, withdrawFrom) {
|
|
@@ -6344,10 +7133,16 @@ async function finalizeSingleWithdrawAtExecute(prepared, environment, poolServic
|
|
|
6344
7133
|
environment,
|
|
6345
7134
|
recipientPrivateAddressStpl1: withdrawFrom
|
|
6346
7135
|
});
|
|
6347
|
-
const
|
|
7136
|
+
const feeFields = await withdrawFeeProofFields({
|
|
7137
|
+
prepared,
|
|
7138
|
+
environment,
|
|
7139
|
+
tokenAddress: context.tokenAddress,
|
|
7140
|
+
available: BigInt(context.coin.value),
|
|
7141
|
+
withdrawFrom
|
|
7142
|
+
});
|
|
6348
7143
|
const proof = await poolService.prepareWithdrawTransactProof({
|
|
6349
7144
|
coin: context.coin,
|
|
6350
|
-
state:
|
|
7145
|
+
state: context.merkleState,
|
|
6351
7146
|
destinationStellarAddress: prepared.intent.to,
|
|
6352
7147
|
privKeyScalarHex: context.senderPrivKeyScalarHex,
|
|
6353
7148
|
depositorEphemeralKey: serializeEphemeralKeyString({
|
|
@@ -6355,11 +7150,24 @@ async function finalizeSingleWithdrawAtExecute(prepared, environment, poolServic
|
|
|
6355
7150
|
yHex: context.ephemeral.yHex
|
|
6356
7151
|
}),
|
|
6357
7152
|
withdrawAmountStroops: prepared.intent.amount,
|
|
6358
|
-
changePrivateAddressStpl1:
|
|
6359
|
-
tokenAddress: context.tokenAddress
|
|
7153
|
+
changePrivateAddressStpl1: feeFields.changePrivateAddressStpl1,
|
|
7154
|
+
tokenAddress: context.tokenAddress,
|
|
7155
|
+
...feeFields.feeOutput ? { feeOutput: feeFields.feeOutput } : {}
|
|
6360
7156
|
});
|
|
6361
7157
|
enrichWithdrawOutputRecords(prepared, proof);
|
|
6362
|
-
return buildWithdrawFinalizeArtifacts(proof, context);
|
|
7158
|
+
return buildWithdrawFinalizeArtifacts(proof, context, environment);
|
|
7159
|
+
}
|
|
7160
|
+
function dualWithdrawEphemeralKeys(input) {
|
|
7161
|
+
return {
|
|
7162
|
+
depositorEphemeralAKey: serializeEphemeralKeyString({
|
|
7163
|
+
xHex: input.context.ephemeral.xHex,
|
|
7164
|
+
yHex: input.context.ephemeral.yHex
|
|
7165
|
+
}),
|
|
7166
|
+
depositorEphemeralBKey: serializeEphemeralKeyString({
|
|
7167
|
+
xHex: input.secondary.ephemeral.xHex,
|
|
7168
|
+
yHex: input.secondary.ephemeral.yHex
|
|
7169
|
+
})
|
|
7170
|
+
};
|
|
6363
7171
|
}
|
|
6364
7172
|
async function finalizeDualWithdrawAtExecute(prepared, environment, poolService, withdrawFrom) {
|
|
6365
7173
|
const [, secondaryRecord] = prepared.consumedRecords;
|
|
@@ -6377,28 +7185,27 @@ async function finalizeDualWithdrawAtExecute(prepared, environment, poolService,
|
|
|
6377
7185
|
walletPublicKey: context.walletPublicKey,
|
|
6378
7186
|
commitments: context.commitments
|
|
6379
7187
|
});
|
|
6380
|
-
const
|
|
6381
|
-
|
|
7188
|
+
const feeFields = await withdrawFeeProofFields({
|
|
7189
|
+
prepared,
|
|
7190
|
+
environment,
|
|
7191
|
+
tokenAddress: context.tokenAddress,
|
|
7192
|
+
available: BigInt(context.coin.value) + BigInt(secondary.coin.value),
|
|
7193
|
+
withdrawFrom
|
|
7194
|
+
});
|
|
6382
7195
|
const proof = await poolService.prepareWithdrawTransactProofDual({
|
|
6383
7196
|
coinA: context.coin,
|
|
6384
7197
|
coinB: secondary.coin,
|
|
6385
|
-
state:
|
|
7198
|
+
state: context.merkleState,
|
|
6386
7199
|
destinationStellarAddress: prepared.intent.to,
|
|
6387
7200
|
privKeyScalarHex: context.senderPrivKeyScalarHex,
|
|
6388
|
-
|
|
6389
|
-
xHex: context.ephemeral.xHex,
|
|
6390
|
-
yHex: context.ephemeral.yHex
|
|
6391
|
-
}),
|
|
6392
|
-
depositorEphemeralBKey: serializeEphemeralKeyString({
|
|
6393
|
-
xHex: secondary.ephemeral.xHex,
|
|
6394
|
-
yHex: secondary.ephemeral.yHex
|
|
6395
|
-
}),
|
|
7201
|
+
...dualWithdrawEphemeralKeys({ context, secondary }),
|
|
6396
7202
|
withdrawAmountStroops: prepared.intent.amount,
|
|
6397
|
-
changePrivateAddressStpl1:
|
|
6398
|
-
tokenAddress: context.tokenAddress
|
|
7203
|
+
changePrivateAddressStpl1: feeFields.changePrivateAddressStpl1,
|
|
7204
|
+
tokenAddress: context.tokenAddress,
|
|
7205
|
+
...feeFields.feeOutput ? { feeOutput: feeFields.feeOutput } : {}
|
|
6399
7206
|
});
|
|
6400
7207
|
enrichWithdrawOutputRecords(prepared, proof);
|
|
6401
|
-
return buildWithdrawFinalizeArtifacts(proof, context);
|
|
7208
|
+
return buildWithdrawFinalizeArtifacts(proof, context, environment);
|
|
6402
7209
|
}
|
|
6403
7210
|
async function finalizeWithdrawAtExecute(prepared, environment, poolService) {
|
|
6404
7211
|
if (prepared.kind !== "withdraw") {
|
|
@@ -6660,7 +7467,7 @@ async function requestKytPassageForPoolInteraction(input) {
|
|
|
6660
7467
|
const applicationId = resolvePoolApplicationId(
|
|
6661
7468
|
input.transactEnvironment.network.applicationId
|
|
6662
7469
|
);
|
|
6663
|
-
const zkConfigNonce = resolveZkConfigNonce(input.transactEnvironment);
|
|
7470
|
+
const zkConfigNonce = input.zkConfigNonce ?? resolveZkConfigNonce(input.transactEnvironment);
|
|
6664
7471
|
const applicationIdsPlaintext = input.applicationIdsPlaintext ?? buildApplicationIdHints2(
|
|
6665
7472
|
applicationId,
|
|
6666
7473
|
layoutForKnownNonce(zkConfigNonce).nAuditSlots
|
|
@@ -6832,6 +7639,10 @@ async function submitSorobanConfidentialTransfer(input) {
|
|
|
6832
7639
|
networkPassphrase: input.networkPassphrase,
|
|
6833
7640
|
sorobanRpcUrl: input.sorobanRpcUrl
|
|
6834
7641
|
});
|
|
7642
|
+
const nonce = transactNonceFromArtifacts(
|
|
7643
|
+
input.zkConfigNonce === void 0 ? void 0 : { zkConfigNonce: input.zkConfigNonce },
|
|
7644
|
+
input.transactEnvironment
|
|
7645
|
+
);
|
|
6835
7646
|
const approval = await requestKytPassageForPoolInteraction({
|
|
6836
7647
|
owner: input.walletPublicKey,
|
|
6837
7648
|
poolContract: input.contractId,
|
|
@@ -6840,6 +7651,7 @@ async function submitSorobanConfidentialTransfer(input) {
|
|
|
6840
7651
|
...input.ciphertextHex ? { ciphertextHex: input.ciphertextHex } : {},
|
|
6841
7652
|
...input.outputNoteEphemeralScalars ? { outputNoteEphemeralScalars: input.outputNoteEphemeralScalars } : {},
|
|
6842
7653
|
...input.applicationIdsPlaintext ? { applicationIdsPlaintext: input.applicationIdsPlaintext } : {},
|
|
7654
|
+
...input.zkConfigNonce === void 0 ? {} : { zkConfigNonce: input.zkConfigNonce },
|
|
6843
7655
|
networkPassphrase: input.networkPassphrase,
|
|
6844
7656
|
sorobanRpcUrl: input.sorobanRpcUrl,
|
|
6845
7657
|
transactEnvironment: input.transactEnvironment
|
|
@@ -6848,7 +7660,7 @@ async function submitSorobanConfidentialTransfer(input) {
|
|
|
6848
7660
|
contractClient: poolClient,
|
|
6849
7661
|
contractId: input.contractId,
|
|
6850
7662
|
from: input.walletPublicKey,
|
|
6851
|
-
nonce
|
|
7663
|
+
nonce,
|
|
6852
7664
|
proofHex: input.proofHex,
|
|
6853
7665
|
publicHex: input.publicHex,
|
|
6854
7666
|
...input.ciphertextHex ? { ciphertextHex: input.ciphertextHex } : {},
|
|
@@ -6879,12 +7691,14 @@ async function submitPreparedDeposit(prepared, environment) {
|
|
|
6879
7691
|
networkPassphrase: environment.network.networkPassphrase,
|
|
6880
7692
|
sorobanRpcUrl: environment.network.rpcUrl
|
|
6881
7693
|
});
|
|
7694
|
+
const nonce = transactNonceFromArtifacts(artifacts, environment);
|
|
6882
7695
|
const approval = await requestKytPassageForPoolInteraction({
|
|
6883
7696
|
owner: artifacts.walletPublicKey,
|
|
6884
7697
|
poolContract: environment.network.poolContract,
|
|
6885
7698
|
proofHex: artifacts.proofHex,
|
|
6886
7699
|
publicHex: artifacts.publicHex,
|
|
6887
7700
|
...optionalInspectCiphertext(artifacts),
|
|
7701
|
+
...artifacts.zkConfigNonce === void 0 ? {} : { zkConfigNonce: artifacts.zkConfigNonce },
|
|
6888
7702
|
networkPassphrase: environment.network.networkPassphrase,
|
|
6889
7703
|
sorobanRpcUrl: environment.network.rpcUrl,
|
|
6890
7704
|
transactEnvironment: environment
|
|
@@ -6893,7 +7707,7 @@ async function submitPreparedDeposit(prepared, environment) {
|
|
|
6893
7707
|
contractClient: poolClient,
|
|
6894
7708
|
contractId: environment.network.poolContract,
|
|
6895
7709
|
from: artifacts.walletPublicKey,
|
|
6896
|
-
nonce
|
|
7710
|
+
nonce,
|
|
6897
7711
|
proofHex: artifacts.proofHex,
|
|
6898
7712
|
publicHex: artifacts.publicHex,
|
|
6899
7713
|
...artifacts.ciphertextHex ? { ciphertextHex: artifacts.ciphertextHex } : {},
|
|
@@ -6914,6 +7728,7 @@ async function submitPreparedPoolTransact(prepared, environment) {
|
|
|
6914
7728
|
proofHex: artifacts.proofHex,
|
|
6915
7729
|
publicHex: artifacts.publicHex,
|
|
6916
7730
|
...optionalInspectCiphertext(artifacts),
|
|
7731
|
+
...artifacts.zkConfigNonce === void 0 ? {} : { zkConfigNonce: artifacts.zkConfigNonce },
|
|
6917
7732
|
networkPassphrase: environment.network.networkPassphrase,
|
|
6918
7733
|
sorobanRpcUrl: environment.network.rpcUrl,
|
|
6919
7734
|
transactEnvironment: environment
|
|
@@ -6969,7 +7784,7 @@ async function privacyPoolInitOptions(assets, transactEnvironment) {
|
|
|
6969
7784
|
};
|
|
6970
7785
|
}
|
|
6971
7786
|
async function createDefaultTransactEngine(assets, transactEnvironment) {
|
|
6972
|
-
await
|
|
7787
|
+
await PrivacyPoolSDK4.init(await privacyPoolInitOptions(assets, transactEnvironment));
|
|
6973
7788
|
if (transactEnvironment) {
|
|
6974
7789
|
configurePrivacyPoolService(
|
|
6975
7790
|
createPrivacyPoolService({
|
|
@@ -7465,6 +8280,7 @@ async function inspectRelayerSweepKyt(input) {
|
|
|
7465
8280
|
...input.prepared.transactArtifacts?.applicationIdsPlaintext ? {
|
|
7466
8281
|
applicationIdsPlaintext: input.prepared.transactArtifacts.applicationIdsPlaintext
|
|
7467
8282
|
} : {},
|
|
8283
|
+
...input.prepared.transactArtifacts?.zkConfigNonce === void 0 ? {} : { zkConfigNonce: input.prepared.transactArtifacts.zkConfigNonce },
|
|
7468
8284
|
networkPassphrase: environment.network.networkPassphrase,
|
|
7469
8285
|
sorobanRpcUrl: environment.network.rpcUrl,
|
|
7470
8286
|
transactEnvironment: environment
|
|
@@ -7477,7 +8293,10 @@ async function simulateSweepAuthEntries(input) {
|
|
|
7477
8293
|
const operation = new Contract(environment.network.poolContract).call(
|
|
7478
8294
|
"transact",
|
|
7479
8295
|
new Address5(input.relayerPublicKey).toScVal(),
|
|
7480
|
-
nativeToScVal2(
|
|
8296
|
+
nativeToScVal2(
|
|
8297
|
+
transactNonceFromArtifacts(input.prepared.transactArtifacts, environment),
|
|
8298
|
+
{ type: "u64" }
|
|
8299
|
+
),
|
|
7481
8300
|
nativeToScVal2(hexToBytes(input.artifacts.proofHex), { type: "bytes" }),
|
|
7482
8301
|
nativeToScVal2(hexToBytes(input.artifacts.publicHex), { type: "bytes" }),
|
|
7483
8302
|
nativeToScVal2(hexToBytes(input.artifacts.ciphertextHex ?? ""), { type: "bytes" }),
|
|
@@ -7514,6 +8333,7 @@ async function unsignedEscrowAuthorizationForSweep(input) {
|
|
|
7514
8333
|
});
|
|
7515
8334
|
const auth = await simulateSweepAuthEntries({
|
|
7516
8335
|
artifacts,
|
|
8336
|
+
prepared: input.prepared,
|
|
7517
8337
|
transactEnvironment: input.transactEnvironment,
|
|
7518
8338
|
relayerPublicKey,
|
|
7519
8339
|
approval
|
|
@@ -7545,15 +8365,15 @@ async function loadDefaultStellarBrowserAssets(options) {
|
|
|
7545
8365
|
}
|
|
7546
8366
|
|
|
7547
8367
|
// src/transact/private-address/temporary-recipient.ts
|
|
7548
|
-
import { PrivacyPoolSDK as
|
|
8368
|
+
import { PrivacyPoolSDK as PrivacyPoolSDK5 } from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
7549
8369
|
var COORDINATE_HEX_LENGTH3 = 64;
|
|
7550
8370
|
async function generateRandomDepositScalarHex() {
|
|
7551
8371
|
await getPrivacyPoolService().getInitializedSdk();
|
|
7552
|
-
return
|
|
8372
|
+
return PrivacyPoolSDK5.generateRandomScalarHex32();
|
|
7553
8373
|
}
|
|
7554
8374
|
async function generateTemporaryRecipientPrivateAddress() {
|
|
7555
8375
|
await getPrivacyPoolService().getInitializedSdk();
|
|
7556
|
-
const temporaryScalarHex =
|
|
8376
|
+
const temporaryScalarHex = PrivacyPoolSDK5.generateRandomScalarHex32();
|
|
7557
8377
|
const sdk = await getPrivacyPoolService().getInitializedSdk();
|
|
7558
8378
|
const point = sdk.ecdhEphemeralPublicKeyFromScalarHex(temporaryScalarHex);
|
|
7559
8379
|
const publicKeyXHex = point.x.padStart(COORDINATE_HEX_LENGTH3, "0");
|
|
@@ -7809,10 +8629,11 @@ function requirePreparedArtifacts(prepared) {
|
|
|
7809
8629
|
};
|
|
7810
8630
|
}
|
|
7811
8631
|
function prepareRelayTransactPackageFromPrepared(input) {
|
|
8632
|
+
const zkConfigNonce = input.zkConfigNonce ?? input.prepared.transactArtifacts?.zkConfigNonce;
|
|
7812
8633
|
return prepareRelayTransactPackage({
|
|
7813
8634
|
poolSelector: input.poolSelector,
|
|
7814
8635
|
...requirePreparedArtifacts(input.prepared),
|
|
7815
|
-
...
|
|
8636
|
+
...zkConfigNonce === void 0 ? {} : { zkConfigNonce },
|
|
7816
8637
|
...input.keyVersionHints ? { keyVersionHints: input.keyVersionHints } : {}
|
|
7817
8638
|
});
|
|
7818
8639
|
}
|
|
@@ -7922,6 +8743,7 @@ function requiredSubmissionMethod(prepared, zkConfigNonce = DEFAULT_ZK_CONFIG_NO
|
|
|
7922
8743
|
return result.method;
|
|
7923
8744
|
}
|
|
7924
8745
|
export {
|
|
8746
|
+
BINDING_ZK_NONCE,
|
|
7925
8747
|
BundledZkCircuit2 as BundledZkCircuit,
|
|
7926
8748
|
COMMITMENT_V2_ZK_NONCE,
|
|
7927
8749
|
DEFAULT_STEALTH_SIGN_NONCE as DEFAULT_PRIVATE_ADDRESS_SIGN_NONCE,
|
|
@@ -7950,6 +8772,7 @@ export {
|
|
|
7950
8772
|
RELAY_TRANSACT_PACKAGE_VERSION_V1,
|
|
7951
8773
|
RELAY_TRANSACT_SIGNAL_PREFIX_BYTES,
|
|
7952
8774
|
RELAY_TRANSACT_SUPPORTED_SIGNAL_COUNT,
|
|
8775
|
+
SIX_BY_SIX_BINDING_ZK_NONCE,
|
|
7953
8776
|
SIX_BY_SIX_ZK_NONCE,
|
|
7954
8777
|
STANDARD_ZK_CONFIG_NONCE,
|
|
7955
8778
|
SUBMISSION_METHOD,
|