@arcanetech/privacy-sdk-stellar 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -0
- package/dist/index.js +215 -18
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +6 -0
- package/dist/node.js +209 -17
- package/dist/node.js.map +1 -1
- package/dist/transact/index.d.ts +6 -0
- package/dist/transact/index.js +131 -2
- package/dist/transact/index.js.map +1 -1
- package/generated/contract/README.md +2 -2
- package/generated/contract/dist/index.d.ts +106 -8
- package/generated/contract/dist/index.js +36 -8
- package/generated/contract/package.json +1 -1
- package/generated/contract/src/index.ts +98 -11
- package/generated/registry/package.json +1 -1
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -252,6 +252,12 @@ interface StellarKytEnvironment {
|
|
|
252
252
|
}
|
|
253
253
|
interface StellarTransactEnvironment {
|
|
254
254
|
network: StellarNetworkConfig;
|
|
255
|
+
/**
|
|
256
|
+
* Nonce (persistent storage key) of the pool's `ZkConfig` entry this
|
|
257
|
+
* environment's proofs/circuit shape target. Defaults to `0n` (the
|
|
258
|
+
* standard circuit) when omitted.
|
|
259
|
+
*/
|
|
260
|
+
zkConfigNonce?: bigint;
|
|
255
261
|
auditPublicKey?: AuditPublicKey;
|
|
256
262
|
kyt: StellarKytEnvironment;
|
|
257
263
|
signTransaction?: StellarSignTransaction;
|
package/dist/index.js
CHANGED
|
@@ -486,7 +486,7 @@ function createInternalPoolContractClient(input) {
|
|
|
486
486
|
networkPassphrase: input.networkPassphrase,
|
|
487
487
|
walletPublicKey: input.walletPublicKey
|
|
488
488
|
});
|
|
489
|
-
|
|
489
|
+
const client = new PrivacyPoolContractClient({
|
|
490
490
|
contractId: input.contractId,
|
|
491
491
|
networkPassphrase: input.networkPassphrase,
|
|
492
492
|
rpcUrl: input.sorobanRpcUrl,
|
|
@@ -494,6 +494,7 @@ function createInternalPoolContractClient(input) {
|
|
|
494
494
|
publicKey: input.walletPublicKey,
|
|
495
495
|
signTransaction: signBinding
|
|
496
496
|
});
|
|
497
|
+
return client;
|
|
497
498
|
}
|
|
498
499
|
|
|
499
500
|
// src/contracts/registry/create-registry-client.ts
|
|
@@ -1693,7 +1694,7 @@ function pickRecordsForSpendAmount(input) {
|
|
|
1693
1694
|
if (selectedTotal >= input.amount) {
|
|
1694
1695
|
return selected;
|
|
1695
1696
|
}
|
|
1696
|
-
if (input.kind === "transfer" && selected.length >= 2) {
|
|
1697
|
+
if ((input.kind === "transfer" || input.kind === "withdraw") && selected.length >= 2) {
|
|
1697
1698
|
throw insufficientStateError3(
|
|
1698
1699
|
"missing_private_records",
|
|
1699
1700
|
"Storage does not contain enough private records for this operation.",
|
|
@@ -6415,12 +6416,17 @@ function enrichWithdrawOutputRecords(prepared, proof) {
|
|
|
6415
6416
|
precommitementHex: changeCoin.precommitementHex
|
|
6416
6417
|
}));
|
|
6417
6418
|
}
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6419
|
+
function buildWithdrawFinalizeArtifacts(proof, context) {
|
|
6420
|
+
return {
|
|
6421
|
+
proofHex: proof.proof_hex,
|
|
6422
|
+
publicHex: proof.public_hex,
|
|
6423
|
+
applicationIdsPlaintext: proof.applicationIdsPlaintext,
|
|
6424
|
+
tokenAddress: context.tokenAddress,
|
|
6425
|
+
walletPublicKey: context.walletPublicKey,
|
|
6426
|
+
executeFinalizeRequired: false
|
|
6427
|
+
};
|
|
6428
|
+
}
|
|
6429
|
+
async function finalizeSingleWithdrawAtExecute(prepared, environment, poolService, withdrawFrom) {
|
|
6424
6430
|
const context = await buildSpendProofContextAtExecute({
|
|
6425
6431
|
prepared,
|
|
6426
6432
|
environment,
|
|
@@ -6441,14 +6447,71 @@ async function finalizeWithdrawAtExecute(prepared, environment, poolService) {
|
|
|
6441
6447
|
tokenAddress: context.tokenAddress
|
|
6442
6448
|
});
|
|
6443
6449
|
enrichWithdrawOutputRecords(prepared, proof);
|
|
6444
|
-
return
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6450
|
+
return buildWithdrawFinalizeArtifacts(proof, context);
|
|
6451
|
+
}
|
|
6452
|
+
async function finalizeDualWithdrawAtExecute(prepared, environment, poolService, withdrawFrom) {
|
|
6453
|
+
const [, secondaryRecord] = prepared.consumedRecords;
|
|
6454
|
+
if (!secondaryRecord) {
|
|
6455
|
+
throw new Error("Dual withdraw execution requires two private input records.");
|
|
6456
|
+
}
|
|
6457
|
+
const context = await buildSpendProofContextAtExecute({
|
|
6458
|
+
prepared,
|
|
6459
|
+
environment,
|
|
6460
|
+
recipientPrivateAddressStpl1: withdrawFrom
|
|
6461
|
+
});
|
|
6462
|
+
const secondary = await readCoinEphemeralForRecord({
|
|
6463
|
+
record: secondaryRecord,
|
|
6464
|
+
environment,
|
|
6449
6465
|
walletPublicKey: context.walletPublicKey,
|
|
6450
|
-
|
|
6451
|
-
};
|
|
6466
|
+
commitments: context.commitments
|
|
6467
|
+
});
|
|
6468
|
+
const totalNotes = BigInt(context.coin.value) + BigInt(secondary.coin.value);
|
|
6469
|
+
const changeStroops = totalNotes - prepared.intent.amount;
|
|
6470
|
+
const proof = await poolService.prepareWithdrawTransactProofDual({
|
|
6471
|
+
coinA: context.coin,
|
|
6472
|
+
coinB: secondary.coin,
|
|
6473
|
+
state: { commitments: context.commitments },
|
|
6474
|
+
destinationStellarAddress: prepared.intent.to,
|
|
6475
|
+
privKeyScalarHex: context.senderPrivKeyScalarHex,
|
|
6476
|
+
depositorEphemeralAKey: serializeEphemeralKeyString({
|
|
6477
|
+
xHex: context.ephemeral.xHex,
|
|
6478
|
+
yHex: context.ephemeral.yHex
|
|
6479
|
+
}),
|
|
6480
|
+
depositorEphemeralBKey: serializeEphemeralKeyString({
|
|
6481
|
+
xHex: secondary.ephemeral.xHex,
|
|
6482
|
+
yHex: secondary.ephemeral.yHex
|
|
6483
|
+
}),
|
|
6484
|
+
withdrawAmountStroops: prepared.intent.amount,
|
|
6485
|
+
changePrivateAddressStpl1: changeStroops > 0n ? withdrawFrom : void 0,
|
|
6486
|
+
tokenAddress: context.tokenAddress
|
|
6487
|
+
});
|
|
6488
|
+
enrichWithdrawOutputRecords(prepared, proof);
|
|
6489
|
+
return buildWithdrawFinalizeArtifacts(proof, context);
|
|
6490
|
+
}
|
|
6491
|
+
async function finalizeWithdrawAtExecute(prepared, environment, poolService) {
|
|
6492
|
+
if (prepared.kind !== "withdraw") {
|
|
6493
|
+
throw new Error("Withdraw finalize requires a withdraw operation.");
|
|
6494
|
+
}
|
|
6495
|
+
const withdrawIntent = prepared.intent;
|
|
6496
|
+
const withdrawFrom = withdrawIntent.from;
|
|
6497
|
+
const recordCount = prepared.consumedRecords.length;
|
|
6498
|
+
if (recordCount === 1) {
|
|
6499
|
+
return finalizeSingleWithdrawAtExecute(
|
|
6500
|
+
prepared,
|
|
6501
|
+
environment,
|
|
6502
|
+
poolService,
|
|
6503
|
+
withdrawFrom
|
|
6504
|
+
);
|
|
6505
|
+
}
|
|
6506
|
+
if (recordCount === 2) {
|
|
6507
|
+
return finalizeDualWithdrawAtExecute(
|
|
6508
|
+
prepared,
|
|
6509
|
+
environment,
|
|
6510
|
+
poolService,
|
|
6511
|
+
withdrawFrom
|
|
6512
|
+
);
|
|
6513
|
+
}
|
|
6514
|
+
throw new Error("Confidential withdraw execution supports at most two input notes.");
|
|
6452
6515
|
}
|
|
6453
6516
|
async function finalizeSpendOperationAtExecute(prepared, environment, poolService) {
|
|
6454
6517
|
if (prepared.kind !== "transfer" && prepared.kind !== "withdraw") {
|
|
@@ -6606,6 +6669,12 @@ async function registerKytPassage(parameters) {
|
|
|
6606
6669
|
await waitForKytRegistration({ server, hash: result.hash });
|
|
6607
6670
|
}
|
|
6608
6671
|
|
|
6672
|
+
// src/transact/environment/zk-config-nonce.ts
|
|
6673
|
+
var DEFAULT_ZK_CONFIG_NONCE = 0n;
|
|
6674
|
+
function resolveZkConfigNonce(transactEnvironment) {
|
|
6675
|
+
return transactEnvironment.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
|
|
6676
|
+
}
|
|
6677
|
+
|
|
6609
6678
|
// src/transact/kyt/passage/inspect.ts
|
|
6610
6679
|
function buildApplicationIdHints(applicationId) {
|
|
6611
6680
|
return [applicationId, applicationId, applicationId, applicationId];
|
|
@@ -6659,6 +6728,7 @@ async function requestKytPassageForPoolInteraction(input) {
|
|
|
6659
6728
|
decryptedAuditSlots: input.decryptedAuditSlots,
|
|
6660
6729
|
onboarding: input.onboarding,
|
|
6661
6730
|
nonce: buildNonce(),
|
|
6731
|
+
zkConfigNonce: resolveZkConfigNonce(input.transactEnvironment),
|
|
6662
6732
|
currentLedger
|
|
6663
6733
|
},
|
|
6664
6734
|
kytJsonReplacer
|
|
@@ -6681,11 +6751,123 @@ async function requestKytPassageForPoolInteraction(input) {
|
|
|
6681
6751
|
return body;
|
|
6682
6752
|
}
|
|
6683
6753
|
|
|
6754
|
+
// src/transact/submit/zk-config-ttl.ts
|
|
6755
|
+
import {
|
|
6756
|
+
Address as Address2,
|
|
6757
|
+
Operation as Operation2,
|
|
6758
|
+
SorobanDataBuilder,
|
|
6759
|
+
TransactionBuilder as TransactionBuilder2,
|
|
6760
|
+
rpc as rpc4,
|
|
6761
|
+
xdr as xdr3
|
|
6762
|
+
} from "@stellar/stellar-sdk";
|
|
6763
|
+
var ZK_CONFIG_TTL_THRESHOLD_LEDGERS = 1e5;
|
|
6764
|
+
var ZK_CONFIG_TTL_EXTEND_TO_LEDGERS = 5e5;
|
|
6765
|
+
var EXTEND_TTL_FEE_STROOPS = "1000000";
|
|
6766
|
+
var EXTEND_TTL_TIMEOUT_SECONDS = 300;
|
|
6767
|
+
var EXTEND_TTL_MAX_POLLS = 60;
|
|
6768
|
+
var EXTEND_TTL_POLL_INTERVAL_MS = 1e3;
|
|
6769
|
+
async function waitForExtendFootprintTtlConfirmation(parameters) {
|
|
6770
|
+
for (let attempt = 0; attempt < EXTEND_TTL_MAX_POLLS; attempt += 1) {
|
|
6771
|
+
const response = await parameters.server.getTransaction(parameters.hash);
|
|
6772
|
+
if (response.status === "SUCCESS") {
|
|
6773
|
+
return;
|
|
6774
|
+
}
|
|
6775
|
+
if (response.status === "FAILED") {
|
|
6776
|
+
throw new Error("ZK config TTL extension failed on-chain");
|
|
6777
|
+
}
|
|
6778
|
+
await new Promise((resolve) => {
|
|
6779
|
+
setTimeout(resolve, EXTEND_TTL_POLL_INTERVAL_MS);
|
|
6780
|
+
});
|
|
6781
|
+
}
|
|
6782
|
+
throw new Error("ZK config TTL extension was not confirmed in time");
|
|
6783
|
+
}
|
|
6784
|
+
function zkConfigLedgerKey(contractId, nonce) {
|
|
6785
|
+
const configKeyScValue = xdr3.ScVal.scvVec([
|
|
6786
|
+
xdr3.ScVal.scvSymbol("Config"),
|
|
6787
|
+
xdr3.ScVal.scvU64(xdr3.Uint64.fromString(nonce.toString()))
|
|
6788
|
+
]);
|
|
6789
|
+
return xdr3.LedgerKey.contractData(
|
|
6790
|
+
new xdr3.LedgerKeyContractData({
|
|
6791
|
+
contract: new Address2(contractId).toScAddress(),
|
|
6792
|
+
key: configKeyScValue,
|
|
6793
|
+
durability: xdr3.ContractDataDurability.persistent()
|
|
6794
|
+
})
|
|
6795
|
+
);
|
|
6796
|
+
}
|
|
6797
|
+
async function needsTtlExtension(parameters) {
|
|
6798
|
+
const [entriesResponse, latestLedger] = await Promise.all([
|
|
6799
|
+
parameters.server.getLedgerEntries(parameters.ledgerKey),
|
|
6800
|
+
parameters.server.getLatestLedger()
|
|
6801
|
+
]);
|
|
6802
|
+
const entry = entriesResponse.entries.at(0);
|
|
6803
|
+
if (!entry || entry.liveUntilLedgerSeq === void 0) {
|
|
6804
|
+
return false;
|
|
6805
|
+
}
|
|
6806
|
+
const remainingLedgers = entry.liveUntilLedgerSeq - latestLedger.sequence;
|
|
6807
|
+
return remainingLedgers < ZK_CONFIG_TTL_THRESHOLD_LEDGERS;
|
|
6808
|
+
}
|
|
6809
|
+
async function submitExtendFootprintTtlTransaction(parameters) {
|
|
6810
|
+
const sourceAccount = await parameters.server.getAccount(parameters.sourcePublicKey);
|
|
6811
|
+
const transaction = new TransactionBuilder2(sourceAccount, {
|
|
6812
|
+
fee: EXTEND_TTL_FEE_STROOPS,
|
|
6813
|
+
networkPassphrase: parameters.networkPassphrase
|
|
6814
|
+
}).addOperation(
|
|
6815
|
+
Operation2.extendFootprintTtl({ extendTo: ZK_CONFIG_TTL_EXTEND_TO_LEDGERS })
|
|
6816
|
+
).setSorobanData(
|
|
6817
|
+
new SorobanDataBuilder().setReadOnly([parameters.ledgerKey]).build()
|
|
6818
|
+
).setTimeout(EXTEND_TTL_TIMEOUT_SECONDS).build();
|
|
6819
|
+
const preparedTransaction = await parameters.server.prepareTransaction(transaction);
|
|
6820
|
+
const { signedTxXdr } = await parameters.signTransaction({
|
|
6821
|
+
xdr: preparedTransaction.toXDR(),
|
|
6822
|
+
networkPassphrase: parameters.networkPassphrase,
|
|
6823
|
+
address: parameters.sourcePublicKey
|
|
6824
|
+
});
|
|
6825
|
+
const signedTransaction = TransactionBuilder2.fromXDR(
|
|
6826
|
+
signedTxXdr,
|
|
6827
|
+
parameters.networkPassphrase
|
|
6828
|
+
);
|
|
6829
|
+
const result = await parameters.server.sendTransaction(signedTransaction);
|
|
6830
|
+
const status = String(result.status);
|
|
6831
|
+
if (status !== "PENDING" && status !== "SUCCESS") {
|
|
6832
|
+
throw new Error(`ZK config TTL extension submit failed: ${status}`);
|
|
6833
|
+
}
|
|
6834
|
+
await waitForExtendFootprintTtlConfirmation({
|
|
6835
|
+
server: parameters.server,
|
|
6836
|
+
hash: result.hash
|
|
6837
|
+
});
|
|
6838
|
+
}
|
|
6839
|
+
async function extendZkConfigTtlIfNeeded(parameters) {
|
|
6840
|
+
if (!parameters.signTransaction) {
|
|
6841
|
+
return;
|
|
6842
|
+
}
|
|
6843
|
+
const server = new rpc4.Server(parameters.sorobanRpcUrl, { allowHttp: true });
|
|
6844
|
+
const ledgerKey = zkConfigLedgerKey(parameters.contractId, parameters.nonce);
|
|
6845
|
+
if (!await needsTtlExtension({ server, ledgerKey })) {
|
|
6846
|
+
return;
|
|
6847
|
+
}
|
|
6848
|
+
await submitExtendFootprintTtlTransaction({
|
|
6849
|
+
server,
|
|
6850
|
+
ledgerKey,
|
|
6851
|
+
networkPassphrase: parameters.networkPassphrase,
|
|
6852
|
+
sourcePublicKey: parameters.sourcePublicKey,
|
|
6853
|
+
signTransaction: parameters.signTransaction
|
|
6854
|
+
});
|
|
6855
|
+
}
|
|
6856
|
+
|
|
6684
6857
|
// src/transact/submit/pool-transact.ts
|
|
6685
6858
|
import { Buffer as Buffer17 } from "buffer";
|
|
6686
6859
|
async function submitPoolTransact(parameters) {
|
|
6860
|
+
await extendZkConfigTtlIfNeeded({
|
|
6861
|
+
sorobanRpcUrl: parameters.sorobanRpcUrl,
|
|
6862
|
+
networkPassphrase: parameters.networkPassphrase,
|
|
6863
|
+
contractId: parameters.contractId,
|
|
6864
|
+
nonce: parameters.nonce,
|
|
6865
|
+
sourcePublicKey: parameters.from,
|
|
6866
|
+
signTransaction: parameters.transactEnvironment.signTransaction
|
|
6867
|
+
});
|
|
6687
6868
|
const assembledTransaction = await parameters.contractClient.transact({
|
|
6688
6869
|
from: parameters.from,
|
|
6870
|
+
nonce: parameters.nonce,
|
|
6689
6871
|
proof_bytes: Buffer17.from(parameters.proofHex.replace(/^0x/iu, ""), "hex"),
|
|
6690
6872
|
pub_signals_bytes: Buffer17.from(parameters.publicHex.replace(/^0x/iu, ""), "hex"),
|
|
6691
6873
|
onboarding: parameters.onboarding,
|
|
@@ -6724,11 +6906,16 @@ async function submitSorobanConfidentialTransfer(input) {
|
|
|
6724
6906
|
});
|
|
6725
6907
|
return submitPoolTransact({
|
|
6726
6908
|
contractClient: poolClient,
|
|
6909
|
+
contractId: input.contractId,
|
|
6727
6910
|
from: input.walletPublicKey,
|
|
6911
|
+
nonce: resolveZkConfigNonce(input.transactEnvironment),
|
|
6728
6912
|
proofHex: input.proofHex,
|
|
6729
6913
|
publicHex: input.publicHex,
|
|
6730
6914
|
...input.onboarding ? { onboarding: input.onboarding } : {},
|
|
6731
|
-
approval
|
|
6915
|
+
approval,
|
|
6916
|
+
networkPassphrase: input.networkPassphrase,
|
|
6917
|
+
sorobanRpcUrl: input.sorobanRpcUrl,
|
|
6918
|
+
transactEnvironment: input.transactEnvironment
|
|
6732
6919
|
});
|
|
6733
6920
|
}
|
|
6734
6921
|
|
|
@@ -6757,10 +6944,15 @@ async function submitPreparedDeposit(prepared, environment) {
|
|
|
6757
6944
|
});
|
|
6758
6945
|
return submitPoolTransact({
|
|
6759
6946
|
contractClient: poolClient,
|
|
6947
|
+
contractId: environment.network.poolContract,
|
|
6760
6948
|
from: artifacts.walletPublicKey,
|
|
6949
|
+
nonce: resolveZkConfigNonce(environment),
|
|
6761
6950
|
proofHex: artifacts.proofHex,
|
|
6762
6951
|
publicHex: artifacts.publicHex,
|
|
6763
|
-
approval
|
|
6952
|
+
approval,
|
|
6953
|
+
networkPassphrase: environment.network.networkPassphrase,
|
|
6954
|
+
sorobanRpcUrl: environment.network.rpcUrl,
|
|
6955
|
+
transactEnvironment: environment
|
|
6764
6956
|
});
|
|
6765
6957
|
}
|
|
6766
6958
|
async function submitPreparedPoolTransact(prepared, environment) {
|
|
@@ -7009,10 +7201,15 @@ async function submitSorobanDeposit(input) {
|
|
|
7009
7201
|
});
|
|
7010
7202
|
return submitPoolTransact({
|
|
7011
7203
|
contractClient: poolClient,
|
|
7204
|
+
contractId: input.contractId,
|
|
7012
7205
|
from: input.walletPublicKey,
|
|
7206
|
+
nonce: resolveZkConfigNonce(input.transactEnvironment),
|
|
7013
7207
|
proofHex: proof_hex,
|
|
7014
7208
|
publicHex: public_hex,
|
|
7015
|
-
approval
|
|
7209
|
+
approval,
|
|
7210
|
+
networkPassphrase: input.networkPassphrase,
|
|
7211
|
+
sorobanRpcUrl: input.sorobanRpcUrl,
|
|
7212
|
+
transactEnvironment: input.transactEnvironment
|
|
7016
7213
|
});
|
|
7017
7214
|
}
|
|
7018
7215
|
export {
|