@arcanetech/privacy-sdk-stellar 0.5.1 → 0.5.4
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 +40 -10
- package/dist/index.js +971 -335
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +7 -5
- package/dist/node.js +947 -319
- package/dist/node.js.map +1 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/transact/index.d.ts +40 -10
- package/dist/transact/index.js +905 -291
- package/dist/transact/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -454,27 +454,9 @@ function buildPrivateRecordFromDeposit(input) {
|
|
|
454
454
|
|
|
455
455
|
// src/transact/pool/service.ts
|
|
456
456
|
import {
|
|
457
|
-
|
|
458
|
-
decodeDecodedEphemeralKey,
|
|
459
|
-
randomFrDecimal253,
|
|
460
|
-
scalarHexToFrDecimal as scalarHexToFrDecimal2
|
|
457
|
+
decodeDecodedEphemeralKey
|
|
461
458
|
} from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
462
459
|
|
|
463
|
-
// src/transact/merkle/field-decimal.ts
|
|
464
|
-
import { Buffer as Buffer4 } from "buffer";
|
|
465
|
-
var BN254 = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
466
|
-
var MERKLE_ROOT_BYTE_LENGTH = 32;
|
|
467
|
-
var DECIMAL_STRING_RADIX = 10;
|
|
468
|
-
function merkleRootBufferToFrDecimal(root) {
|
|
469
|
-
if (root.length !== MERKLE_ROOT_BYTE_LENGTH) {
|
|
470
|
-
throw new Error(
|
|
471
|
-
`expected ${MERKLE_ROOT_BYTE_LENGTH}-byte merkle root, got ${root.length}`
|
|
472
|
-
);
|
|
473
|
-
}
|
|
474
|
-
const hex = Buffer4.from(root).toString("hex");
|
|
475
|
-
return (BigInt(`0x${hex}`) % BN254).toString(DECIMAL_STRING_RADIX);
|
|
476
|
-
}
|
|
477
|
-
|
|
478
460
|
// src/transact/private-address/codec.ts
|
|
479
461
|
import {
|
|
480
462
|
buildStealthAddressSignMessage,
|
|
@@ -530,18 +512,18 @@ function privateAddressSdk(sdk) {
|
|
|
530
512
|
import { withdrawObjectFromMerkleWitness as withdrawObjectFromMerkleWitness2 } from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
531
513
|
|
|
532
514
|
// src/transact/proofs/transaction-input.ts
|
|
533
|
-
import { Buffer as
|
|
515
|
+
import { Buffer as Buffer5 } from "buffer";
|
|
534
516
|
import { StrKey as StrKey2 } from "@stellar/stellar-sdk";
|
|
535
517
|
|
|
536
518
|
// src/transact/stellar/token-contract.ts
|
|
537
|
-
import { Buffer as
|
|
519
|
+
import { Buffer as Buffer4 } from "buffer";
|
|
538
520
|
import { StrKey } from "@stellar/stellar-sdk";
|
|
539
521
|
var CONTRACT_ID_BYTE_LENGTH = 32;
|
|
540
522
|
var HEX_CHARS_PER_BYTE = 2;
|
|
541
523
|
var CONTRACT_ID_HEX_CHAR_LENGTH = CONTRACT_ID_BYTE_LENGTH * HEX_CHARS_PER_BYTE;
|
|
542
524
|
var CONTRACT_ID_HEX = /^(?:0x)?([0-9a-f]{64})$/i;
|
|
543
525
|
function encodeContractFromHex(hexPayload) {
|
|
544
|
-
return StrKey.encodeContract(
|
|
526
|
+
return StrKey.encodeContract(Buffer4.from(hexPayload, "hex"));
|
|
545
527
|
}
|
|
546
528
|
function normalizeSorobanContractId(raw) {
|
|
547
529
|
const trimmed = raw.trim();
|
|
@@ -574,14 +556,14 @@ var ZERO_PUBLIC_WITHDRAW_ADDRESS = {
|
|
|
574
556
|
var CONTRACT_ADDRESS_HALF_BYTES = 16;
|
|
575
557
|
var CONTRACT_ADDRESS_BYTES = 32;
|
|
576
558
|
function bytes16ToDecimal(bytes) {
|
|
577
|
-
return BigInt(`0x${
|
|
559
|
+
return BigInt(`0x${Buffer5.from(bytes).toString("hex")}`).toString();
|
|
578
560
|
}
|
|
579
561
|
function decimalToBytes16(value) {
|
|
580
562
|
const hex = BigInt(value).toString(16).padStart(CONTRACT_ADDRESS_HALF_BYTES * 2, "0");
|
|
581
563
|
if (hex.length > CONTRACT_ADDRESS_HALF_BYTES * 2) {
|
|
582
564
|
throw new Error("Asset leg does not fit into 16 bytes.");
|
|
583
565
|
}
|
|
584
|
-
return
|
|
566
|
+
return Buffer5.from(hex, "hex");
|
|
585
567
|
}
|
|
586
568
|
function tokenAddressFrParts(tokenAddress) {
|
|
587
569
|
const normalized = resolveTokenContractId(tokenAddress);
|
|
@@ -623,7 +605,7 @@ function tokenAddressToAssetLeg(tokenAddress) {
|
|
|
623
605
|
return [hi, lo];
|
|
624
606
|
}
|
|
625
607
|
function assetLegToTokenAddress(assetHi, assetLo) {
|
|
626
|
-
const payload =
|
|
608
|
+
const payload = Buffer5.concat([decimalToBytes16(assetHi), decimalToBytes16(assetLo)]);
|
|
627
609
|
return StrKey2.encodeContract(payload);
|
|
628
610
|
}
|
|
629
611
|
function buildZeroPublicLegs(publicNInputs = 1, publicNOutputs = 1) {
|
|
@@ -746,14 +728,144 @@ function requireChangeRecipientWhenPartial(changeStroops, selfPrivateAddressStpl
|
|
|
746
728
|
}
|
|
747
729
|
}
|
|
748
730
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
731
|
+
|
|
732
|
+
// src/transact/fees/quote-request-body.ts
|
|
733
|
+
function presentInstructedAmount(amount) {
|
|
734
|
+
const trimmed = amount?.trim() ?? "";
|
|
735
|
+
if (!trimmed || trimmed === "0") {
|
|
736
|
+
return void 0;
|
|
737
|
+
}
|
|
738
|
+
return trimmed;
|
|
739
|
+
}
|
|
740
|
+
function feeQuoteRequestBody(request) {
|
|
741
|
+
const publicDepositAmount = presentInstructedAmount(request.publicDepositAmount);
|
|
742
|
+
const transferInstructedAmount = presentInstructedAmount(
|
|
743
|
+
request.transferInstructedAmount
|
|
744
|
+
);
|
|
745
|
+
const publicWithdrawalAmount = presentInstructedAmount(
|
|
746
|
+
request.publicWithdrawalAmount
|
|
747
|
+
);
|
|
748
|
+
return {
|
|
749
|
+
feeAsset: request.feeAsset,
|
|
750
|
+
spendsNotes: request.spendsNotes,
|
|
751
|
+
...publicDepositAmount === void 0 ? {} : { publicDepositAmount },
|
|
752
|
+
...transferInstructedAmount === void 0 ? {} : { transferInstructedAmount },
|
|
753
|
+
...publicWithdrawalAmount === void 0 ? {} : { publicWithdrawalAmount }
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// src/transact/fees/quote-required-fee.ts
|
|
758
|
+
function quoteHeaders(inspectAuthorization) {
|
|
759
|
+
const token = inspectAuthorization?.trim();
|
|
760
|
+
return {
|
|
761
|
+
"content-type": "application/json",
|
|
762
|
+
...token ? { authorization: `Bearer ${token}` } : {}
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
function parseRequiredFee(raw) {
|
|
766
|
+
const text = `${raw ?? ""}`.trim();
|
|
767
|
+
if (!/^\d+$/u.test(text)) {
|
|
768
|
+
throw new Error("Fee Quote Required Fee must be an integer minor-unit string.");
|
|
769
|
+
}
|
|
770
|
+
return BigInt(text);
|
|
771
|
+
}
|
|
772
|
+
function requireQuoteString(raw, field) {
|
|
773
|
+
const text = `${raw ?? ""}`.trim();
|
|
774
|
+
if (!text) {
|
|
775
|
+
throw new Error(`Fee Quote is missing ${field}.`);
|
|
776
|
+
}
|
|
777
|
+
return text;
|
|
778
|
+
}
|
|
779
|
+
function parseQuotePayload(payload) {
|
|
780
|
+
return {
|
|
781
|
+
requiredFee: parseRequiredFee(payload.requiredFee),
|
|
782
|
+
feeAsset: requireQuoteString(payload.feeAsset, "Fee Asset"),
|
|
783
|
+
feeCollectorPrivateAddress: requireQuoteString(
|
|
784
|
+
payload.feeCollectorPrivateAddress,
|
|
785
|
+
"Fee Collector Private Address"
|
|
786
|
+
),
|
|
787
|
+
feeRate: requireQuoteString(payload.feeRate, "Fee Rate")
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
async function quoteRequiredFee(input) {
|
|
791
|
+
const response = await fetch(
|
|
792
|
+
`${input.transactEnvironment.kyt.apiBaseUrl}/kyt/fees/quote`,
|
|
793
|
+
{
|
|
794
|
+
method: "POST",
|
|
795
|
+
headers: quoteHeaders(input.transactEnvironment.kyt.inspectAuthorization),
|
|
796
|
+
body: JSON.stringify(feeQuoteRequestBody(input.request))
|
|
797
|
+
}
|
|
798
|
+
);
|
|
799
|
+
const payload = await response.json();
|
|
800
|
+
if (!response.ok) {
|
|
801
|
+
throw new Error(`Fee Quote failed: ${JSON.stringify(payload)}`);
|
|
802
|
+
}
|
|
803
|
+
return parseQuotePayload(payload);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// src/transact/fees/should-attach-fee-output.ts
|
|
807
|
+
function shouldAttachFeeOutput(input) {
|
|
808
|
+
if (input.spendSource === "escrow" && input.escrowSend !== true) {
|
|
809
|
+
return false;
|
|
810
|
+
}
|
|
811
|
+
return input.kind === "deposit" || input.kind === "transfer" || input.kind === "withdraw";
|
|
812
|
+
}
|
|
813
|
+
function feeOutputKindFromPrepared(prepared) {
|
|
814
|
+
return {
|
|
815
|
+
kind: prepared.kind,
|
|
816
|
+
...prepared.transactArtifacts?.spendSource ? { spendSource: prepared.transactArtifacts.spendSource } : {},
|
|
817
|
+
...prepared.transactArtifacts?.escrowSend ? { escrowSend: true } : {}
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// src/transact/fees/quote-fee-output-for-prepared.ts
|
|
822
|
+
function instructedMinorUnits(prepared) {
|
|
823
|
+
return prepared.intent.amount.toString();
|
|
824
|
+
}
|
|
825
|
+
function quoteRequestForPrepared(input) {
|
|
826
|
+
const amount = instructedMinorUnits(input.prepared);
|
|
827
|
+
if (input.prepared.kind === "deposit") {
|
|
828
|
+
return {
|
|
829
|
+
feeAsset: input.tokenAddress,
|
|
830
|
+
publicDepositAmount: amount,
|
|
831
|
+
spendsNotes: false
|
|
832
|
+
};
|
|
752
833
|
}
|
|
753
|
-
if (
|
|
754
|
-
|
|
834
|
+
if (input.prepared.kind === "withdraw") {
|
|
835
|
+
return {
|
|
836
|
+
feeAsset: input.tokenAddress,
|
|
837
|
+
publicWithdrawalAmount: amount,
|
|
838
|
+
spendsNotes: true
|
|
839
|
+
};
|
|
755
840
|
}
|
|
756
|
-
return
|
|
841
|
+
return {
|
|
842
|
+
feeAsset: input.tokenAddress,
|
|
843
|
+
transferInstructedAmount: amount,
|
|
844
|
+
spendsNotes: true
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
async function quoteFeeOutputForPrepared(input) {
|
|
848
|
+
if (!shouldAttachFeeOutput(feeOutputKindFromPrepared(input.prepared))) {
|
|
849
|
+
return void 0;
|
|
850
|
+
}
|
|
851
|
+
const quote = await quoteRequiredFee({
|
|
852
|
+
transactEnvironment: input.environment,
|
|
853
|
+
request: quoteRequestForPrepared(input)
|
|
854
|
+
});
|
|
855
|
+
if (quote.requiredFee <= 0n) {
|
|
856
|
+
return void 0;
|
|
857
|
+
}
|
|
858
|
+
return {
|
|
859
|
+
requiredFee: quote.requiredFee,
|
|
860
|
+
feeCollectorPrivateAddress: quote.feeCollectorPrivateAddress
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
function remainingAfterRequiredFee(input) {
|
|
864
|
+
const remaining = input.available - input.instructed - input.requiredFee;
|
|
865
|
+
if (remaining < 0n) {
|
|
866
|
+
throw new Error("Instructed amount and Required Fee exceed available note value");
|
|
867
|
+
}
|
|
868
|
+
return remaining;
|
|
757
869
|
}
|
|
758
870
|
|
|
759
871
|
// src/transact/audit/parameters.ts
|
|
@@ -761,7 +873,7 @@ import {
|
|
|
761
873
|
DEMO_AUDIT_PUBLIC_KEY,
|
|
762
874
|
resolveTransactionAuditParams
|
|
763
875
|
} from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
764
|
-
import { Buffer as
|
|
876
|
+
import { Buffer as Buffer6 } from "buffer";
|
|
765
877
|
var UNCOMPRESSED_PREFIX = "04";
|
|
766
878
|
var UNCOMPRESSED_HEX_LENGTH = 130;
|
|
767
879
|
var XY_HEX_LENGTH = 128;
|
|
@@ -788,7 +900,7 @@ function parseAuditPublicKeyFromEnvHex(raw) {
|
|
|
788
900
|
"Audit public key must be uncompressed 65-byte hex (04 + X + Y) or 64-byte X+Y hex"
|
|
789
901
|
);
|
|
790
902
|
}
|
|
791
|
-
const bytes =
|
|
903
|
+
const bytes = Buffer6.from(payload, "hex");
|
|
792
904
|
const auditPublicKeyXDecimal = BigInt(
|
|
793
905
|
`0x${bytes.subarray(0, X_OFFSET_END).toString("hex")}`
|
|
794
906
|
).toString(DECIMAL_RADIX);
|
|
@@ -810,6 +922,7 @@ function buildPoolTransactionAuditParameters(input) {
|
|
|
810
922
|
input.nAuditSlots
|
|
811
923
|
);
|
|
812
924
|
}
|
|
925
|
+
var DECIMAL_APPLICATION_ID = /^\d+$/u;
|
|
813
926
|
function resolvePoolApplicationId(applicationId) {
|
|
814
927
|
const trimmed = applicationId?.trim();
|
|
815
928
|
if (!trimmed) {
|
|
@@ -817,6 +930,11 @@ function resolvePoolApplicationId(applicationId) {
|
|
|
817
930
|
"Privacy pool applicationId is required. Pass it in client factory config."
|
|
818
931
|
);
|
|
819
932
|
}
|
|
933
|
+
if (!DECIMAL_APPLICATION_ID.test(trimmed)) {
|
|
934
|
+
throw new Error(
|
|
935
|
+
"Privacy pool applicationId must be association.audit_id (decimal Fr), not a UUID or foreignId."
|
|
936
|
+
);
|
|
937
|
+
}
|
|
820
938
|
return trimmed;
|
|
821
939
|
}
|
|
822
940
|
|
|
@@ -825,13 +943,13 @@ import { ed25519PubkeyPayloadHexToWithdrawFrDecimals } from "@arcanetech/stellar
|
|
|
825
943
|
|
|
826
944
|
// src/transact/stellar/account.ts
|
|
827
945
|
import { StrKey as StrKey3 } from "@stellar/stellar-sdk";
|
|
828
|
-
import { Buffer as
|
|
946
|
+
import { Buffer as Buffer7 } from "buffer";
|
|
829
947
|
var MUXED_ACCOUNT_ID_BYTE_LENGTH = 8;
|
|
830
948
|
var ED25519_PUBLIC_KEY_BYTE_LENGTH = 32;
|
|
831
949
|
function ed25519HexFromGAddress(trimmed) {
|
|
832
950
|
try {
|
|
833
951
|
const raw = StrKey3.decodeEd25519PublicKey(trimmed);
|
|
834
|
-
return
|
|
952
|
+
return Buffer7.from(raw).toString("hex");
|
|
835
953
|
} catch {
|
|
836
954
|
return void 0;
|
|
837
955
|
}
|
|
@@ -888,6 +1006,32 @@ function privKeyScalarDecimalFromRecipientScalarHex(hexInput) {
|
|
|
888
1006
|
return canonicalBabyJubScalarFromInteger(value).toString(DECIMAL_RADIX2);
|
|
889
1007
|
}
|
|
890
1008
|
|
|
1009
|
+
// src/transact/fees/append-fee-output.ts
|
|
1010
|
+
function feeCoinFromSlot(slot) {
|
|
1011
|
+
return {
|
|
1012
|
+
commitment_hex: slot.commitment_hex,
|
|
1013
|
+
coin: slot.coin,
|
|
1014
|
+
depositScalarHex: slot.depositScalarHex,
|
|
1015
|
+
precommitementHex: slot.precommitementHex
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
async function appendFeeOutputSlot(input) {
|
|
1019
|
+
const requiredFee = input.feeOutput?.requiredFee ?? ZERO_STROOPS;
|
|
1020
|
+
const collector = input.feeOutput?.feeCollectorPrivateAddress.trim() ?? "";
|
|
1021
|
+
if (requiredFee <= ZERO_STROOPS || !collector) {
|
|
1022
|
+
return { deposits: input.deposits };
|
|
1023
|
+
}
|
|
1024
|
+
const slot = await input.buildAlignedDepositSlot({
|
|
1025
|
+
privateAddressStpl1: collector,
|
|
1026
|
+
amountStroops: requiredFee,
|
|
1027
|
+
tokenAddress: input.tokenAddress
|
|
1028
|
+
});
|
|
1029
|
+
return {
|
|
1030
|
+
deposits: [...input.deposits, slot.deposit],
|
|
1031
|
+
feeCoin: feeCoinFromSlot(slot)
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
|
|
891
1035
|
// src/transact/proofs/withdraw/helpers.ts
|
|
892
1036
|
function destinationWithdrawFrAndScalar(parameters) {
|
|
893
1037
|
const pkHex = ed25519PublicKeyHexFromStellarAccount(
|
|
@@ -942,14 +1086,15 @@ async function resolveWithdrawChangeDeposits(parameters) {
|
|
|
942
1086
|
}
|
|
943
1087
|
};
|
|
944
1088
|
}
|
|
945
|
-
function validateDualWithdrawAmounts(withdrawAmountStroops, totalNotes, changePrivateAddressStpl1) {
|
|
1089
|
+
function validateDualWithdrawAmounts(withdrawAmountStroops, totalNotes, changePrivateAddressStpl1, requiredFee) {
|
|
946
1090
|
if (withdrawAmountStroops < MIN_CONFIDENTIAL_TRANSFER_STROOPS) {
|
|
947
1091
|
throw new Error("Withdraw amount must be positive");
|
|
948
1092
|
}
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1093
|
+
const changeStroops = remainingAfterRequiredFee({
|
|
1094
|
+
available: totalNotes,
|
|
1095
|
+
instructed: withdrawAmountStroops,
|
|
1096
|
+
requiredFee
|
|
1097
|
+
});
|
|
953
1098
|
requireChangeRecipientWhenPartial(changeStroops, changePrivateAddressStpl1);
|
|
954
1099
|
return changeStroops;
|
|
955
1100
|
}
|
|
@@ -962,11 +1107,31 @@ function buildDualWithdrawPublicInput(parameters) {
|
|
|
962
1107
|
publicWithdrawalAmount: parameters.publicWithdrawalAmount
|
|
963
1108
|
});
|
|
964
1109
|
}
|
|
1110
|
+
async function withdrawOutputsWithOptionalFee(parameters) {
|
|
1111
|
+
const { deposits: changeDeposits, changeCoin } = await resolveWithdrawChangeDeposits({
|
|
1112
|
+
changeStroops: parameters.changeStroops,
|
|
1113
|
+
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
1114
|
+
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
1115
|
+
tokenAddress: parameters.tokenAddress
|
|
1116
|
+
});
|
|
1117
|
+
const withFee = await appendFeeOutputSlot({
|
|
1118
|
+
deposits: changeDeposits,
|
|
1119
|
+
tokenAddress: parameters.tokenAddress,
|
|
1120
|
+
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
1121
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1122
|
+
});
|
|
1123
|
+
return {
|
|
1124
|
+
deposits: withFee.deposits,
|
|
1125
|
+
...changeCoin ? { changeCoin } : {},
|
|
1126
|
+
...withFee.feeCoin ? { feeCoin: withFee.feeCoin } : {}
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
965
1129
|
async function prepareDualWithdrawProofInputs(parameters) {
|
|
966
1130
|
const changeStroops = validateDualWithdrawAmounts(
|
|
967
1131
|
parameters.withdrawAmountStroops,
|
|
968
1132
|
BigInt(parameters.coinA.value) + BigInt(parameters.coinB.value),
|
|
969
|
-
parameters.changePrivateAddressStpl1
|
|
1133
|
+
parameters.changePrivateAddressStpl1,
|
|
1134
|
+
parameters.feeOutput?.requiredFee ?? 0n
|
|
970
1135
|
);
|
|
971
1136
|
const { legA, legB } = dualWithdrawLegsWithSharedRoot({
|
|
972
1137
|
sdk: parameters.sdk,
|
|
@@ -981,11 +1146,12 @@ async function prepareDualWithdrawProofInputs(parameters) {
|
|
|
981
1146
|
),
|
|
982
1147
|
applicationId: parameters.applicationId
|
|
983
1148
|
});
|
|
984
|
-
const { deposits, changeCoin } = await
|
|
1149
|
+
const { deposits, changeCoin, feeCoin } = await withdrawOutputsWithOptionalFee({
|
|
985
1150
|
changeStroops,
|
|
986
1151
|
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
987
1152
|
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
988
|
-
tokenAddress: parameters.tokenAddress
|
|
1153
|
+
tokenAddress: parameters.tokenAddress,
|
|
1154
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
989
1155
|
});
|
|
990
1156
|
const publicInput = buildDualWithdrawPublicInput({
|
|
991
1157
|
destinationStellarAddress: parameters.destinationStellarAddress,
|
|
@@ -1004,19 +1170,55 @@ async function prepareDualWithdrawProofInputs(parameters) {
|
|
|
1004
1170
|
audit,
|
|
1005
1171
|
deposits,
|
|
1006
1172
|
withdrawLegs: [legA.withdrawObject, legB.withdrawObject],
|
|
1007
|
-
...changeCoin ? { changeCoin } : {}
|
|
1173
|
+
...changeCoin ? { changeCoin } : {},
|
|
1174
|
+
...feeCoin ? { feeCoin } : {}
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
// src/transact/proofs/withdraw/fee-deposits.ts
|
|
1179
|
+
async function withdrawDepositsWithFee(parameters) {
|
|
1180
|
+
const { deposits, changeCoin } = await resolveWithdrawChangeDeposits({
|
|
1181
|
+
changeStroops: parameters.changeStroops,
|
|
1182
|
+
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
1183
|
+
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
1184
|
+
tokenAddress: parameters.tokenAddress
|
|
1185
|
+
});
|
|
1186
|
+
const withFee = await appendFeeOutputSlot({
|
|
1187
|
+
deposits,
|
|
1188
|
+
tokenAddress: parameters.tokenAddress,
|
|
1189
|
+
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
1190
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1191
|
+
});
|
|
1192
|
+
return {
|
|
1193
|
+
deposits: withFee.deposits,
|
|
1194
|
+
...changeCoin ? { changeCoin } : {},
|
|
1195
|
+
...withFee.feeCoin ? { feeCoin: withFee.feeCoin } : {}
|
|
1008
1196
|
};
|
|
1009
1197
|
}
|
|
1198
|
+
function withdrawOutputApplicationIds(input) {
|
|
1199
|
+
const outputIds = [];
|
|
1200
|
+
if (input.hasChange) {
|
|
1201
|
+
outputIds.push(input.applicationId);
|
|
1202
|
+
}
|
|
1203
|
+
if (input.hasFeeOutput) {
|
|
1204
|
+
outputIds.push(input.applicationId);
|
|
1205
|
+
}
|
|
1206
|
+
if (outputIds.length === 0) {
|
|
1207
|
+
outputIds.push("0");
|
|
1208
|
+
}
|
|
1209
|
+
return outputIds;
|
|
1210
|
+
}
|
|
1010
1211
|
|
|
1011
1212
|
// src/transact/proofs/withdraw/transact-proof.ts
|
|
1012
|
-
function validateSingleWithdrawAmounts(withdrawAmountStroops, noteStroops) {
|
|
1213
|
+
function validateSingleWithdrawAmounts(withdrawAmountStroops, noteStroops, requiredFee) {
|
|
1013
1214
|
if (withdrawAmountStroops < MIN_CONFIDENTIAL_TRANSFER_STROOPS) {
|
|
1014
1215
|
throw new Error("Withdraw amount must be positive");
|
|
1015
1216
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1217
|
+
return remainingAfterRequiredFee({
|
|
1218
|
+
available: noteStroops,
|
|
1219
|
+
instructed: withdrawAmountStroops,
|
|
1220
|
+
requiredFee
|
|
1221
|
+
});
|
|
1020
1222
|
}
|
|
1021
1223
|
async function proveSingleWithdrawTransaction(parameters) {
|
|
1022
1224
|
return parameters.sdk.proveTransaction(
|
|
@@ -1055,7 +1257,8 @@ function buildPrimaryWithdrawForCoin(parameters) {
|
|
|
1055
1257
|
async function prepareSingleWithdrawProofInputs(parameters) {
|
|
1056
1258
|
const changeStroops = validateSingleWithdrawAmounts(
|
|
1057
1259
|
parameters.withdrawAmountStroops,
|
|
1058
|
-
BigInt(parameters.coin.value)
|
|
1260
|
+
BigInt(parameters.coin.value),
|
|
1261
|
+
parameters.feeOutput?.requiredFee ?? 0n
|
|
1059
1262
|
);
|
|
1060
1263
|
const { witness, primaryWithdraw } = buildPrimaryWithdrawForCoin({
|
|
1061
1264
|
sdk: parameters.sdk,
|
|
@@ -1064,11 +1267,12 @@ async function prepareSingleWithdrawProofInputs(parameters) {
|
|
|
1064
1267
|
state: parameters.state,
|
|
1065
1268
|
privKeyScalarHex: parameters.privKeyScalarHex
|
|
1066
1269
|
});
|
|
1067
|
-
const { deposits, changeCoin } = await
|
|
1270
|
+
const { deposits, changeCoin, feeCoin } = await withdrawDepositsWithFee({
|
|
1068
1271
|
changeStroops,
|
|
1069
1272
|
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
1070
1273
|
buildAlignedDepositSlot: parameters.buildAlignedDepositSlot,
|
|
1071
|
-
tokenAddress: parameters.tokenAddress
|
|
1274
|
+
tokenAddress: parameters.tokenAddress,
|
|
1275
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1072
1276
|
});
|
|
1073
1277
|
const publicInput = buildWithdrawPublicInput({
|
|
1074
1278
|
stateRoot: witness.stateRoot,
|
|
@@ -1081,6 +1285,7 @@ async function prepareSingleWithdrawProofInputs(parameters) {
|
|
|
1081
1285
|
primaryWithdraw,
|
|
1082
1286
|
deposits,
|
|
1083
1287
|
changeCoin,
|
|
1288
|
+
feeCoin,
|
|
1084
1289
|
publicInput,
|
|
1085
1290
|
audit: buildPoolTransactionAuditParameters({
|
|
1086
1291
|
applicationId: parameters.applicationId,
|
|
@@ -1090,7 +1295,7 @@ async function prepareSingleWithdrawProofInputs(parameters) {
|
|
|
1090
1295
|
};
|
|
1091
1296
|
}
|
|
1092
1297
|
async function proveWithdrawTransact(parameters) {
|
|
1093
|
-
const { primaryWithdraw, deposits, changeCoin, publicInput, audit } = await prepareSingleWithdrawProofInputs(parameters);
|
|
1298
|
+
const { primaryWithdraw, deposits, changeCoin, feeCoin, publicInput, audit } = await prepareSingleWithdrawProofInputs(parameters);
|
|
1094
1299
|
const proof = await proveSingleWithdrawTransaction({
|
|
1095
1300
|
sdk: parameters.sdk,
|
|
1096
1301
|
publicInput,
|
|
@@ -1105,13 +1310,17 @@ async function proveWithdrawTransact(parameters) {
|
|
|
1105
1310
|
applicationIdsPlaintext: buildApplicationIdHints({
|
|
1106
1311
|
sdk: parameters.sdk,
|
|
1107
1312
|
inputIds: [parameters.applicationId],
|
|
1108
|
-
outputIds:
|
|
1313
|
+
outputIds: withdrawOutputApplicationIds({
|
|
1314
|
+
applicationId: parameters.applicationId,
|
|
1315
|
+
hasChange: Boolean(changeCoin),
|
|
1316
|
+
hasFeeOutput: Boolean(feeCoin)
|
|
1317
|
+
})
|
|
1109
1318
|
}),
|
|
1110
1319
|
...changeCoin ? { changeCoin } : {}
|
|
1111
1320
|
};
|
|
1112
1321
|
}
|
|
1113
1322
|
async function proveWithdrawTransactDual(parameters) {
|
|
1114
|
-
const { publicInput, audit, withdrawLegs, deposits, changeCoin } = await prepareDualWithdrawProofInputs(parameters);
|
|
1323
|
+
const { publicInput, audit, withdrawLegs, deposits, changeCoin, feeCoin } = await prepareDualWithdrawProofInputs(parameters);
|
|
1115
1324
|
const proof = await parameters.sdk.proveTransaction(
|
|
1116
1325
|
publicInput,
|
|
1117
1326
|
padPublicLegsToLayout(
|
|
@@ -1130,7 +1339,11 @@ async function proveWithdrawTransactDual(parameters) {
|
|
|
1130
1339
|
applicationIdsPlaintext: buildApplicationIdHints({
|
|
1131
1340
|
sdk: parameters.sdk,
|
|
1132
1341
|
inputIds: [audit.applicationId, audit.applicationId],
|
|
1133
|
-
outputIds:
|
|
1342
|
+
outputIds: withdrawOutputApplicationIds({
|
|
1343
|
+
applicationId: audit.applicationId,
|
|
1344
|
+
hasChange: Boolean(changeCoin),
|
|
1345
|
+
hasFeeOutput: Boolean(feeCoin)
|
|
1346
|
+
})
|
|
1134
1347
|
}),
|
|
1135
1348
|
...changeCoin ? { changeCoin } : {}
|
|
1136
1349
|
};
|
|
@@ -1154,6 +1367,9 @@ var DEFAULT_ZK_CONFIG_NONCE = BINDING_ZK_NONCE;
|
|
|
1154
1367
|
function resolveZkConfigNonce(transactEnvironment) {
|
|
1155
1368
|
return transactEnvironment.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
|
|
1156
1369
|
}
|
|
1370
|
+
function transactNonceFromArtifacts(artifacts, transactEnvironment) {
|
|
1371
|
+
return artifacts?.zkConfigNonce ?? resolveZkConfigNonce(transactEnvironment);
|
|
1372
|
+
}
|
|
1157
1373
|
|
|
1158
1374
|
// src/transact/zk/browser-artifact-cache.ts
|
|
1159
1375
|
import { ZK_ARTIFACT_VERSION } from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
@@ -1406,6 +1622,122 @@ async function buildAlignedDepositSlotForSdk(sdk, applicationId, parameters) {
|
|
|
1406
1622
|
};
|
|
1407
1623
|
}
|
|
1408
1624
|
|
|
1625
|
+
// src/transact/pool/initialize-sdk.ts
|
|
1626
|
+
import { PrivacyPoolSDK as PrivacyPoolSDK2 } from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
1627
|
+
async function initializePrivacyPoolSdk(input, nonce) {
|
|
1628
|
+
const zkConfigNonce = nonce ?? input.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
|
|
1629
|
+
const zkCircuits = await materializeSelectedZkCircuit(
|
|
1630
|
+
input.zkCircuits,
|
|
1631
|
+
zkConfigNonce,
|
|
1632
|
+
input.zkArtifactBaseUrl
|
|
1633
|
+
);
|
|
1634
|
+
return PrivacyPoolSDK2.init({
|
|
1635
|
+
wasmBinary: input.assets.sdkWasm,
|
|
1636
|
+
zkCircuits,
|
|
1637
|
+
zkConfigNonce,
|
|
1638
|
+
...optionalZkArtifactBaseUrl(input.zkArtifactBaseUrl)
|
|
1639
|
+
});
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
// src/transact/fees/zk-config-nonce-for-kind.ts
|
|
1643
|
+
function configuredNonceSpread(zkConfigNonce) {
|
|
1644
|
+
if (zkConfigNonce === void 0) {
|
|
1645
|
+
return {};
|
|
1646
|
+
}
|
|
1647
|
+
return { configuredNonce: zkConfigNonce };
|
|
1648
|
+
}
|
|
1649
|
+
function zkConfigNonceForFeeBearingKind(input) {
|
|
1650
|
+
if (input.configuredNonce === SIX_BY_SIX_BINDING_ZK_NONCE) {
|
|
1651
|
+
return SIX_BY_SIX_BINDING_ZK_NONCE;
|
|
1652
|
+
}
|
|
1653
|
+
if (input.kind === "transfer" && shouldAttachFeeOutput(input)) {
|
|
1654
|
+
return SIX_BY_SIX_BINDING_ZK_NONCE;
|
|
1655
|
+
}
|
|
1656
|
+
return input.configuredNonce ?? BINDING_ZK_NONCE;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
// src/transact/pool/prepare-deposit-proof.ts
|
|
1660
|
+
import {
|
|
1661
|
+
randomFrDecimal253,
|
|
1662
|
+
scalarHexToFrDecimal as scalarHexToFrDecimal2
|
|
1663
|
+
} from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
1664
|
+
|
|
1665
|
+
// src/transact/merkle/field-decimal.ts
|
|
1666
|
+
import { Buffer as Buffer8 } from "buffer";
|
|
1667
|
+
var BN254 = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
1668
|
+
var MERKLE_ROOT_BYTE_LENGTH = 32;
|
|
1669
|
+
var DECIMAL_STRING_RADIX = 10;
|
|
1670
|
+
function merkleRootBufferToFrDecimal(root) {
|
|
1671
|
+
if (root.length !== MERKLE_ROOT_BYTE_LENGTH) {
|
|
1672
|
+
throw new Error(
|
|
1673
|
+
`expected ${MERKLE_ROOT_BYTE_LENGTH}-byte merkle root, got ${root.length}`
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
const hex = Buffer8.from(root).toString("hex");
|
|
1677
|
+
return (BigInt(`0x${hex}`) % BN254).toString(DECIMAL_STRING_RADIX);
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
// src/transact/pool/prepare-deposit-proof.ts
|
|
1681
|
+
function userDepositSlot(input) {
|
|
1682
|
+
return {
|
|
1683
|
+
value: input.coin.value,
|
|
1684
|
+
nullifier: input.coin.nullifier,
|
|
1685
|
+
ephemeralKeyScalar: scalarHexToFrDecimal2(input.depositScalarHex),
|
|
1686
|
+
asset: [input.coin.asset_hi, input.coin.asset_lo],
|
|
1687
|
+
applicationId: input.applicationId,
|
|
1688
|
+
recipientPublicKeys: recipientPublicKeysDecimalFromPrivateAddress(
|
|
1689
|
+
input.privateAddressStpl1
|
|
1690
|
+
)
|
|
1691
|
+
};
|
|
1692
|
+
}
|
|
1693
|
+
function outputApplicationIds(input) {
|
|
1694
|
+
if (input.hasFeeOutput) {
|
|
1695
|
+
return [input.applicationId, input.applicationId];
|
|
1696
|
+
}
|
|
1697
|
+
return [input.applicationId];
|
|
1698
|
+
}
|
|
1699
|
+
async function proveDepositTransact(input) {
|
|
1700
|
+
const publicDeposit = (input.publicDepositStroops ?? BigInt(input.coin.value)).toString();
|
|
1701
|
+
const withFee = await appendFeeOutputSlot({
|
|
1702
|
+
deposits: [userDepositSlot(input)],
|
|
1703
|
+
tokenAddress: input.tokenAddress,
|
|
1704
|
+
buildAlignedDepositSlot: input.buildAlignedDepositSlot,
|
|
1705
|
+
...input.feeOutput ? { feeOutput: input.feeOutput } : {}
|
|
1706
|
+
});
|
|
1707
|
+
const audit = buildPoolTransactionAuditParameters({
|
|
1708
|
+
applicationId: input.applicationId,
|
|
1709
|
+
nAuditSlots: input.sdk.getLayout().nAuditSlots,
|
|
1710
|
+
...input.auditPublicKey ? { auditPublicKey: input.auditPublicKey } : {}
|
|
1711
|
+
});
|
|
1712
|
+
const proof = await input.sdk.proveTransaction(
|
|
1713
|
+
withTokenAddressPublicInputs(
|
|
1714
|
+
{
|
|
1715
|
+
stateRoot: merkleRootBufferToFrDecimal(input.merkleRootBytes),
|
|
1716
|
+
privKeyScalar: randomFrDecimal253()
|
|
1717
|
+
},
|
|
1718
|
+
input.tokenAddress
|
|
1719
|
+
),
|
|
1720
|
+
padPublicLegsToLayout(
|
|
1721
|
+
input.sdk,
|
|
1722
|
+
buildPublicDepositLegs(input.tokenAddress, publicDeposit)
|
|
1723
|
+
),
|
|
1724
|
+
padWithdrawSlotsToLayout(input.sdk, []),
|
|
1725
|
+
padDepositSlotsToLayout(input.sdk, withFee.deposits),
|
|
1726
|
+
audit
|
|
1727
|
+
);
|
|
1728
|
+
return {
|
|
1729
|
+
...proof,
|
|
1730
|
+
applicationIdsPlaintext: buildApplicationIdHints({
|
|
1731
|
+
sdk: input.sdk,
|
|
1732
|
+
inputIds: [],
|
|
1733
|
+
outputIds: outputApplicationIds({
|
|
1734
|
+
applicationId: input.applicationId,
|
|
1735
|
+
hasFeeOutput: Boolean(withFee.feeCoin)
|
|
1736
|
+
})
|
|
1737
|
+
})
|
|
1738
|
+
};
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1409
1741
|
// src/transact/pool/service.ts
|
|
1410
1742
|
var PrivacyPoolService = class {
|
|
1411
1743
|
constructor(assets, applicationId, auditPublicKey, zkCircuits, zkConfigNonce, zkArtifactBaseUrl) {
|
|
@@ -1422,42 +1754,50 @@ var PrivacyPoolService = class {
|
|
|
1422
1754
|
zkCircuits;
|
|
1423
1755
|
zkConfigNonce;
|
|
1424
1756
|
zkArtifactBaseUrl;
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
async
|
|
1428
|
-
|
|
1429
|
-
|
|
1757
|
+
sdks = /* @__PURE__ */ new Map();
|
|
1758
|
+
initPromises = /* @__PURE__ */ new Map();
|
|
1759
|
+
async getInitializedSdk(nonce) {
|
|
1760
|
+
const zkConfigNonce = nonce ?? this.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
|
|
1761
|
+
const key = zkConfigNonce.toString();
|
|
1762
|
+
const existing = this.sdks.get(key);
|
|
1763
|
+
if (existing) {
|
|
1764
|
+
return existing;
|
|
1430
1765
|
}
|
|
1431
|
-
|
|
1432
|
-
|
|
1766
|
+
const pending = this.initPromises.get(key);
|
|
1767
|
+
if (pending) {
|
|
1768
|
+
return pending;
|
|
1433
1769
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
zkConfigNonce,
|
|
1450
|
-
...optionalZkArtifactBaseUrl(this.zkArtifactBaseUrl)
|
|
1451
|
-
});
|
|
1452
|
-
})();
|
|
1453
|
-
return this.initPromise;
|
|
1770
|
+
const started = this.initializeSdk(zkConfigNonce);
|
|
1771
|
+
this.initPromises.set(key, started);
|
|
1772
|
+
try {
|
|
1773
|
+
const sdk = await started;
|
|
1774
|
+
this.sdks.set(key, sdk);
|
|
1775
|
+
return sdk;
|
|
1776
|
+
} finally {
|
|
1777
|
+
this.initPromises.delete(key);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
feeBearingZkConfigNonce(input) {
|
|
1781
|
+
return zkConfigNonceForFeeBearingKind({
|
|
1782
|
+
...input,
|
|
1783
|
+
...configuredNonceSpread(this.zkConfigNonce)
|
|
1784
|
+
});
|
|
1454
1785
|
}
|
|
1455
|
-
async
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1786
|
+
async initializeSdk(nonce) {
|
|
1787
|
+
if (!this.assets) {
|
|
1788
|
+
throw new Error(
|
|
1789
|
+
"PrivacyPoolService requires browser ZK assets before initialization."
|
|
1790
|
+
);
|
|
1459
1791
|
}
|
|
1460
|
-
return
|
|
1792
|
+
return initializePrivacyPoolSdk(
|
|
1793
|
+
{
|
|
1794
|
+
assets: this.assets,
|
|
1795
|
+
...this.zkCircuits ? { zkCircuits: this.zkCircuits } : {},
|
|
1796
|
+
...this.zkConfigNonce === void 0 ? {} : { zkConfigNonce: this.zkConfigNonce },
|
|
1797
|
+
...optionalZkArtifactBaseUrl(this.zkArtifactBaseUrl)
|
|
1798
|
+
},
|
|
1799
|
+
nonce
|
|
1800
|
+
);
|
|
1461
1801
|
}
|
|
1462
1802
|
getAuditPublicKey() {
|
|
1463
1803
|
return this.auditPublicKey;
|
|
@@ -1490,65 +1830,51 @@ var PrivacyPoolService = class {
|
|
|
1490
1830
|
return { commitment_hex, coin, depositScalarHex, precommitementHex };
|
|
1491
1831
|
}
|
|
1492
1832
|
async prepareDepositTransactProof(parameters) {
|
|
1493
|
-
const sdk = await this.getInitializedSdk(
|
|
1494
|
-
|
|
1495
|
-
const recipientPublicKeys = recipientPublicKeysDecimalFromPrivateAddress(
|
|
1496
|
-
parameters.privateAddressStpl1
|
|
1833
|
+
const sdk = await this.getInitializedSdk(
|
|
1834
|
+
this.feeBearingZkConfigNonce({ kind: "deposit" })
|
|
1497
1835
|
);
|
|
1498
|
-
|
|
1499
|
-
const audit = buildPoolTransactionAuditParameters({
|
|
1500
|
-
applicationId,
|
|
1501
|
-
nAuditSlots: sdk.getLayout().nAuditSlots,
|
|
1502
|
-
...this.auditPublicKey ? { auditPublicKey: this.auditPublicKey } : {}
|
|
1503
|
-
});
|
|
1504
|
-
const deposit = {
|
|
1505
|
-
value: parameters.coin.value,
|
|
1506
|
-
nullifier: parameters.coin.nullifier,
|
|
1507
|
-
ephemeralKeyScalar: scalarHexToFrDecimal2(parameters.depositScalarHex),
|
|
1508
|
-
asset: [parameters.coin.asset_hi, parameters.coin.asset_lo],
|
|
1509
|
-
applicationId,
|
|
1510
|
-
recipientPublicKeys
|
|
1511
|
-
};
|
|
1512
|
-
const publicInput = withTokenAddressPublicInputs(
|
|
1513
|
-
{
|
|
1514
|
-
stateRoot,
|
|
1515
|
-
privKeyScalar: randomFrDecimal253()
|
|
1516
|
-
},
|
|
1517
|
-
parameters.tokenAddress
|
|
1518
|
-
);
|
|
1519
|
-
const proof = await sdk.proveTransaction(
|
|
1520
|
-
publicInput,
|
|
1521
|
-
padPublicLegsToLayout(
|
|
1522
|
-
sdk,
|
|
1523
|
-
buildPublicDepositLegs(parameters.tokenAddress, parameters.coin.value)
|
|
1524
|
-
),
|
|
1525
|
-
padWithdrawSlotsToLayout(sdk, []),
|
|
1526
|
-
padDepositSlotsToLayout(sdk, [deposit]),
|
|
1527
|
-
audit
|
|
1528
|
-
);
|
|
1529
|
-
const applicationIdsPlaintext = buildApplicationIdHints({
|
|
1836
|
+
return proveDepositTransact({
|
|
1530
1837
|
sdk,
|
|
1531
|
-
|
|
1532
|
-
|
|
1838
|
+
applicationId: this.getApplicationId(),
|
|
1839
|
+
privateAddressStpl1: parameters.privateAddressStpl1,
|
|
1840
|
+
coin: parameters.coin,
|
|
1841
|
+
depositScalarHex: parameters.depositScalarHex,
|
|
1842
|
+
merkleRootBytes: parameters.merkleRootBytes,
|
|
1843
|
+
tokenAddress: parameters.tokenAddress,
|
|
1844
|
+
buildAlignedDepositSlot: (input) => this.buildAlignedDepositSlot(input),
|
|
1845
|
+
...this.auditPublicKey ? { auditPublicKey: this.auditPublicKey } : {},
|
|
1846
|
+
...parameters.publicDepositStroops === void 0 ? {} : { publicDepositStroops: parameters.publicDepositStroops },
|
|
1847
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1533
1848
|
});
|
|
1534
|
-
return { ...proof, applicationIdsPlaintext };
|
|
1535
1849
|
}
|
|
1536
1850
|
async calculateNullifierHash(nullifier, privKeyScalar) {
|
|
1537
1851
|
const sdk = await this.getInitializedSdk();
|
|
1538
1852
|
return sdk.calculateNullifierHash(nullifier, privKeyScalar);
|
|
1539
1853
|
}
|
|
1540
1854
|
async prepareWithdrawTransactProof(parameters) {
|
|
1541
|
-
const sdk = await this.getInitializedSdk(
|
|
1855
|
+
const sdk = await this.getInitializedSdk(
|
|
1856
|
+
this.feeBearingZkConfigNonce({ kind: "withdraw" })
|
|
1857
|
+
);
|
|
1542
1858
|
return proveWithdrawTransact({
|
|
1543
1859
|
sdk,
|
|
1544
1860
|
applicationId: this.getApplicationId(),
|
|
1545
1861
|
buildAlignedDepositSlot: (input) => this.buildAlignedDepositSlot(input),
|
|
1546
1862
|
...this.auditPublicKey ? { auditPublicKey: this.auditPublicKey } : {},
|
|
1547
|
-
|
|
1863
|
+
coin: parameters.coin,
|
|
1864
|
+
state: parameters.state,
|
|
1865
|
+
destinationStellarAddress: parameters.destinationStellarAddress,
|
|
1866
|
+
privKeyScalarHex: parameters.privKeyScalarHex,
|
|
1867
|
+
depositorEphemeralKey: parameters.depositorEphemeralKey,
|
|
1868
|
+
withdrawAmountStroops: parameters.withdrawAmountStroops,
|
|
1869
|
+
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
1870
|
+
tokenAddress: parameters.tokenAddress,
|
|
1871
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1548
1872
|
});
|
|
1549
1873
|
}
|
|
1550
1874
|
async prepareWithdrawTransactProofDual(parameters) {
|
|
1551
|
-
const sdk = await this.getInitializedSdk(
|
|
1875
|
+
const sdk = await this.getInitializedSdk(
|
|
1876
|
+
this.feeBearingZkConfigNonce({ kind: "withdraw" })
|
|
1877
|
+
);
|
|
1552
1878
|
return proveWithdrawTransactDual({
|
|
1553
1879
|
sdk,
|
|
1554
1880
|
applicationId: this.getApplicationId(),
|
|
@@ -1563,7 +1889,8 @@ var PrivacyPoolService = class {
|
|
|
1563
1889
|
ephemeralBKey: parameters.depositorEphemeralBKey,
|
|
1564
1890
|
withdrawAmountStroops: parameters.withdrawAmountStroops,
|
|
1565
1891
|
changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
|
|
1566
|
-
tokenAddress: parameters.tokenAddress
|
|
1892
|
+
tokenAddress: parameters.tokenAddress,
|
|
1893
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
1567
1894
|
});
|
|
1568
1895
|
}
|
|
1569
1896
|
};
|
|
@@ -1593,92 +1920,167 @@ function getPrivacyPoolService() {
|
|
|
1593
1920
|
}
|
|
1594
1921
|
|
|
1595
1922
|
// src/transact/merkle/fetch-contract.ts
|
|
1923
|
+
import { Buffer as Buffer12 } from "buffer";
|
|
1924
|
+
|
|
1925
|
+
// src/transact/merkle/state-port.ts
|
|
1926
|
+
function poolMerkleStateToCachedView(state) {
|
|
1927
|
+
return {
|
|
1928
|
+
commitments: state.commitments,
|
|
1929
|
+
updatedAt: state.updatedAt,
|
|
1930
|
+
merkleRootHex: state.merkleRootHex
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
// src/transact/merkle/read-tree-leaves.ts
|
|
1935
|
+
import { Address, xdr } from "@stellar/stellar-sdk";
|
|
1596
1936
|
import { Buffer as Buffer11 } from "buffer";
|
|
1597
1937
|
|
|
1598
1938
|
// src/transact/merkle/encoding.ts
|
|
1599
1939
|
import "buffer";
|
|
1600
1940
|
var FR_ORDER = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001n;
|
|
1601
|
-
function
|
|
1941
|
+
function commitmentBufferToDecimal(buf) {
|
|
1602
1942
|
const hex = buf.toString("hex");
|
|
1603
1943
|
const bigintFromHex = BigInt(`0x${hex}`);
|
|
1604
1944
|
const reduced = bigintFromHex % FR_ORDER;
|
|
1605
1945
|
return reduced.toString();
|
|
1606
1946
|
}
|
|
1607
|
-
function commitmentsBuffersToDecimal(buffers) {
|
|
1608
|
-
return buffers.map((bufferRow) => bufferToDecimal(bufferRow));
|
|
1609
|
-
}
|
|
1610
1947
|
|
|
1611
|
-
// src/transact/merkle/
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
// src/transact/merkle/fetch-contract.ts
|
|
1621
|
-
function normalizeCommitmentBuffers(rawBuffers) {
|
|
1622
|
-
return rawBuffers.map(
|
|
1623
|
-
(bufferRow) => Buffer11.isBuffer(bufferRow) ? bufferRow : Buffer11.from(bufferRow)
|
|
1948
|
+
// src/transact/merkle/read-tree-leaves.ts
|
|
1949
|
+
var TREE_LEAF_LEDGER_BATCH_SIZE = 100;
|
|
1950
|
+
function treeLeafLedgerKey(contractId, leafIndex) {
|
|
1951
|
+
return xdr.LedgerKey.contractData(
|
|
1952
|
+
new xdr.LedgerKeyContractData({
|
|
1953
|
+
contract: new Address(contractId).toScAddress(),
|
|
1954
|
+
key: treeLeafKeyScValue(leafIndex),
|
|
1955
|
+
durability: xdr.ContractDataDurability.persistent()
|
|
1956
|
+
})
|
|
1624
1957
|
);
|
|
1625
1958
|
}
|
|
1626
|
-
function
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
void
|
|
1632
|
-
poolContract: parameters.poolContractId,
|
|
1633
|
-
commitments: parameters.contractCommitments,
|
|
1634
|
-
commitmentCount: parameters.contractCount,
|
|
1635
|
-
merkleRootHex: parameters.merkleRootHex,
|
|
1636
|
-
updatedAt
|
|
1637
|
-
});
|
|
1638
|
-
return {
|
|
1639
|
-
commitments: parameters.contractCommitments,
|
|
1640
|
-
updatedAt,
|
|
1641
|
-
merkleRootHex: parameters.merkleRootHex,
|
|
1642
|
-
commitmentCount: parameters.contractCount
|
|
1643
|
-
};
|
|
1959
|
+
function treeLeafKeyScValue(leafIndex) {
|
|
1960
|
+
return xdr.ScVal.scvVec([xdr.ScVal.scvSymbol("Leaf"), xdr.ScVal.scvU32(leafIndex)]);
|
|
1961
|
+
}
|
|
1962
|
+
function leafIndexFromContractDataKey(key) {
|
|
1963
|
+
if (key.switch() !== xdr.ScValType.scvVec()) {
|
|
1964
|
+
return void 0;
|
|
1644
1965
|
}
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1966
|
+
const fields = key.vec();
|
|
1967
|
+
if (!fields || fields.length !== 2) {
|
|
1968
|
+
return void 0;
|
|
1969
|
+
}
|
|
1970
|
+
const [tag, indexValue] = fields;
|
|
1971
|
+
if (!tag || tag.switch() !== xdr.ScValType.scvSymbol()) {
|
|
1972
|
+
return void 0;
|
|
1973
|
+
}
|
|
1974
|
+
if (tag.sym().toString() !== "Leaf") {
|
|
1975
|
+
return void 0;
|
|
1976
|
+
}
|
|
1977
|
+
if (!indexValue || indexValue.switch() !== xdr.ScValType.scvU32()) {
|
|
1978
|
+
return void 0;
|
|
1979
|
+
}
|
|
1980
|
+
return indexValue.u32();
|
|
1651
1981
|
}
|
|
1652
|
-
|
|
1653
|
-
if (
|
|
1982
|
+
function commitmentBytesFromContractDataValue(value) {
|
|
1983
|
+
if (value.switch() !== xdr.ScValType.scvBytes()) {
|
|
1654
1984
|
return void 0;
|
|
1655
1985
|
}
|
|
1656
|
-
|
|
1657
|
-
|
|
1986
|
+
return Buffer11.from(value.bytes());
|
|
1987
|
+
}
|
|
1988
|
+
async function readTreeLeafCommitments(input) {
|
|
1989
|
+
if (input.startIndex >= input.endIndex) {
|
|
1990
|
+
return [];
|
|
1991
|
+
}
|
|
1992
|
+
const byIndex = await readLeafBuffersByIndex(input);
|
|
1993
|
+
return decimalCommitmentsInRange(byIndex, input.startIndex, input.endIndex);
|
|
1994
|
+
}
|
|
1995
|
+
async function readLeafBuffersByIndex(input) {
|
|
1996
|
+
const keys = ledgerKeysForRange(input.contractId, input.startIndex, input.endIndex);
|
|
1997
|
+
const byIndex = /* @__PURE__ */ new Map();
|
|
1998
|
+
for (const batch of chunkLedgerKeys(keys, TREE_LEAF_LEDGER_BATCH_SIZE)) {
|
|
1999
|
+
const response = await input.reader.getLedgerEntries(...batch);
|
|
2000
|
+
collectLeafBuffers(response.entries, byIndex);
|
|
2001
|
+
}
|
|
2002
|
+
return byIndex;
|
|
2003
|
+
}
|
|
2004
|
+
function ledgerKeysForRange(contractId, startIndex, endIndex) {
|
|
2005
|
+
const keys = [];
|
|
2006
|
+
for (let leafIndex = startIndex; leafIndex < endIndex; leafIndex += 1) {
|
|
2007
|
+
keys.push(treeLeafLedgerKey(contractId, leafIndex));
|
|
2008
|
+
}
|
|
2009
|
+
return keys;
|
|
2010
|
+
}
|
|
2011
|
+
function chunkLedgerKeys(keys, batchSize) {
|
|
2012
|
+
const batches = [];
|
|
2013
|
+
for (let offset = 0; offset < keys.length; offset += batchSize) {
|
|
2014
|
+
batches.push(keys.slice(offset, offset + batchSize));
|
|
2015
|
+
}
|
|
2016
|
+
return batches;
|
|
2017
|
+
}
|
|
2018
|
+
function collectLeafBuffers(entries, byIndex) {
|
|
2019
|
+
for (const entry of entries) {
|
|
2020
|
+
const contractData = entry.val.contractData();
|
|
2021
|
+
const leafIndex = leafIndexFromContractDataKey(contractData.key());
|
|
2022
|
+
const bytes = commitmentBytesFromContractDataValue(contractData.val());
|
|
2023
|
+
if (leafIndex === void 0 || !bytes) {
|
|
2024
|
+
continue;
|
|
2025
|
+
}
|
|
2026
|
+
byIndex.set(leafIndex, bytes);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
function decimalCommitmentsInRange(byIndex, startIndex, endIndex) {
|
|
2030
|
+
const commitments = [];
|
|
2031
|
+
for (let leafIndex = startIndex; leafIndex < endIndex; leafIndex += 1) {
|
|
2032
|
+
const bytes = byIndex.get(leafIndex);
|
|
2033
|
+
if (!bytes) {
|
|
2034
|
+
throw new Error(`Missing Merkle leaf ${String(leafIndex)} in pool storage.`);
|
|
2035
|
+
}
|
|
2036
|
+
commitments.push(commitmentBufferToDecimal(bytes));
|
|
2037
|
+
}
|
|
2038
|
+
return commitments;
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
// src/transact/merkle/reuse-cached-commitments.ts
|
|
2042
|
+
function completeCacheRootMatches(cachedState, merkleRootHex) {
|
|
2043
|
+
const cachedRoot = cachedState?.merkleRootHex;
|
|
2044
|
+
if (cachedRoot === void 0 || cachedRoot === "") {
|
|
2045
|
+
return true;
|
|
2046
|
+
}
|
|
2047
|
+
return cachedRoot === merkleRootHex;
|
|
2048
|
+
}
|
|
2049
|
+
function reuseCachedCommitments(input) {
|
|
2050
|
+
const cachedCommitments = input.cachedState?.commitments ?? [];
|
|
2051
|
+
if (cachedCommitments.length === 0) {
|
|
2052
|
+
return [];
|
|
2053
|
+
}
|
|
2054
|
+
if (cachedCommitments.length > input.onChainCount) {
|
|
2055
|
+
return [];
|
|
2056
|
+
}
|
|
2057
|
+
if (cachedCommitments.length === input.onChainCount) {
|
|
2058
|
+
return completeCacheRootMatches(input.cachedState, input.merkleRootHex) ? cachedCommitments : [];
|
|
2059
|
+
}
|
|
2060
|
+
return cachedCommitments;
|
|
1658
2061
|
}
|
|
2062
|
+
|
|
2063
|
+
// src/transact/merkle/fetch-contract.ts
|
|
1659
2064
|
async function fetchAndMergeMerkleState(parameters) {
|
|
1660
|
-
const client =
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
networkPassphrase: parameters.transactEnvironment.network.networkPassphrase,
|
|
1664
|
-
sorobanRpcUrl: parameters.transactEnvironment.network.rpcUrl
|
|
1665
|
-
});
|
|
1666
|
-
const commitmentsRead = await client.get_commitments();
|
|
1667
|
-
const rawBuffers = commitmentsRead.result;
|
|
1668
|
-
const buffers = normalizeCommitmentBuffers(rawBuffers);
|
|
1669
|
-
const contractCommitments = commitmentsBuffersToDecimal(buffers);
|
|
1670
|
-
const contractCount = contractCommitments.length;
|
|
2065
|
+
const client = createPoolClient(parameters);
|
|
2066
|
+
const countRead = await client.get_commitment_count();
|
|
2067
|
+
const onChainCount = requireCommitmentCount(countRead.result);
|
|
1671
2068
|
const rootRead = await client.get_merkle_root();
|
|
1672
|
-
const
|
|
1673
|
-
const merkleRootHex = Buffer11.from(merkleRootBuffer).toString("hex");
|
|
2069
|
+
const merkleRootHex = merkleRootToHex(rootRead.result);
|
|
1674
2070
|
const cachedState = await readCachedPoolMerkleView(
|
|
1675
2071
|
parameters.poolMerkleState,
|
|
1676
2072
|
parameters.poolContractId
|
|
1677
2073
|
);
|
|
1678
|
-
|
|
2074
|
+
const commitments = await loadCommitments({
|
|
2075
|
+
cachedState,
|
|
2076
|
+
onChainCount,
|
|
2077
|
+
merkleRootHex,
|
|
2078
|
+
rpcUrl: parameters.transactEnvironment.network.rpcUrl,
|
|
2079
|
+
contractId: parameters.poolContractId
|
|
2080
|
+
});
|
|
2081
|
+
return persistFetchedMerkleState({
|
|
1679
2082
|
poolContractId: parameters.poolContractId,
|
|
1680
|
-
|
|
1681
|
-
contractCount,
|
|
2083
|
+
commitments,
|
|
1682
2084
|
merkleRootHex,
|
|
1683
2085
|
cachedState,
|
|
1684
2086
|
...parameters.poolMerkleState ? { poolMerkleState: parameters.poolMerkleState } : {}
|
|
@@ -1692,19 +2094,14 @@ async function readLeafEphemeralHex(parameters) {
|
|
|
1692
2094
|
if (cached?.xHex && cached.yHex) {
|
|
1693
2095
|
return { xHex: cached.xHex, yHex: cached.yHex };
|
|
1694
2096
|
}
|
|
1695
|
-
const client =
|
|
1696
|
-
contractId: parameters.poolContractId,
|
|
1697
|
-
walletPublicKey: parameters.walletPublicKey,
|
|
1698
|
-
networkPassphrase: parameters.transactEnvironment.network.networkPassphrase,
|
|
1699
|
-
sorobanRpcUrl: parameters.transactEnvironment.network.rpcUrl
|
|
1700
|
-
});
|
|
2097
|
+
const client = createPoolClient(parameters);
|
|
1701
2098
|
const read = await client.get_leaf_ephemeral({ leaf_index: parameters.leafIndex });
|
|
1702
2099
|
const coords = read.result;
|
|
1703
2100
|
if (!coords?.x || !coords?.y) {
|
|
1704
2101
|
throw new Error("Missing leaf ephemeral key on contract");
|
|
1705
2102
|
}
|
|
1706
|
-
const xHex =
|
|
1707
|
-
const yHex =
|
|
2103
|
+
const xHex = Buffer12.from(coords.x).toString("hex");
|
|
2104
|
+
const yHex = Buffer12.from(coords.y).toString("hex");
|
|
1708
2105
|
await parameters.leafEphemeral?.set({
|
|
1709
2106
|
poolContract: parameters.poolContractId,
|
|
1710
2107
|
leafIndex: parameters.leafIndex,
|
|
@@ -1714,6 +2111,84 @@ async function readLeafEphemeralHex(parameters) {
|
|
|
1714
2111
|
});
|
|
1715
2112
|
return { xHex, yHex };
|
|
1716
2113
|
}
|
|
2114
|
+
function createPoolClient(parameters) {
|
|
2115
|
+
return readPoolClientFactory(parameters.transactEnvironment)({
|
|
2116
|
+
contractId: parameters.poolContractId,
|
|
2117
|
+
walletPublicKey: parameters.walletPublicKey,
|
|
2118
|
+
networkPassphrase: parameters.transactEnvironment.network.networkPassphrase,
|
|
2119
|
+
sorobanRpcUrl: parameters.transactEnvironment.network.rpcUrl
|
|
2120
|
+
});
|
|
2121
|
+
}
|
|
2122
|
+
function requireCommitmentCount(result) {
|
|
2123
|
+
if (typeof result === "number" && Number.isInteger(result) && result >= 0) {
|
|
2124
|
+
return result;
|
|
2125
|
+
}
|
|
2126
|
+
throw new Error("Pool commitment count is not a non-negative integer.");
|
|
2127
|
+
}
|
|
2128
|
+
function merkleRootToHex(root) {
|
|
2129
|
+
return Buffer12.from(root).toString("hex");
|
|
2130
|
+
}
|
|
2131
|
+
async function readCachedPoolMerkleView(poolMerkleState, poolContractId) {
|
|
2132
|
+
if (!poolMerkleState) {
|
|
2133
|
+
return void 0;
|
|
2134
|
+
}
|
|
2135
|
+
const cached = await poolMerkleState.get(poolContractId);
|
|
2136
|
+
return cached ? poolMerkleStateToCachedView(cached) : void 0;
|
|
2137
|
+
}
|
|
2138
|
+
async function loadCommitments(input) {
|
|
2139
|
+
const reused = reuseCachedCommitments({
|
|
2140
|
+
cachedState: input.cachedState,
|
|
2141
|
+
onChainCount: input.onChainCount,
|
|
2142
|
+
merkleRootHex: input.merkleRootHex
|
|
2143
|
+
});
|
|
2144
|
+
if (reused.length === input.onChainCount) {
|
|
2145
|
+
return reused;
|
|
2146
|
+
}
|
|
2147
|
+
const fetched = await readTreeLeafCommitments({
|
|
2148
|
+
reader: createStellarRpcServer(input.rpcUrl),
|
|
2149
|
+
contractId: input.contractId,
|
|
2150
|
+
startIndex: reused.length,
|
|
2151
|
+
endIndex: input.onChainCount
|
|
2152
|
+
});
|
|
2153
|
+
return [...reused, ...fetched];
|
|
2154
|
+
}
|
|
2155
|
+
async function persistFetchedMerkleState(input) {
|
|
2156
|
+
const cachedState = input.cachedState;
|
|
2157
|
+
if (cachedState && cachedMerkleUnchanged(cachedState, input.commitments, input.merkleRootHex)) {
|
|
2158
|
+
return viewFromCachedMerkle(cachedState, input.merkleRootHex);
|
|
2159
|
+
}
|
|
2160
|
+
const updatedAt = Date.now();
|
|
2161
|
+
await input.poolMerkleState?.set({
|
|
2162
|
+
poolContract: input.poolContractId,
|
|
2163
|
+
commitments: input.commitments,
|
|
2164
|
+
commitmentCount: input.commitments.length,
|
|
2165
|
+
merkleRootHex: input.merkleRootHex,
|
|
2166
|
+
updatedAt
|
|
2167
|
+
});
|
|
2168
|
+
return {
|
|
2169
|
+
commitments: input.commitments,
|
|
2170
|
+
updatedAt,
|
|
2171
|
+
merkleRootHex: input.merkleRootHex,
|
|
2172
|
+
commitmentCount: input.commitments.length
|
|
2173
|
+
};
|
|
2174
|
+
}
|
|
2175
|
+
function viewFromCachedMerkle(cachedState, merkleRootHex) {
|
|
2176
|
+
return {
|
|
2177
|
+
commitments: cachedState.commitments,
|
|
2178
|
+
updatedAt: cachedState.updatedAt,
|
|
2179
|
+
merkleRootHex: cachedState.merkleRootHex ?? merkleRootHex,
|
|
2180
|
+
commitmentCount: cachedState.commitments.length
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
function cachedMerkleUnchanged(cachedState, commitments, merkleRootHex) {
|
|
2184
|
+
if (!cachedState) {
|
|
2185
|
+
return false;
|
|
2186
|
+
}
|
|
2187
|
+
if ((cachedState.merkleRootHex ?? merkleRootHex) !== merkleRootHex) {
|
|
2188
|
+
return false;
|
|
2189
|
+
}
|
|
2190
|
+
return cachedState.commitments.join(",") === commitments.join(",");
|
|
2191
|
+
}
|
|
1717
2192
|
|
|
1718
2193
|
// src/transact/engine/prepare/shared.ts
|
|
1719
2194
|
async function resolveTokenContractId2(environment, assetId) {
|
|
@@ -2003,6 +2478,13 @@ async function filterUnspentPrivateRecords(input) {
|
|
|
2003
2478
|
}
|
|
2004
2479
|
return unspent;
|
|
2005
2480
|
}
|
|
2481
|
+
function spendAmountCoveringProtocolFee(amount) {
|
|
2482
|
+
if (amount <= 0n) {
|
|
2483
|
+
return amount;
|
|
2484
|
+
}
|
|
2485
|
+
const hundredths = (amount + 99n) / 100n;
|
|
2486
|
+
return amount + (hundredths === 0n ? 1n : hundredths);
|
|
2487
|
+
}
|
|
2006
2488
|
function pickRecordsForSpendAmount(input) {
|
|
2007
2489
|
let selectedTotal = 0n;
|
|
2008
2490
|
const selected = [];
|
|
@@ -2056,7 +2538,7 @@ async function selectPrivateRecords(input) {
|
|
|
2056
2538
|
return pickRecordsForSpendAmount({
|
|
2057
2539
|
available,
|
|
2058
2540
|
kind: input.kind,
|
|
2059
|
-
amount: input.intent.amount
|
|
2541
|
+
amount: spendAmountCoveringProtocolFee(input.intent.amount)
|
|
2060
2542
|
});
|
|
2061
2543
|
}
|
|
2062
2544
|
function sumRecordAmounts(records) {
|
|
@@ -4257,7 +4739,7 @@ function createStellarStorageAdapterFromState(state) {
|
|
|
4257
4739
|
}
|
|
4258
4740
|
|
|
4259
4741
|
// src/contracts/registry/registry-domain-service.ts
|
|
4260
|
-
import { Buffer as
|
|
4742
|
+
import { Buffer as Buffer13 } from "buffer";
|
|
4261
4743
|
|
|
4262
4744
|
// src/transact/submit/ttl-preflight.ts
|
|
4263
4745
|
function getNested(source, path) {
|
|
@@ -4306,11 +4788,11 @@ async function runTtlPreflight(assembledTransaction) {
|
|
|
4306
4788
|
// src/contracts/registry/registry-domain-service.ts
|
|
4307
4789
|
var COORDINATE_HEX_LENGTH = 64;
|
|
4308
4790
|
function readCoordinateBytes(value) {
|
|
4309
|
-
if (value instanceof
|
|
4791
|
+
if (value instanceof Buffer13) {
|
|
4310
4792
|
return value;
|
|
4311
4793
|
}
|
|
4312
4794
|
if (value instanceof Uint8Array) {
|
|
4313
|
-
return
|
|
4795
|
+
return Buffer13.from(value);
|
|
4314
4796
|
}
|
|
4315
4797
|
return void 0;
|
|
4316
4798
|
}
|
|
@@ -4349,8 +4831,8 @@ function parseRegistryLookupRecord(result) {
|
|
|
4349
4831
|
return parseOptionSomeRecord(result);
|
|
4350
4832
|
}
|
|
4351
4833
|
function recordToLookupResult(record) {
|
|
4352
|
-
const publicKeyXHex =
|
|
4353
|
-
const publicKeyYHex =
|
|
4834
|
+
const publicKeyXHex = Buffer13.from(record.public_key_x).toString("hex");
|
|
4835
|
+
const publicKeyYHex = Buffer13.from(record.public_key_y).toString("hex");
|
|
4354
4836
|
return {
|
|
4355
4837
|
owner: record.owner,
|
|
4356
4838
|
status: "registered",
|
|
@@ -4393,8 +4875,8 @@ async function registerPrivateAddressOnChain(input) {
|
|
|
4393
4875
|
});
|
|
4394
4876
|
const assembled = await client.register_private_address({
|
|
4395
4877
|
owner: input.owner.trim(),
|
|
4396
|
-
public_key_x:
|
|
4397
|
-
public_key_y:
|
|
4878
|
+
public_key_x: Buffer13.from(decoded.x.padStart(COORDINATE_HEX_LENGTH, "0"), "hex"),
|
|
4879
|
+
public_key_y: Buffer13.from(decoded.y.padStart(COORDINATE_HEX_LENGTH, "0"), "hex")
|
|
4398
4880
|
});
|
|
4399
4881
|
await runTtlPreflight(assembled);
|
|
4400
4882
|
const sent = await assembled.signAndSend();
|
|
@@ -4409,7 +4891,7 @@ async function registerPrivateAddressOnChain(input) {
|
|
|
4409
4891
|
import { StrKey as StrKey5 } from "@stellar/stellar-sdk";
|
|
4410
4892
|
|
|
4411
4893
|
// src/transact/escrow/derived-escrow-recipient.ts
|
|
4412
|
-
import { Buffer as
|
|
4894
|
+
import { Buffer as Buffer14 } from "buffer";
|
|
4413
4895
|
import { StrKey as StrKey4 } from "@stellar/stellar-sdk";
|
|
4414
4896
|
import {
|
|
4415
4897
|
derivedEscrowKey,
|
|
@@ -4419,7 +4901,7 @@ import {
|
|
|
4419
4901
|
var COORDINATE_HEX_LENGTH2 = 64;
|
|
4420
4902
|
function stellarAccountToFieldLimbs(stellarAddress) {
|
|
4421
4903
|
const pkRaw = StrKey4.decodeEd25519PublicKey(stellarAddress.trim());
|
|
4422
|
-
const pkHex =
|
|
4904
|
+
const pkHex = Buffer14.from(pkRaw).toString("hex");
|
|
4423
4905
|
const { hi, lo } = ed25519PubkeyPayloadHexToWithdrawFrDecimals2(pkHex);
|
|
4424
4906
|
return { recipientHi: hi, recipientLo: lo };
|
|
4425
4907
|
}
|
|
@@ -4504,7 +4986,7 @@ async function resolveTransferRecipientFromChain(input) {
|
|
|
4504
4986
|
import { Api } from "@stellar/stellar-sdk/rpc";
|
|
4505
4987
|
|
|
4506
4988
|
// src/rpc/soroban-transaction-meta.ts
|
|
4507
|
-
import { Address, StrKey as StrKey6 } from "@stellar/stellar-sdk";
|
|
4989
|
+
import { Address as Address2, StrKey as StrKey6 } from "@stellar/stellar-sdk";
|
|
4508
4990
|
var BIGINT_SHIFT_64 = 64n;
|
|
4509
4991
|
var TRANSACTION_META_SWITCH_SOROBAN_V3 = 3;
|
|
4510
4992
|
var TRANSACTION_META_SWITCH_SOROBAN_V4 = 4;
|
|
@@ -4604,8 +5086,8 @@ function transferPartyAddressesFromTopics(topics) {
|
|
|
4604
5086
|
return void 0;
|
|
4605
5087
|
}
|
|
4606
5088
|
return {
|
|
4607
|
-
from:
|
|
4608
|
-
to:
|
|
5089
|
+
from: Address2.fromScVal(fromTopic).toString(),
|
|
5090
|
+
to: Address2.fromScVal(toTopic).toString()
|
|
4609
5091
|
};
|
|
4610
5092
|
} catch {
|
|
4611
5093
|
return void 0;
|
|
@@ -5311,7 +5793,7 @@ function createStellarPrivacyClientFromResolvedConfig(config) {
|
|
|
5311
5793
|
}
|
|
5312
5794
|
|
|
5313
5795
|
// src/transact/engine/default-factory.ts
|
|
5314
|
-
import { PrivacyPoolSDK as
|
|
5796
|
+
import { PrivacyPoolSDK as PrivacyPoolSDK4 } from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
5315
5797
|
|
|
5316
5798
|
// src/transact/pool/proof-types.ts
|
|
5317
5799
|
function ciphertextArtifactsFromProof(proof) {
|
|
@@ -5326,9 +5808,15 @@ function ciphertextArtifactsFromProof(proof) {
|
|
|
5326
5808
|
// src/transact/engine/prepare/deposit.ts
|
|
5327
5809
|
var STROOPS_PER_UNIT = 10000000n;
|
|
5328
5810
|
async function createAlignedDepositWithProof(parameters) {
|
|
5811
|
+
const feeOutput = await quoteFeeOutputForPrepared(parameters);
|
|
5812
|
+
const instructed = parameters.prepared.intent.amount;
|
|
5813
|
+
const userAmount = instructed - (feeOutput?.requiredFee ?? 0n);
|
|
5814
|
+
if (userAmount <= 0n) {
|
|
5815
|
+
throw new Error("Required Fee leaves no spendable deposit note");
|
|
5816
|
+
}
|
|
5329
5817
|
const aligned = await parameters.poolService.createAlignedShieldCoinData({
|
|
5330
5818
|
privateAddressStpl1: parameters.prepared.intent.to,
|
|
5331
|
-
amountStroops:
|
|
5819
|
+
amountStroops: userAmount,
|
|
5332
5820
|
tokenAddress: parameters.tokenAddress
|
|
5333
5821
|
});
|
|
5334
5822
|
const poolClient = readPoolClientFactory(parameters.environment)({
|
|
@@ -5343,7 +5831,9 @@ async function createAlignedDepositWithProof(parameters) {
|
|
|
5343
5831
|
coin: aligned.coin,
|
|
5344
5832
|
depositScalarHex: aligned.depositScalarHex,
|
|
5345
5833
|
merkleRootBytes: merkleTx.result,
|
|
5346
|
-
tokenAddress: parameters.tokenAddress
|
|
5834
|
+
tokenAddress: parameters.tokenAddress,
|
|
5835
|
+
publicDepositStroops: instructed,
|
|
5836
|
+
...feeOutput ? { feeOutput } : {}
|
|
5347
5837
|
});
|
|
5348
5838
|
return { ...aligned, proof };
|
|
5349
5839
|
}
|
|
@@ -5362,8 +5852,8 @@ async function prepareDepositOperation(prepared, environment, poolService) {
|
|
|
5362
5852
|
privateAddress: prepared.intent.to,
|
|
5363
5853
|
assetId: prepared.intent.asset,
|
|
5364
5854
|
poolContract: environment.network.poolContract,
|
|
5365
|
-
amount:
|
|
5366
|
-
amountDisplay: Number(
|
|
5855
|
+
amount: BigInt(depositProof.coin.value),
|
|
5856
|
+
amountDisplay: Number(depositProof.coin.value) / Number(STROOPS_PER_UNIT),
|
|
5367
5857
|
commitmentHex: depositProof.commitment_hex,
|
|
5368
5858
|
coin: depositProof.coin,
|
|
5369
5859
|
depositScalarHex: depositProof.depositScalarHex,
|
|
@@ -5379,7 +5869,11 @@ async function prepareDepositOperation(prepared, environment, poolService) {
|
|
|
5379
5869
|
depositScalarHex: depositProof.depositScalarHex,
|
|
5380
5870
|
precommitementHex: depositProof.precommitementHex,
|
|
5381
5871
|
commitmentHex: depositProof.commitment_hex,
|
|
5382
|
-
walletPublicKey
|
|
5872
|
+
walletPublicKey,
|
|
5873
|
+
zkConfigNonce: zkConfigNonceForFeeBearingKind({
|
|
5874
|
+
kind: "deposit",
|
|
5875
|
+
...configuredNonceSpread(environment.zkConfigNonce)
|
|
5876
|
+
})
|
|
5383
5877
|
});
|
|
5384
5878
|
}
|
|
5385
5879
|
|
|
@@ -5553,9 +6047,6 @@ function escrowOutputFields(input) {
|
|
|
5553
6047
|
recipientLo: input.escrowSend.recipientLo
|
|
5554
6048
|
};
|
|
5555
6049
|
}
|
|
5556
|
-
function paddingDepositPair(recipientDeposit) {
|
|
5557
|
-
return [recipientDeposit, "dummy"];
|
|
5558
|
-
}
|
|
5559
6050
|
async function buildChangeDepositPair(parameters) {
|
|
5560
6051
|
const changeSlot = await getPrivacyPoolService().buildAlignedDepositSlot({
|
|
5561
6052
|
privateAddressStpl1: parameters.selfPrivateAddressStpl1ForChange.trim(),
|
|
@@ -5572,34 +6063,54 @@ async function buildChangeDepositPair(parameters) {
|
|
|
5572
6063
|
}
|
|
5573
6064
|
};
|
|
5574
6065
|
}
|
|
6066
|
+
function recipientOnlyDeposits(recipientDeposit, hasFeeOutput) {
|
|
6067
|
+
if (hasFeeOutput) {
|
|
6068
|
+
return [recipientDeposit];
|
|
6069
|
+
}
|
|
6070
|
+
return [recipientDeposit, "dummy"];
|
|
6071
|
+
}
|
|
6072
|
+
async function depositsWithoutFee(input) {
|
|
6073
|
+
if (input.changeStroops <= ZERO_STROOPS) {
|
|
6074
|
+
return {
|
|
6075
|
+
deposits: recipientOnlyDeposits(input.recipientDeposit, input.hasFeeOutput)
|
|
6076
|
+
};
|
|
6077
|
+
}
|
|
6078
|
+
return buildChangeDepositPair({
|
|
6079
|
+
selfPrivateAddressStpl1ForChange: input.selfPrivateAddressStpl1ForChange,
|
|
6080
|
+
changeStroops: input.changeStroops,
|
|
6081
|
+
tokenAddress: input.tokenAddress,
|
|
6082
|
+
recipientDeposit: input.recipientDeposit
|
|
6083
|
+
});
|
|
6084
|
+
}
|
|
5575
6085
|
async function buildRecipientAndOptionalChangeDeposits(parameters) {
|
|
5576
6086
|
const escrow = {
|
|
5577
6087
|
...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
|
|
5578
6088
|
...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
|
|
5579
6089
|
};
|
|
5580
|
-
const recipientPrivateAddress = parameters.recipientPrivateAddressStpl1.trim();
|
|
5581
6090
|
const recipientSlot = await getPrivacyPoolService().buildAlignedDepositSlot({
|
|
5582
|
-
privateAddressStpl1:
|
|
6091
|
+
privateAddressStpl1: parameters.recipientPrivateAddressStpl1.trim(),
|
|
5583
6092
|
amountStroops: parameters.transferStroops,
|
|
5584
6093
|
tokenAddress: parameters.tokenAddress,
|
|
5585
6094
|
...escrowOutputFields(escrow)
|
|
5586
6095
|
});
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
recipientSlot,
|
|
5590
|
-
deposits: paddingDepositPair(recipientSlot.deposit)
|
|
5591
|
-
};
|
|
5592
|
-
}
|
|
5593
|
-
const changeResult = await buildChangeDepositPair({
|
|
5594
|
-
selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
|
|
6096
|
+
const withoutFee = await depositsWithoutFee({
|
|
6097
|
+
recipientDeposit: recipientSlot.deposit,
|
|
5595
6098
|
changeStroops: parameters.changeStroops,
|
|
6099
|
+
selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
|
|
5596
6100
|
tokenAddress: parameters.tokenAddress,
|
|
5597
|
-
|
|
6101
|
+
hasFeeOutput: (parameters.feeOutput?.requiredFee ?? ZERO_STROOPS) > ZERO_STROOPS
|
|
6102
|
+
});
|
|
6103
|
+
const withFee = await appendFeeOutputSlot({
|
|
6104
|
+
deposits: withoutFee.deposits,
|
|
6105
|
+
tokenAddress: parameters.tokenAddress,
|
|
6106
|
+
buildAlignedDepositSlot: (aligned) => getPrivacyPoolService().buildAlignedDepositSlot(aligned),
|
|
6107
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
5598
6108
|
});
|
|
5599
6109
|
return {
|
|
5600
6110
|
recipientSlot,
|
|
5601
|
-
deposits:
|
|
5602
|
-
changeCoin:
|
|
6111
|
+
deposits: withFee.deposits,
|
|
6112
|
+
..."changeCoin" in withoutFee ? { changeCoin: withoutFee.changeCoin } : {},
|
|
6113
|
+
...withFee.feeCoin ? { feeCoin: withFee.feeCoin } : {}
|
|
5603
6114
|
};
|
|
5604
6115
|
}
|
|
5605
6116
|
|
|
@@ -5652,14 +6163,15 @@ function sweepOutputOwnerFields(parameters) {
|
|
|
5652
6163
|
return { sweepOutputOwnerPubX, sweepOutputOwnerPubY };
|
|
5653
6164
|
}
|
|
5654
6165
|
async function buildTransferDepositsAndPublicInput(parameters) {
|
|
5655
|
-
const { recipientSlot, deposits, changeCoin } = await buildRecipientAndOptionalChangeDeposits({
|
|
6166
|
+
const { recipientSlot, deposits, changeCoin, feeCoin } = await buildRecipientAndOptionalChangeDeposits({
|
|
5656
6167
|
recipientPrivateAddressStpl1: parameters.recipientPrivateAddressStpl1,
|
|
5657
6168
|
transferStroops: parameters.transferStroops,
|
|
5658
6169
|
changeStroops: parameters.changeStroops,
|
|
5659
6170
|
selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
|
|
5660
6171
|
tokenAddress: parameters.tokenAddress,
|
|
5661
6172
|
...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
|
|
5662
|
-
...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
|
|
6173
|
+
...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {},
|
|
6174
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
5663
6175
|
});
|
|
5664
6176
|
const publicInput = withTokenAddressPublicInputs(
|
|
5665
6177
|
{
|
|
@@ -5674,6 +6186,7 @@ async function buildTransferDepositsAndPublicInput(parameters) {
|
|
|
5674
6186
|
recipientSlot,
|
|
5675
6187
|
deposits,
|
|
5676
6188
|
...changeCoin ? { changeCoin } : {},
|
|
6189
|
+
...feeCoin ? { feeCoin } : {},
|
|
5677
6190
|
publicInput
|
|
5678
6191
|
};
|
|
5679
6192
|
}
|
|
@@ -5689,7 +6202,8 @@ async function buildSenderTransferDepositsAndPublicInput(parameters) {
|
|
|
5689
6202
|
parameters.senderPrivKeyScalarHex
|
|
5690
6203
|
),
|
|
5691
6204
|
...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
|
|
5692
|
-
...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
|
|
6205
|
+
...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {},
|
|
6206
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
5693
6207
|
});
|
|
5694
6208
|
}
|
|
5695
6209
|
|
|
@@ -5713,11 +6227,20 @@ function stampDualWithdrawLegs(legs, parameters) {
|
|
|
5713
6227
|
}
|
|
5714
6228
|
};
|
|
5715
6229
|
}
|
|
5716
|
-
function buildDualTransferApplicationIds(sdk, applicationId, changeCoin) {
|
|
6230
|
+
function buildDualTransferApplicationIds(sdk, applicationId, changeCoin, feeCoin) {
|
|
6231
|
+
const outputIds = [applicationId];
|
|
6232
|
+
if (changeCoin) {
|
|
6233
|
+
outputIds.push(applicationId);
|
|
6234
|
+
} else if (!feeCoin) {
|
|
6235
|
+
outputIds.push("0");
|
|
6236
|
+
}
|
|
6237
|
+
if (feeCoin) {
|
|
6238
|
+
outputIds.push(applicationId);
|
|
6239
|
+
}
|
|
5717
6240
|
return buildApplicationIdHints({
|
|
5718
6241
|
sdk,
|
|
5719
6242
|
inputIds: [applicationId, applicationId],
|
|
5720
|
-
outputIds
|
|
6243
|
+
outputIds
|
|
5721
6244
|
});
|
|
5722
6245
|
}
|
|
5723
6246
|
async function proveDualConfidentialTransfer(parameters) {
|
|
@@ -5737,16 +6260,24 @@ async function proveDualConfidentialTransfer(parameters) {
|
|
|
5737
6260
|
audit
|
|
5738
6261
|
);
|
|
5739
6262
|
}
|
|
5740
|
-
|
|
6263
|
+
function dualTransferChangeStroops(parameters) {
|
|
5741
6264
|
const totalNotes = BigInt(parameters.coinA.value) + BigInt(parameters.coinB.value);
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
6265
|
+
if (parameters.transferStroops < MIN_CONFIDENTIAL_TRANSFER_STROOPS) {
|
|
6266
|
+
throw new Error("Transfer amount must be positive");
|
|
6267
|
+
}
|
|
6268
|
+
const changeStroops = remainingAfterRequiredFee({
|
|
6269
|
+
available: totalNotes,
|
|
6270
|
+
instructed: parameters.transferStroops,
|
|
6271
|
+
requiredFee: parameters.feeOutput?.requiredFee ?? 0n
|
|
6272
|
+
});
|
|
5746
6273
|
requireChangeRecipientWhenPartial(
|
|
5747
6274
|
changeStroops,
|
|
5748
6275
|
parameters.selfPrivateAddressStpl1ForChange
|
|
5749
6276
|
);
|
|
6277
|
+
return changeStroops;
|
|
6278
|
+
}
|
|
6279
|
+
async function buildDualTransferProofContext(parameters, applicationId, sdk) {
|
|
6280
|
+
const changeStroops = dualTransferChangeStroops(parameters);
|
|
5750
6281
|
const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
|
|
5751
6282
|
parameters.senderPrivKeyScalarHex
|
|
5752
6283
|
);
|
|
@@ -5773,15 +6304,21 @@ async function buildDualTransferProofContext(parameters, applicationId, sdk) {
|
|
|
5773
6304
|
selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
|
|
5774
6305
|
tokenAddress: parameters.tokenAddress,
|
|
5775
6306
|
stateRoot: legA.witness.stateRoot,
|
|
5776
|
-
...confidentialEscrowFields(parameters)
|
|
6307
|
+
...confidentialEscrowFields(parameters),
|
|
6308
|
+
...parameters.feeOutput ? { feeOutput: parameters.feeOutput } : {}
|
|
5777
6309
|
});
|
|
5778
6310
|
return { legA, legB, applicationId, ...transferInputs };
|
|
5779
6311
|
}
|
|
5780
6312
|
async function prepareConfidentialTransferProofDual(parameters) {
|
|
5781
6313
|
const poolService = getPrivacyPoolService();
|
|
5782
|
-
const sdk = await poolService.getInitializedSdk(
|
|
6314
|
+
const sdk = await poolService.getInitializedSdk(
|
|
6315
|
+
poolService.feeBearingZkConfigNonce({
|
|
6316
|
+
kind: "transfer",
|
|
6317
|
+
...parameters.escrowClaimantLimbs ? { spendSource: "escrow" } : {}
|
|
6318
|
+
})
|
|
6319
|
+
);
|
|
5783
6320
|
const applicationId = poolService.getApplicationId();
|
|
5784
|
-
const { legA, legB, recipientSlot, deposits, changeCoin, publicInput } = await buildDualTransferProofContext(parameters, applicationId, sdk);
|
|
6321
|
+
const { legA, legB, recipientSlot, deposits, changeCoin, feeCoin, publicInput } = await buildDualTransferProofContext(parameters, applicationId, sdk);
|
|
5785
6322
|
const auditPublicKey = poolService.getAuditPublicKey();
|
|
5786
6323
|
const proof = await (auditPublicKey ? proveDualConfidentialTransfer({
|
|
5787
6324
|
sdk,
|
|
@@ -5804,7 +6341,8 @@ async function prepareConfidentialTransferProofDual(parameters) {
|
|
|
5804
6341
|
applicationIdsPlaintext: buildDualTransferApplicationIds(
|
|
5805
6342
|
sdk,
|
|
5806
6343
|
applicationId,
|
|
5807
|
-
changeCoin
|
|
6344
|
+
changeCoin,
|
|
6345
|
+
feeCoin
|
|
5808
6346
|
),
|
|
5809
6347
|
recipientCoin: generatedOutputCoinFromSlot(recipientSlot),
|
|
5810
6348
|
...changeCoin ? { changeCoin } : {}
|
|
@@ -5812,22 +6350,32 @@ async function prepareConfidentialTransferProofDual(parameters) {
|
|
|
5812
6350
|
}
|
|
5813
6351
|
|
|
5814
6352
|
// src/transact/proofs/confidential/single.ts
|
|
5815
|
-
function validateSingleCoinTransferAmounts(transferStroops, noteStroops, selfPrivateAddressStpl1ForChange) {
|
|
6353
|
+
function validateSingleCoinTransferAmounts(transferStroops, noteStroops, selfPrivateAddressStpl1ForChange, requiredFee) {
|
|
5816
6354
|
if (transferStroops < MIN_CONFIDENTIAL_TRANSFER_STROOPS) {
|
|
5817
6355
|
throw new Error("Transfer amount must be positive");
|
|
5818
6356
|
}
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
6357
|
+
const changeStroops = remainingAfterRequiredFee({
|
|
6358
|
+
available: noteStroops,
|
|
6359
|
+
instructed: transferStroops,
|
|
6360
|
+
requiredFee
|
|
6361
|
+
});
|
|
5823
6362
|
requireChangeRecipientWhenPartial(changeStroops, selfPrivateAddressStpl1ForChange);
|
|
5824
6363
|
return changeStroops;
|
|
5825
6364
|
}
|
|
5826
|
-
function buildSingleTransferApplicationIds(sdk, applicationId, changeCoin) {
|
|
6365
|
+
function buildSingleTransferApplicationIds(sdk, applicationId, changeCoin, feeCoin) {
|
|
6366
|
+
const outputIds = [applicationId];
|
|
6367
|
+
if (changeCoin) {
|
|
6368
|
+
outputIds.push(applicationId);
|
|
6369
|
+
} else if (!feeCoin) {
|
|
6370
|
+
outputIds.push("0");
|
|
6371
|
+
}
|
|
6372
|
+
if (feeCoin) {
|
|
6373
|
+
outputIds.push(applicationId);
|
|
6374
|
+
}
|
|
5827
6375
|
return buildApplicationIdHints({
|
|
5828
6376
|
sdk,
|
|
5829
6377
|
inputIds: [applicationId],
|
|
5830
|
-
outputIds
|
|
6378
|
+
outputIds
|
|
5831
6379
|
});
|
|
5832
6380
|
}
|
|
5833
6381
|
function buildTransferAuditParameters(parameters) {
|
|
@@ -5853,11 +6401,25 @@ function confidentialEscrowFields2(input) {
|
|
|
5853
6401
|
...input.escrowClaimantLimbs ? { escrowClaimantLimbs: input.escrowClaimantLimbs } : {}
|
|
5854
6402
|
};
|
|
5855
6403
|
}
|
|
6404
|
+
function transferDepositInputFromProof(input, changeStroops, stateRoot) {
|
|
6405
|
+
return {
|
|
6406
|
+
senderPrivKeyScalarHex: input.senderPrivKeyScalarHex,
|
|
6407
|
+
recipientPrivateAddressStpl1: input.recipientPrivateAddressStpl1,
|
|
6408
|
+
transferStroops: input.transferStroops,
|
|
6409
|
+
changeStroops,
|
|
6410
|
+
selfPrivateAddressStpl1ForChange: input.selfPrivateAddressStpl1ForChange,
|
|
6411
|
+
tokenAddress: input.tokenAddress,
|
|
6412
|
+
stateRoot,
|
|
6413
|
+
...confidentialEscrowFields2(input),
|
|
6414
|
+
...input.feeOutput ? { feeOutput: input.feeOutput } : {}
|
|
6415
|
+
};
|
|
6416
|
+
}
|
|
5856
6417
|
async function buildTransferProofInputs(parameters) {
|
|
5857
6418
|
const changeStroops = validateSingleCoinTransferAmounts(
|
|
5858
6419
|
parameters.input.transferStroops,
|
|
5859
6420
|
parameters.noteStroops,
|
|
5860
|
-
parameters.input.selfPrivateAddressStpl1ForChange
|
|
6421
|
+
parameters.input.selfPrivateAddressStpl1ForChange,
|
|
6422
|
+
parameters.input.feeOutput?.requiredFee ?? 0n
|
|
5861
6423
|
);
|
|
5862
6424
|
const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
|
|
5863
6425
|
parameters.input.senderPrivKeyScalarHex
|
|
@@ -5876,31 +6438,30 @@ async function buildTransferProofInputs(parameters) {
|
|
|
5876
6438
|
withdrawObject,
|
|
5877
6439
|
sweepWithdrawStamp(confidentialEscrowFields2(parameters.input))
|
|
5878
6440
|
);
|
|
5879
|
-
const { recipientSlot, deposits, changeCoin, publicInput } = await buildSenderTransferDepositsAndPublicInput(
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
transferStroops: parameters.input.transferStroops,
|
|
5883
|
-
changeStroops,
|
|
5884
|
-
selfPrivateAddressStpl1ForChange: parameters.input.selfPrivateAddressStpl1ForChange,
|
|
5885
|
-
tokenAddress: parameters.input.tokenAddress,
|
|
5886
|
-
stateRoot: witness.stateRoot,
|
|
5887
|
-
...confidentialEscrowFields2(parameters.input)
|
|
5888
|
-
});
|
|
6441
|
+
const { recipientSlot, deposits, changeCoin, feeCoin, publicInput } = await buildSenderTransferDepositsAndPublicInput(
|
|
6442
|
+
transferDepositInputFromProof(parameters.input, changeStroops, witness.stateRoot)
|
|
6443
|
+
);
|
|
5889
6444
|
return {
|
|
5890
6445
|
witness,
|
|
5891
6446
|
withdrawObject: stampedWithdraw,
|
|
5892
6447
|
recipientSlot,
|
|
5893
6448
|
deposits,
|
|
5894
6449
|
changeCoin,
|
|
6450
|
+
feeCoin,
|
|
5895
6451
|
publicInput
|
|
5896
6452
|
};
|
|
5897
6453
|
}
|
|
5898
6454
|
async function prepareConfidentialTransferProof(parameters) {
|
|
5899
6455
|
const poolService = getPrivacyPoolService();
|
|
5900
|
-
const sdk = await poolService.getInitializedSdk(
|
|
6456
|
+
const sdk = await poolService.getInitializedSdk(
|
|
6457
|
+
poolService.feeBearingZkConfigNonce({
|
|
6458
|
+
kind: "transfer",
|
|
6459
|
+
...parameters.escrowClaimantLimbs ? { spendSource: "escrow" } : {}
|
|
6460
|
+
})
|
|
6461
|
+
);
|
|
5901
6462
|
const applicationId = poolService.getApplicationId();
|
|
5902
6463
|
const noteStroops = BigInt(parameters.coin.value);
|
|
5903
|
-
const { withdrawObject, recipientSlot, deposits, changeCoin, publicInput } = await buildTransferProofInputs({
|
|
6464
|
+
const { withdrawObject, recipientSlot, deposits, changeCoin, feeCoin, publicInput } = await buildTransferProofInputs({
|
|
5904
6465
|
sdk,
|
|
5905
6466
|
applicationId,
|
|
5906
6467
|
input: parameters,
|
|
@@ -5923,7 +6484,8 @@ async function prepareConfidentialTransferProof(parameters) {
|
|
|
5923
6484
|
applicationIdsPlaintext: buildSingleTransferApplicationIds(
|
|
5924
6485
|
sdk,
|
|
5925
6486
|
applicationId,
|
|
5926
|
-
changeCoin
|
|
6487
|
+
changeCoin,
|
|
6488
|
+
feeCoin
|
|
5927
6489
|
),
|
|
5928
6490
|
recipientCoin: generatedOutputCoinFromSlot(recipientSlot),
|
|
5929
6491
|
...changeCoin ? { changeCoin } : {}
|
|
@@ -5946,7 +6508,12 @@ function proofEscrowFields(input) {
|
|
|
5946
6508
|
}
|
|
5947
6509
|
async function buildSingleTransferProofAtExecute(input) {
|
|
5948
6510
|
const context = await buildSpendProofContextAtExecute(input);
|
|
5949
|
-
const
|
|
6511
|
+
const feeOutput = await quoteFeeOutputForPrepared({
|
|
6512
|
+
prepared: input.prepared,
|
|
6513
|
+
environment: input.environment,
|
|
6514
|
+
tokenAddress: context.tokenAddress
|
|
6515
|
+
});
|
|
6516
|
+
const changeStroops = BigInt(context.coin.value) - input.prepared.intent.amount - (feeOutput?.requiredFee ?? 0n);
|
|
5950
6517
|
const proof = await prepareConfidentialTransferProof({
|
|
5951
6518
|
coin: context.coin,
|
|
5952
6519
|
state: { commitments: context.commitments },
|
|
@@ -5959,7 +6526,8 @@ async function buildSingleTransferProofAtExecute(input) {
|
|
|
5959
6526
|
recipientPrivateAddressStpl1: context.recipientPrivateAddressStpl1,
|
|
5960
6527
|
selfPrivateAddressStpl1ForChange: readChangeRecipient(input, changeStroops),
|
|
5961
6528
|
tokenAddress: context.tokenAddress,
|
|
5962
|
-
...proofEscrowFields(input)
|
|
6529
|
+
...proofEscrowFields(input),
|
|
6530
|
+
...feeOutput ? { feeOutput } : {}
|
|
5963
6531
|
});
|
|
5964
6532
|
return { context, proof };
|
|
5965
6533
|
}
|
|
@@ -5976,7 +6544,12 @@ async function buildDualTransferProofAtExecute(input) {
|
|
|
5976
6544
|
commitments: context.commitments
|
|
5977
6545
|
});
|
|
5978
6546
|
const totalNotes = BigInt(context.coin.value) + BigInt(secondary.coin.value);
|
|
5979
|
-
const
|
|
6547
|
+
const feeOutput = await quoteFeeOutputForPrepared({
|
|
6548
|
+
prepared: input.prepared,
|
|
6549
|
+
environment: input.environment,
|
|
6550
|
+
tokenAddress: context.tokenAddress
|
|
6551
|
+
});
|
|
6552
|
+
const changeStroops = totalNotes - input.prepared.intent.amount - (feeOutput?.requiredFee ?? 0n);
|
|
5980
6553
|
const proof = await prepareConfidentialTransferProofDual({
|
|
5981
6554
|
coinA: context.coin,
|
|
5982
6555
|
coinB: secondary.coin,
|
|
@@ -5994,7 +6567,8 @@ async function buildDualTransferProofAtExecute(input) {
|
|
|
5994
6567
|
recipientPrivateAddressStpl1: context.recipientPrivateAddressStpl1,
|
|
5995
6568
|
selfPrivateAddressStpl1ForChange: readChangeRecipient(input, changeStroops),
|
|
5996
6569
|
tokenAddress: context.tokenAddress,
|
|
5997
|
-
...proofEscrowFields(input)
|
|
6570
|
+
...proofEscrowFields(input),
|
|
6571
|
+
...feeOutput ? { feeOutput } : {}
|
|
5998
6572
|
});
|
|
5999
6573
|
return { context, proof };
|
|
6000
6574
|
}
|
|
@@ -6126,11 +6700,17 @@ async function runTransferFinalizeSteps(input) {
|
|
|
6126
6700
|
walletPublicKey: input.walletPublicKey,
|
|
6127
6701
|
...recipient.escrowSend ? { escrowSendPrivateAddress: recipient.recipientPrivateAddressStpl1 } : {}
|
|
6128
6702
|
});
|
|
6129
|
-
return
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6703
|
+
return {
|
|
6704
|
+
...buildTransferFinalizeArtifacts({
|
|
6705
|
+
proof,
|
|
6706
|
+
context,
|
|
6707
|
+
...sweepFinalizeStamp(input.prepared, recipient)
|
|
6708
|
+
}),
|
|
6709
|
+
zkConfigNonce: zkConfigNonceForFeeBearingKind({
|
|
6710
|
+
...feeOutputKindFromPrepared(input.prepared),
|
|
6711
|
+
...configuredNonceSpread(input.environment.zkConfigNonce)
|
|
6712
|
+
})
|
|
6713
|
+
};
|
|
6134
6714
|
}
|
|
6135
6715
|
function sweepArtifactStamp(artifacts) {
|
|
6136
6716
|
return {
|
|
@@ -6158,6 +6738,24 @@ async function finalizeTransferAtExecute(prepared, environment) {
|
|
|
6158
6738
|
return runTransferFinalizeSteps({ prepared, environment, walletPublicKey });
|
|
6159
6739
|
}
|
|
6160
6740
|
|
|
6741
|
+
// src/transact/engine/withdraw-fee.ts
|
|
6742
|
+
async function withdrawFeeProofFields(input) {
|
|
6743
|
+
const feeOutput = await quoteFeeOutputForPrepared({
|
|
6744
|
+
prepared: input.prepared,
|
|
6745
|
+
environment: input.environment,
|
|
6746
|
+
tokenAddress: input.tokenAddress
|
|
6747
|
+
});
|
|
6748
|
+
const changeStroops = remainingAfterRequiredFee({
|
|
6749
|
+
available: input.available,
|
|
6750
|
+
instructed: input.prepared.intent.amount,
|
|
6751
|
+
requiredFee: feeOutput?.requiredFee ?? 0n
|
|
6752
|
+
});
|
|
6753
|
+
return {
|
|
6754
|
+
...feeOutput ? { feeOutput } : {},
|
|
6755
|
+
...changeStroops > 0n ? { changePrivateAddressStpl1: input.withdrawFrom } : {}
|
|
6756
|
+
};
|
|
6757
|
+
}
|
|
6758
|
+
|
|
6161
6759
|
// src/transact/engine/execute.ts
|
|
6162
6760
|
function enrichWithdrawOutputRecords(prepared, proof) {
|
|
6163
6761
|
if (!proof.changeCoin || prepared.outputRecords.length === 0) {
|
|
@@ -6173,7 +6771,7 @@ function enrichWithdrawOutputRecords(prepared, proof) {
|
|
|
6173
6771
|
precommitementHex: changeCoin.precommitementHex
|
|
6174
6772
|
}));
|
|
6175
6773
|
}
|
|
6176
|
-
function buildWithdrawFinalizeArtifacts(proof, context) {
|
|
6774
|
+
function buildWithdrawFinalizeArtifacts(proof, context, environment) {
|
|
6177
6775
|
return {
|
|
6178
6776
|
proofHex: proof.proof_hex,
|
|
6179
6777
|
publicHex: proof.public_hex,
|
|
@@ -6181,7 +6779,11 @@ function buildWithdrawFinalizeArtifacts(proof, context) {
|
|
|
6181
6779
|
applicationIdsPlaintext: proof.applicationIdsPlaintext,
|
|
6182
6780
|
tokenAddress: context.tokenAddress,
|
|
6183
6781
|
walletPublicKey: context.walletPublicKey,
|
|
6184
|
-
executeFinalizeRequired: false
|
|
6782
|
+
executeFinalizeRequired: false,
|
|
6783
|
+
zkConfigNonce: zkConfigNonceForFeeBearingKind({
|
|
6784
|
+
kind: "withdraw",
|
|
6785
|
+
...configuredNonceSpread(environment.zkConfigNonce)
|
|
6786
|
+
})
|
|
6185
6787
|
};
|
|
6186
6788
|
}
|
|
6187
6789
|
async function finalizeSingleWithdrawAtExecute(prepared, environment, poolService, withdrawFrom) {
|
|
@@ -6190,7 +6792,13 @@ async function finalizeSingleWithdrawAtExecute(prepared, environment, poolServic
|
|
|
6190
6792
|
environment,
|
|
6191
6793
|
recipientPrivateAddressStpl1: withdrawFrom
|
|
6192
6794
|
});
|
|
6193
|
-
const
|
|
6795
|
+
const feeFields = await withdrawFeeProofFields({
|
|
6796
|
+
prepared,
|
|
6797
|
+
environment,
|
|
6798
|
+
tokenAddress: context.tokenAddress,
|
|
6799
|
+
available: BigInt(context.coin.value),
|
|
6800
|
+
withdrawFrom
|
|
6801
|
+
});
|
|
6194
6802
|
const proof = await poolService.prepareWithdrawTransactProof({
|
|
6195
6803
|
coin: context.coin,
|
|
6196
6804
|
state: { commitments: context.commitments },
|
|
@@ -6201,11 +6809,24 @@ async function finalizeSingleWithdrawAtExecute(prepared, environment, poolServic
|
|
|
6201
6809
|
yHex: context.ephemeral.yHex
|
|
6202
6810
|
}),
|
|
6203
6811
|
withdrawAmountStroops: prepared.intent.amount,
|
|
6204
|
-
changePrivateAddressStpl1:
|
|
6205
|
-
tokenAddress: context.tokenAddress
|
|
6812
|
+
changePrivateAddressStpl1: feeFields.changePrivateAddressStpl1,
|
|
6813
|
+
tokenAddress: context.tokenAddress,
|
|
6814
|
+
...feeFields.feeOutput ? { feeOutput: feeFields.feeOutput } : {}
|
|
6206
6815
|
});
|
|
6207
6816
|
enrichWithdrawOutputRecords(prepared, proof);
|
|
6208
|
-
return buildWithdrawFinalizeArtifacts(proof, context);
|
|
6817
|
+
return buildWithdrawFinalizeArtifacts(proof, context, environment);
|
|
6818
|
+
}
|
|
6819
|
+
function dualWithdrawEphemeralKeys(input) {
|
|
6820
|
+
return {
|
|
6821
|
+
depositorEphemeralAKey: serializeEphemeralKeyString({
|
|
6822
|
+
xHex: input.context.ephemeral.xHex,
|
|
6823
|
+
yHex: input.context.ephemeral.yHex
|
|
6824
|
+
}),
|
|
6825
|
+
depositorEphemeralBKey: serializeEphemeralKeyString({
|
|
6826
|
+
xHex: input.secondary.ephemeral.xHex,
|
|
6827
|
+
yHex: input.secondary.ephemeral.yHex
|
|
6828
|
+
})
|
|
6829
|
+
};
|
|
6209
6830
|
}
|
|
6210
6831
|
async function finalizeDualWithdrawAtExecute(prepared, environment, poolService, withdrawFrom) {
|
|
6211
6832
|
const [, secondaryRecord] = prepared.consumedRecords;
|
|
@@ -6223,28 +6844,27 @@ async function finalizeDualWithdrawAtExecute(prepared, environment, poolService,
|
|
|
6223
6844
|
walletPublicKey: context.walletPublicKey,
|
|
6224
6845
|
commitments: context.commitments
|
|
6225
6846
|
});
|
|
6226
|
-
const
|
|
6227
|
-
|
|
6847
|
+
const feeFields = await withdrawFeeProofFields({
|
|
6848
|
+
prepared,
|
|
6849
|
+
environment,
|
|
6850
|
+
tokenAddress: context.tokenAddress,
|
|
6851
|
+
available: BigInt(context.coin.value) + BigInt(secondary.coin.value),
|
|
6852
|
+
withdrawFrom
|
|
6853
|
+
});
|
|
6228
6854
|
const proof = await poolService.prepareWithdrawTransactProofDual({
|
|
6229
6855
|
coinA: context.coin,
|
|
6230
6856
|
coinB: secondary.coin,
|
|
6231
6857
|
state: { commitments: context.commitments },
|
|
6232
6858
|
destinationStellarAddress: prepared.intent.to,
|
|
6233
6859
|
privKeyScalarHex: context.senderPrivKeyScalarHex,
|
|
6234
|
-
|
|
6235
|
-
xHex: context.ephemeral.xHex,
|
|
6236
|
-
yHex: context.ephemeral.yHex
|
|
6237
|
-
}),
|
|
6238
|
-
depositorEphemeralBKey: serializeEphemeralKeyString({
|
|
6239
|
-
xHex: secondary.ephemeral.xHex,
|
|
6240
|
-
yHex: secondary.ephemeral.yHex
|
|
6241
|
-
}),
|
|
6860
|
+
...dualWithdrawEphemeralKeys({ context, secondary }),
|
|
6242
6861
|
withdrawAmountStroops: prepared.intent.amount,
|
|
6243
|
-
changePrivateAddressStpl1:
|
|
6244
|
-
tokenAddress: context.tokenAddress
|
|
6862
|
+
changePrivateAddressStpl1: feeFields.changePrivateAddressStpl1,
|
|
6863
|
+
tokenAddress: context.tokenAddress,
|
|
6864
|
+
...feeFields.feeOutput ? { feeOutput: feeFields.feeOutput } : {}
|
|
6245
6865
|
});
|
|
6246
6866
|
enrichWithdrawOutputRecords(prepared, proof);
|
|
6247
|
-
return buildWithdrawFinalizeArtifacts(proof, context);
|
|
6867
|
+
return buildWithdrawFinalizeArtifacts(proof, context, environment);
|
|
6248
6868
|
}
|
|
6249
6869
|
async function finalizeWithdrawAtExecute(prepared, environment, poolService) {
|
|
6250
6870
|
if (prepared.kind !== "withdraw") {
|
|
@@ -6376,20 +6996,20 @@ async function waitForKytRegistration(parameters) {
|
|
|
6376
6996
|
}
|
|
6377
6997
|
|
|
6378
6998
|
// src/transact/kyt/passage/submit.ts
|
|
6379
|
-
import { Buffer as
|
|
6380
|
-
import { Operation, TransactionBuilder, rpc as rpc3, xdr as
|
|
6999
|
+
import { Buffer as Buffer15 } from "buffer";
|
|
7000
|
+
import { Operation, TransactionBuilder, rpc as rpc3, xdr as xdr3 } from "@stellar/stellar-sdk";
|
|
6381
7001
|
var KYT_REGISTER_FEE_STROOPS = "1000000";
|
|
6382
7002
|
var KYT_REGISTER_TIMEOUT_SECONDS = 300;
|
|
6383
7003
|
function passageIdToScValue(passageId) {
|
|
6384
|
-
return
|
|
7004
|
+
return xdr3.ScVal.scvBytes(Buffer15.from(passageId.replace(/^0x/, ""), "hex"));
|
|
6385
7005
|
}
|
|
6386
7006
|
function approvalSignatureToBytes(signature) {
|
|
6387
7007
|
const clean = signature.trim();
|
|
6388
|
-
return /^(0x)?[0-9a-fA-F]{128}$/.test(clean) ?
|
|
7008
|
+
return /^(0x)?[0-9a-fA-F]{128}$/.test(clean) ? Buffer15.from(clean.replace(/^0x/i, ""), "hex") : Buffer15.from(clean, "base64");
|
|
6389
7009
|
}
|
|
6390
7010
|
function signatureToScValue(signature) {
|
|
6391
7011
|
const bytes = approvalSignatureToBytes(signature);
|
|
6392
|
-
return
|
|
7012
|
+
return xdr3.ScVal.scvBytes(bytes);
|
|
6393
7013
|
}
|
|
6394
7014
|
async function registerKytPassage(parameters) {
|
|
6395
7015
|
const signTransaction = parameters.transactEnvironment.signTransaction;
|
|
@@ -6410,7 +7030,7 @@ async function registerKytPassage(parameters) {
|
|
|
6410
7030
|
function: "register_passage",
|
|
6411
7031
|
args: [
|
|
6412
7032
|
passageIdToScValue(parameters.approval.passageId),
|
|
6413
|
-
|
|
7033
|
+
xdr3.ScVal.scvU32(parameters.approval.expiresAtLedger),
|
|
6414
7034
|
signatureToScValue(parameters.approval.signature)
|
|
6415
7035
|
]
|
|
6416
7036
|
})
|
|
@@ -6506,7 +7126,7 @@ async function requestKytPassageForPoolInteraction(input) {
|
|
|
6506
7126
|
const applicationId = resolvePoolApplicationId(
|
|
6507
7127
|
input.transactEnvironment.network.applicationId
|
|
6508
7128
|
);
|
|
6509
|
-
const zkConfigNonce = resolveZkConfigNonce(input.transactEnvironment);
|
|
7129
|
+
const zkConfigNonce = input.zkConfigNonce ?? resolveZkConfigNonce(input.transactEnvironment);
|
|
6510
7130
|
const applicationIdsPlaintext = input.applicationIdsPlaintext ?? buildApplicationIdHints2(
|
|
6511
7131
|
applicationId,
|
|
6512
7132
|
layoutForKnownNonce(zkConfigNonce).nAuditSlots
|
|
@@ -6535,12 +7155,12 @@ async function requestKytPassageForPoolInteraction(input) {
|
|
|
6535
7155
|
|
|
6536
7156
|
// src/transact/submit/zk-config-ttl.ts
|
|
6537
7157
|
import {
|
|
6538
|
-
Address as
|
|
7158
|
+
Address as Address3,
|
|
6539
7159
|
Operation as Operation2,
|
|
6540
7160
|
SorobanDataBuilder,
|
|
6541
7161
|
TransactionBuilder as TransactionBuilder2,
|
|
6542
7162
|
rpc as rpc4,
|
|
6543
|
-
xdr as
|
|
7163
|
+
xdr as xdr4
|
|
6544
7164
|
} from "@stellar/stellar-sdk";
|
|
6545
7165
|
var ZK_CONFIG_TTL_THRESHOLD_LEDGERS = 1e5;
|
|
6546
7166
|
var ZK_CONFIG_TTL_EXTEND_TO_LEDGERS = 5e5;
|
|
@@ -6564,15 +7184,15 @@ async function waitForExtendFootprintTtlConfirmation(parameters) {
|
|
|
6564
7184
|
throw new Error("ZK config TTL extension was not confirmed in time");
|
|
6565
7185
|
}
|
|
6566
7186
|
function zkConfigLedgerKey(contractId, nonce) {
|
|
6567
|
-
const configKeyScValue =
|
|
6568
|
-
|
|
6569
|
-
|
|
7187
|
+
const configKeyScValue = xdr4.ScVal.scvVec([
|
|
7188
|
+
xdr4.ScVal.scvSymbol("Config"),
|
|
7189
|
+
xdr4.ScVal.scvU64(xdr4.Uint64.fromString(nonce.toString()))
|
|
6570
7190
|
]);
|
|
6571
|
-
return
|
|
6572
|
-
new
|
|
6573
|
-
contract: new
|
|
7191
|
+
return xdr4.LedgerKey.contractData(
|
|
7192
|
+
new xdr4.LedgerKeyContractData({
|
|
7193
|
+
contract: new Address3(contractId).toScAddress(),
|
|
6574
7194
|
key: configKeyScValue,
|
|
6575
|
-
durability:
|
|
7195
|
+
durability: xdr4.ContractDataDurability.persistent()
|
|
6576
7196
|
})
|
|
6577
7197
|
);
|
|
6578
7198
|
}
|
|
@@ -6637,7 +7257,7 @@ async function extendZkConfigTtlIfNeeded(parameters) {
|
|
|
6637
7257
|
}
|
|
6638
7258
|
|
|
6639
7259
|
// src/transact/submit/pool-transact.ts
|
|
6640
|
-
import { Buffer as
|
|
7260
|
+
import { Buffer as Buffer16 } from "buffer";
|
|
6641
7261
|
async function submitPoolTransact(parameters) {
|
|
6642
7262
|
await extendZkConfigTtlIfNeeded({
|
|
6643
7263
|
sorobanRpcUrl: parameters.sorobanRpcUrl,
|
|
@@ -6650,9 +7270,9 @@ async function submitPoolTransact(parameters) {
|
|
|
6650
7270
|
const assembledTransaction = await parameters.contractClient.transact({
|
|
6651
7271
|
from: parameters.from,
|
|
6652
7272
|
nonce: parameters.nonce,
|
|
6653
|
-
proof_bytes:
|
|
6654
|
-
pub_signals_bytes:
|
|
6655
|
-
ciphertext_bytes:
|
|
7273
|
+
proof_bytes: Buffer16.from(parameters.proofHex.replace(/^0x/iu, ""), "hex"),
|
|
7274
|
+
pub_signals_bytes: Buffer16.from(parameters.publicHex.replace(/^0x/iu, ""), "hex"),
|
|
7275
|
+
ciphertext_bytes: Buffer16.from(
|
|
6656
7276
|
(parameters.ciphertextHex ?? "").replace(/^0x/iu, ""),
|
|
6657
7277
|
"hex"
|
|
6658
7278
|
),
|
|
@@ -6678,6 +7298,10 @@ async function submitSorobanConfidentialTransfer(input) {
|
|
|
6678
7298
|
networkPassphrase: input.networkPassphrase,
|
|
6679
7299
|
sorobanRpcUrl: input.sorobanRpcUrl
|
|
6680
7300
|
});
|
|
7301
|
+
const nonce = transactNonceFromArtifacts(
|
|
7302
|
+
input.zkConfigNonce === void 0 ? void 0 : { zkConfigNonce: input.zkConfigNonce },
|
|
7303
|
+
input.transactEnvironment
|
|
7304
|
+
);
|
|
6681
7305
|
const approval = await requestKytPassageForPoolInteraction({
|
|
6682
7306
|
owner: input.walletPublicKey,
|
|
6683
7307
|
poolContract: input.contractId,
|
|
@@ -6686,6 +7310,7 @@ async function submitSorobanConfidentialTransfer(input) {
|
|
|
6686
7310
|
...input.ciphertextHex ? { ciphertextHex: input.ciphertextHex } : {},
|
|
6687
7311
|
...input.outputNoteEphemeralScalars ? { outputNoteEphemeralScalars: input.outputNoteEphemeralScalars } : {},
|
|
6688
7312
|
...input.applicationIdsPlaintext ? { applicationIdsPlaintext: input.applicationIdsPlaintext } : {},
|
|
7313
|
+
...input.zkConfigNonce === void 0 ? {} : { zkConfigNonce: input.zkConfigNonce },
|
|
6689
7314
|
networkPassphrase: input.networkPassphrase,
|
|
6690
7315
|
sorobanRpcUrl: input.sorobanRpcUrl,
|
|
6691
7316
|
transactEnvironment: input.transactEnvironment
|
|
@@ -6694,7 +7319,7 @@ async function submitSorobanConfidentialTransfer(input) {
|
|
|
6694
7319
|
contractClient: poolClient,
|
|
6695
7320
|
contractId: input.contractId,
|
|
6696
7321
|
from: input.walletPublicKey,
|
|
6697
|
-
nonce
|
|
7322
|
+
nonce,
|
|
6698
7323
|
proofHex: input.proofHex,
|
|
6699
7324
|
publicHex: input.publicHex,
|
|
6700
7325
|
...input.ciphertextHex ? { ciphertextHex: input.ciphertextHex } : {},
|
|
@@ -6725,12 +7350,14 @@ async function submitPreparedDeposit(prepared, environment) {
|
|
|
6725
7350
|
networkPassphrase: environment.network.networkPassphrase,
|
|
6726
7351
|
sorobanRpcUrl: environment.network.rpcUrl
|
|
6727
7352
|
});
|
|
7353
|
+
const nonce = transactNonceFromArtifacts(artifacts, environment);
|
|
6728
7354
|
const approval = await requestKytPassageForPoolInteraction({
|
|
6729
7355
|
owner: artifacts.walletPublicKey,
|
|
6730
7356
|
poolContract: environment.network.poolContract,
|
|
6731
7357
|
proofHex: artifacts.proofHex,
|
|
6732
7358
|
publicHex: artifacts.publicHex,
|
|
6733
7359
|
...optionalInspectCiphertext(artifacts),
|
|
7360
|
+
...artifacts.zkConfigNonce === void 0 ? {} : { zkConfigNonce: artifacts.zkConfigNonce },
|
|
6734
7361
|
networkPassphrase: environment.network.networkPassphrase,
|
|
6735
7362
|
sorobanRpcUrl: environment.network.rpcUrl,
|
|
6736
7363
|
transactEnvironment: environment
|
|
@@ -6739,7 +7366,7 @@ async function submitPreparedDeposit(prepared, environment) {
|
|
|
6739
7366
|
contractClient: poolClient,
|
|
6740
7367
|
contractId: environment.network.poolContract,
|
|
6741
7368
|
from: artifacts.walletPublicKey,
|
|
6742
|
-
nonce
|
|
7369
|
+
nonce,
|
|
6743
7370
|
proofHex: artifacts.proofHex,
|
|
6744
7371
|
publicHex: artifacts.publicHex,
|
|
6745
7372
|
...artifacts.ciphertextHex ? { ciphertextHex: artifacts.ciphertextHex } : {},
|
|
@@ -6760,6 +7387,7 @@ async function submitPreparedPoolTransact(prepared, environment) {
|
|
|
6760
7387
|
proofHex: artifacts.proofHex,
|
|
6761
7388
|
publicHex: artifacts.publicHex,
|
|
6762
7389
|
...optionalInspectCiphertext(artifacts),
|
|
7390
|
+
...artifacts.zkConfigNonce === void 0 ? {} : { zkConfigNonce: artifacts.zkConfigNonce },
|
|
6763
7391
|
networkPassphrase: environment.network.networkPassphrase,
|
|
6764
7392
|
sorobanRpcUrl: environment.network.rpcUrl,
|
|
6765
7393
|
transactEnvironment: environment
|
|
@@ -6815,7 +7443,7 @@ async function privacyPoolInitOptions(assets, transactEnvironment) {
|
|
|
6815
7443
|
};
|
|
6816
7444
|
}
|
|
6817
7445
|
async function createDefaultTransactEngine(assets, transactEnvironment) {
|
|
6818
|
-
await
|
|
7446
|
+
await PrivacyPoolSDK4.init(await privacyPoolInitOptions(assets, transactEnvironment));
|
|
6819
7447
|
if (transactEnvironment) {
|
|
6820
7448
|
configurePrivacyPoolService(
|
|
6821
7449
|
createPrivacyPoolService({
|
|
@@ -7217,13 +7845,13 @@ async function fetchEscrowOutputNoteEvents(input) {
|
|
|
7217
7845
|
// src/transact/escrow/simulate-escrow-authorization.ts
|
|
7218
7846
|
import {
|
|
7219
7847
|
Account,
|
|
7220
|
-
Address as
|
|
7848
|
+
Address as Address5,
|
|
7221
7849
|
Contract,
|
|
7222
7850
|
nativeToScVal as nativeToScVal2,
|
|
7223
7851
|
TransactionBuilder as TransactionBuilder3,
|
|
7224
7852
|
rpc as rpc5
|
|
7225
7853
|
} from "@stellar/stellar-sdk";
|
|
7226
|
-
import { Buffer as
|
|
7854
|
+
import { Buffer as Buffer17 } from "buffer";
|
|
7227
7855
|
|
|
7228
7856
|
// src/transact/escrow/kyt-authorization-sc-value.ts
|
|
7229
7857
|
import { nativeToScVal } from "@stellar/stellar-sdk";
|
|
@@ -7243,14 +7871,14 @@ function kytAuthorizationScValue(parameters) {
|
|
|
7243
7871
|
}
|
|
7244
7872
|
|
|
7245
7873
|
// src/transact/escrow/pick-escrow-authorization.ts
|
|
7246
|
-
import { Address as
|
|
7874
|
+
import { Address as Address4 } from "@stellar/stellar-sdk";
|
|
7247
7875
|
function credentialAddress(entry) {
|
|
7248
7876
|
try {
|
|
7249
7877
|
const credentials = entry.credentials();
|
|
7250
7878
|
if (credentials.switch().name !== "sorobanCredentialsAddress") {
|
|
7251
7879
|
return void 0;
|
|
7252
7880
|
}
|
|
7253
|
-
return
|
|
7881
|
+
return Address4.fromScAddress(credentials.address().address()).toString();
|
|
7254
7882
|
} catch {
|
|
7255
7883
|
return void 0;
|
|
7256
7884
|
}
|
|
@@ -7269,7 +7897,7 @@ var SIMULATE_FEE = "100";
|
|
|
7269
7897
|
var SIMULATE_TIMEOUT_SECONDS = 30;
|
|
7270
7898
|
var RECORD_NONROOT_AUTH = "record_allow_nonroot";
|
|
7271
7899
|
function hexToBytes(hex) {
|
|
7272
|
-
return
|
|
7900
|
+
return Buffer17.from(hex.replace(/^0x/iu, ""), "hex");
|
|
7273
7901
|
}
|
|
7274
7902
|
function optionalSweepCiphertext(artifacts) {
|
|
7275
7903
|
return {
|
|
@@ -7311,6 +7939,7 @@ async function inspectRelayerSweepKyt(input) {
|
|
|
7311
7939
|
...input.prepared.transactArtifacts?.applicationIdsPlaintext ? {
|
|
7312
7940
|
applicationIdsPlaintext: input.prepared.transactArtifacts.applicationIdsPlaintext
|
|
7313
7941
|
} : {},
|
|
7942
|
+
...input.prepared.transactArtifacts?.zkConfigNonce === void 0 ? {} : { zkConfigNonce: input.prepared.transactArtifacts.zkConfigNonce },
|
|
7314
7943
|
networkPassphrase: environment.network.networkPassphrase,
|
|
7315
7944
|
sorobanRpcUrl: environment.network.rpcUrl,
|
|
7316
7945
|
transactEnvironment: environment
|
|
@@ -7322,8 +7951,11 @@ async function simulateSweepAuthEntries(input) {
|
|
|
7322
7951
|
const account = await server.getAccount(input.relayerPublicKey);
|
|
7323
7952
|
const operation = new Contract(environment.network.poolContract).call(
|
|
7324
7953
|
"transact",
|
|
7325
|
-
new
|
|
7326
|
-
nativeToScVal2(
|
|
7954
|
+
new Address5(input.relayerPublicKey).toScVal(),
|
|
7955
|
+
nativeToScVal2(
|
|
7956
|
+
transactNonceFromArtifacts(input.prepared.transactArtifacts, environment),
|
|
7957
|
+
{ type: "u64" }
|
|
7958
|
+
),
|
|
7327
7959
|
nativeToScVal2(hexToBytes(input.artifacts.proofHex), { type: "bytes" }),
|
|
7328
7960
|
nativeToScVal2(hexToBytes(input.artifacts.publicHex), { type: "bytes" }),
|
|
7329
7961
|
nativeToScVal2(hexToBytes(input.artifacts.ciphertextHex ?? ""), { type: "bytes" }),
|
|
@@ -7360,6 +7992,7 @@ async function unsignedEscrowAuthorizationForSweep(input) {
|
|
|
7360
7992
|
});
|
|
7361
7993
|
const auth = await simulateSweepAuthEntries({
|
|
7362
7994
|
artifacts,
|
|
7995
|
+
prepared: input.prepared,
|
|
7363
7996
|
transactEnvironment: input.transactEnvironment,
|
|
7364
7997
|
relayerPublicKey,
|
|
7365
7998
|
approval
|
|
@@ -7391,15 +8024,15 @@ async function loadDefaultStellarBrowserAssets(options) {
|
|
|
7391
8024
|
}
|
|
7392
8025
|
|
|
7393
8026
|
// src/transact/private-address/temporary-recipient.ts
|
|
7394
|
-
import { PrivacyPoolSDK as
|
|
8027
|
+
import { PrivacyPoolSDK as PrivacyPoolSDK5 } from "@arcanetech/stellar-privacy-pool-zk-sdk";
|
|
7395
8028
|
var COORDINATE_HEX_LENGTH3 = 64;
|
|
7396
8029
|
async function generateRandomDepositScalarHex() {
|
|
7397
8030
|
await getPrivacyPoolService().getInitializedSdk();
|
|
7398
|
-
return
|
|
8031
|
+
return PrivacyPoolSDK5.generateRandomScalarHex32();
|
|
7399
8032
|
}
|
|
7400
8033
|
async function generateTemporaryRecipientPrivateAddress() {
|
|
7401
8034
|
await getPrivacyPoolService().getInitializedSdk();
|
|
7402
|
-
const temporaryScalarHex =
|
|
8035
|
+
const temporaryScalarHex = PrivacyPoolSDK5.generateRandomScalarHex32();
|
|
7403
8036
|
const sdk = await getPrivacyPoolService().getInitializedSdk();
|
|
7404
8037
|
const point = sdk.ecdhEphemeralPublicKeyFromScalarHex(temporaryScalarHex);
|
|
7405
8038
|
const publicKeyXHex = point.x.padStart(COORDINATE_HEX_LENGTH3, "0");
|
|
@@ -7493,7 +8126,7 @@ var RELAY_SIGNAL_INDEX_PUBLIC_DEPOSIT = 91;
|
|
|
7493
8126
|
var RELAY_SIGNAL_INDEX_PUBLIC_WITHDRAWAL = 92;
|
|
7494
8127
|
|
|
7495
8128
|
// src/transact/relay/signals.ts
|
|
7496
|
-
import { Buffer as
|
|
8129
|
+
import { Buffer as Buffer18 } from "buffer";
|
|
7497
8130
|
|
|
7498
8131
|
// src/transact/relay/layout-profile.ts
|
|
7499
8132
|
var FIELD_BYTES = 32;
|
|
@@ -7573,7 +8206,7 @@ function relayLayoutProfileForNonce(nonce) {
|
|
|
7573
8206
|
|
|
7574
8207
|
// src/transact/relay/signals.ts
|
|
7575
8208
|
function decodePublicSignalBytes(publicSignals) {
|
|
7576
|
-
return
|
|
8209
|
+
return Buffer18.from(publicSignals.replace(/^0x/iu, ""), "hex");
|
|
7577
8210
|
}
|
|
7578
8211
|
function hasSupportedLengthPrefix(bytes, signalCount) {
|
|
7579
8212
|
const expected = RELAY_TRANSACT_SIGNAL_PREFIX_BYTES + signalCount * RELAY_TRANSACT_FIELD_BYTES;
|
|
@@ -7600,7 +8233,7 @@ function sliceSupportedPublicSignalFields(publicSignals, zkConfigNonce = DEFAULT
|
|
|
7600
8233
|
const body = hasSupportedLengthPrefix(bytes, profile.signalCount) ? bytes.subarray(RELAY_TRANSACT_SIGNAL_PREFIX_BYTES) : bytes;
|
|
7601
8234
|
return Array.from(
|
|
7602
8235
|
{ length: profile.signalCount },
|
|
7603
|
-
(_unused, index) =>
|
|
8236
|
+
(_unused, index) => Buffer18.from(
|
|
7604
8237
|
body.subarray(
|
|
7605
8238
|
index * RELAY_TRANSACT_FIELD_BYTES,
|
|
7606
8239
|
(index + 1) * RELAY_TRANSACT_FIELD_BYTES
|
|
@@ -7655,10 +8288,11 @@ function requirePreparedArtifacts(prepared) {
|
|
|
7655
8288
|
};
|
|
7656
8289
|
}
|
|
7657
8290
|
function prepareRelayTransactPackageFromPrepared(input) {
|
|
8291
|
+
const zkConfigNonce = input.zkConfigNonce ?? input.prepared.transactArtifacts?.zkConfigNonce;
|
|
7658
8292
|
return prepareRelayTransactPackage({
|
|
7659
8293
|
poolSelector: input.poolSelector,
|
|
7660
8294
|
...requirePreparedArtifacts(input.prepared),
|
|
7661
|
-
...
|
|
8295
|
+
...zkConfigNonce === void 0 ? {} : { zkConfigNonce },
|
|
7662
8296
|
...input.keyVersionHints ? { keyVersionHints: input.keyVersionHints } : {}
|
|
7663
8297
|
});
|
|
7664
8298
|
}
|
|
@@ -7768,6 +8402,7 @@ function requiredSubmissionMethod(prepared, zkConfigNonce = DEFAULT_ZK_CONFIG_NO
|
|
|
7768
8402
|
return result.method;
|
|
7769
8403
|
}
|
|
7770
8404
|
export {
|
|
8405
|
+
BINDING_ZK_NONCE,
|
|
7771
8406
|
BundledZkCircuit2 as BundledZkCircuit,
|
|
7772
8407
|
COMMITMENT_V2_ZK_NONCE,
|
|
7773
8408
|
DEFAULT_STEALTH_SIGN_NONCE as DEFAULT_PRIVATE_ADDRESS_SIGN_NONCE,
|
|
@@ -7796,6 +8431,7 @@ export {
|
|
|
7796
8431
|
RELAY_TRANSACT_PACKAGE_VERSION_V1,
|
|
7797
8432
|
RELAY_TRANSACT_SIGNAL_PREFIX_BYTES,
|
|
7798
8433
|
RELAY_TRANSACT_SUPPORTED_SIGNAL_COUNT,
|
|
8434
|
+
SIX_BY_SIX_BINDING_ZK_NONCE,
|
|
7799
8435
|
SIX_BY_SIX_ZK_NONCE,
|
|
7800
8436
|
STANDARD_ZK_CONFIG_NONCE,
|
|
7801
8437
|
SUBMISSION_METHOD,
|