@arcanetech/privacy-sdk-stellar 0.6.2 → 1.0.0-rc.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/node.d.ts CHANGED
@@ -340,13 +340,28 @@ interface FetchContractMerkleResult {
340
340
  nodes?: StellarLeanImtNode[];
341
341
  }
342
342
 
343
- type StellarTransactionDetails = {
344
- txHash: string;
345
- status: StellarTransactionConfirmationStatus;
346
- ledger?: number;
347
- createdAt?: string;
348
- invokedPoolContractId?: string;
349
- transferAmountRaw?: string;
343
+ type IncomingNoteDeadReason = 'commitment_mismatch' | 'nullifier_consumed';
344
+ type IncomingNoteAssessment = {
345
+ kind: 'dead';
346
+ reason: IncomingNoteDeadReason;
347
+ } | {
348
+ kind: 'pending';
349
+ } | {
350
+ kind: 'spendable';
351
+ };
352
+ type IncomingNoteFields = {
353
+ value: string;
354
+ nullifier: string;
355
+ secret: string;
356
+ commitment: string;
357
+ asset_hi: string;
358
+ asset_lo: string;
359
+ application_id?: string;
360
+ };
361
+ type AssessIncomingNoteInput = {
362
+ note: IncomingNoteFields;
363
+ commitmentHex: string;
364
+ privKeyScalarHex: string;
350
365
  };
351
366
 
352
367
  interface StellarPublicBalanceInput {
@@ -452,6 +467,20 @@ type ComposedStellarStateService = ReturnType<typeof composeStellarStateService>
452
467
 
453
468
  type StellarStateService = ComposedStellarStateService;
454
469
 
470
+ type AssessIncomingNoteClientInput = AssessIncomingNoteInput & {
471
+ walletPublicKey: string;
472
+ poolContractId?: string;
473
+ };
474
+
475
+ type StellarTransactionDetails = {
476
+ txHash: string;
477
+ status: StellarTransactionConfirmationStatus;
478
+ ledger?: number;
479
+ createdAt?: string;
480
+ invokedPoolContractId?: string;
481
+ transferAmountRaw?: string;
482
+ };
483
+
455
484
  declare function composeStellarPrivacyClient(config: ResolvedStellarPrivacyClientConfig): {
456
485
  state: {
457
486
  getTransactionStatus(txHash: string): Promise<StellarTransactionStatus | undefined>;
@@ -567,6 +596,7 @@ declare function composeStellarPrivacyClient(config: ResolvedStellarPrivacyClien
567
596
  }) => Promise<StellarTransactionStatus>;
568
597
  fetchTransactionConfirmationStatus: (txHash: string) => Promise<StellarTransactionStatus>;
569
598
  getTransactionDetails: (txHash: string) => Promise<StellarTransactionDetails>;
599
+ assessIncomingNote: (assessmentInput: AssessIncomingNoteClientInput) => Promise<IncomingNoteAssessment>;
570
600
  checkRegistrationStatus: (registrationInput: {
571
601
  address: StellarAddress;
572
602
  walletPublicKey: string;
@@ -675,6 +705,7 @@ type StellarPrivacyClient = {
675
705
  registerPrivateAddress: StellarPrivacyClientNetwork['registerPrivateAddress'];
676
706
  resolveTransferRecipient: StellarPrivacyClientNetwork['resolveTransferRecipient'];
677
707
  checkPrivateRecordSpendStatus: StellarPrivacyClientNetwork['checkPrivateRecordSpendStatus'];
708
+ assessIncomingNote: StellarPrivacyClientNetwork['assessIncomingNote'];
678
709
  waitForTransactionConfirmation: StellarPrivacyClientNetwork['waitForTransactionConfirmation'];
679
710
  fetchTransactionConfirmationStatus: StellarPrivacyClientNetwork['fetchTransactionConfirmationStatus'];
680
711
  getTransactionDetails: StellarPrivacyClientNetwork['getTransactionDetails'];
package/dist/node.js CHANGED
@@ -932,14 +932,39 @@ function uniformApplicationIdHints(applicationId, nAuditSlots) {
932
932
  }
933
933
 
934
934
  // src/transact/proofs/confidential/helpers.ts
935
- import { withdrawObjectFromMerkleWitness } from "@arcanetech/stellar-privacy-pool-zk-sdk";
935
+ import {
936
+ withdrawObjectFromEscrowMerkleWitness,
937
+ withdrawObjectFromMerkleWitness
938
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
936
939
  var MIN_CONFIDENTIAL_TRANSFER_STROOPS = 1n;
937
940
  var ZERO_STROOPS = 0n;
941
+ function escrowSpendWitnessFromLimbs(limbs, derivedScalarHex) {
942
+ const nonce = limbs.nonceDecimal?.trim() ?? "";
943
+ if (!nonce) {
944
+ throw new Error("Escrow claimant limbs require nonceDecimal");
945
+ }
946
+ return {
947
+ nonce,
948
+ recipientHi: limbs.recipientHi,
949
+ recipientLo: limbs.recipientLo,
950
+ derivedScalarHex
951
+ };
952
+ }
938
953
  function withdrawWitnessForCoin(parameters) {
939
954
  const { sdk, coin, state } = parameters;
940
955
  const witness = withdrawMerkleWitnessFromTree({ sdk, coin, state });
941
956
  const withdrawApplicationId = coin.application_id ?? parameters.applicationId;
942
- const withdrawObject = withdrawObjectFromMerkleWitness(
957
+ const withdrawObject = parameters.escrow ? withdrawObjectFromEscrowMerkleWitness(
958
+ witness,
959
+ parameters.ownerPubHex,
960
+ withdrawApplicationId,
961
+ parameters.escrow.derivedScalarHex,
962
+ {
963
+ nonce: parameters.escrow.nonce,
964
+ recipientHi: parameters.escrow.recipientHi,
965
+ recipientLo: parameters.escrow.recipientLo
966
+ }
967
+ ) : withdrawObjectFromMerkleWitness(
943
968
  witness,
944
969
  parameters.ownerPubHex,
945
970
  withdrawApplicationId,
@@ -948,21 +973,21 @@ function withdrawWitnessForCoin(parameters) {
948
973
  return { witness, withdrawObject };
949
974
  }
950
975
  function dualWithdrawLegsWithSharedRoot(parameters) {
951
- const legA = withdrawWitnessForCoin({
976
+ const shared = {
952
977
  sdk: parameters.sdk,
953
- coin: parameters.coinA,
954
978
  state: parameters.state,
955
979
  ownerPubHex: parameters.ownerPubHex,
956
980
  privKeyScalar: parameters.privKeyScalar,
957
- applicationId: parameters.applicationId
981
+ applicationId: parameters.applicationId,
982
+ ...parameters.escrow ? { escrow: parameters.escrow } : {}
983
+ };
984
+ const legA = withdrawWitnessForCoin({
985
+ ...shared,
986
+ coin: parameters.coinA
958
987
  });
959
988
  const legB = withdrawWitnessForCoin({
960
- sdk: parameters.sdk,
961
- coin: parameters.coinB,
962
- state: parameters.state,
963
- ownerPubHex: parameters.ownerPubHex,
964
- privKeyScalar: parameters.privKeyScalar,
965
- applicationId: parameters.applicationId
989
+ ...shared,
990
+ coin: parameters.coinB
966
991
  });
967
992
  if (legA.witness.stateRoot !== legB.witness.stateRoot) {
968
993
  throw new Error("Merkle state root mismatch between input coins");
@@ -1233,7 +1258,10 @@ function ed25519PublicKeyHexFromStellarAccount(address) {
1233
1258
  }
1234
1259
 
1235
1260
  // src/transact/encoding/priv-key-scalar-from-recipient-hex.ts
1236
- import { canonicalBabyJubScalarFromInteger } from "@arcanetech/stellar-privacy-pool-zk-sdk";
1261
+ import {
1262
+ canonicalBabyJubScalarFromInteger,
1263
+ reduceDerivedEscrowSpendScalar
1264
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
1237
1265
  var SCALAR_HEX_CHAR_LENGTH = 64;
1238
1266
  var DECIMAL_RADIX2 = 10;
1239
1267
  function normalizeRecipientScalarHex(hexInput) {
@@ -1256,6 +1284,25 @@ function privKeyScalarDecimalFromRecipientScalarHex(hexInput) {
1256
1284
  const value = BigInt(`0x${hex}`);
1257
1285
  return canonicalBabyJubScalarFromInteger(value).toString(DECIMAL_RADIX2);
1258
1286
  }
1287
+ function privKeyScalarDecimalFromDerivedEscrowHex(hexInput) {
1288
+ const hex = normalizeRecipientScalarHex(hexInput);
1289
+ const value = BigInt(`0x${hex}`);
1290
+ return reduceDerivedEscrowSpendScalar(value).toString(DECIMAL_RADIX2);
1291
+ }
1292
+ function resolveTransferSpendScalars(input) {
1293
+ const senderHex = input.senderPrivKeyScalarHex;
1294
+ if (!input.escrowSweep) {
1295
+ return {
1296
+ privKeyScalar: privKeyScalarDecimalFromRecipientScalarHex(senderHex),
1297
+ ownerScalarHex: senderHex
1298
+ };
1299
+ }
1300
+ const privKeyScalar = privKeyScalarDecimalFromDerivedEscrowHex(senderHex);
1301
+ return {
1302
+ privKeyScalar,
1303
+ ownerScalarHex: BigInt(privKeyScalar).toString(16).padStart(SCALAR_HEX_CHAR_LENGTH, "0")
1304
+ };
1305
+ }
1259
1306
 
1260
1307
  // src/transact/fees/append-fee-output.ts
1261
1308
  function feeCoinFromSlot(slot) {
@@ -5560,6 +5607,9 @@ function createNullifierSpentChecker(transactEnvironment) {
5560
5607
  };
5561
5608
  }
5562
5609
 
5610
+ // src/client/assess-incoming-note-network.ts
5611
+ import { commitmentHexFromNoteOpening } from "@arcanetech/stellar-privacy-pool-zk-sdk";
5612
+
5563
5613
  // src/client/pool-sync.ts
5564
5614
  function requireTransactEnvironment(transactEnvironment) {
5565
5615
  if (!transactEnvironment) {
@@ -5598,6 +5648,129 @@ async function readPoolLeafEphemeralHexWithEnvironment(transactEnvironment, inpu
5598
5648
  });
5599
5649
  }
5600
5650
 
5651
+ // src/client/assess-incoming-note.ts
5652
+ var COMMITMENT_HEX_LENGTH = 64;
5653
+ function normalizeCommitmentHex(value) {
5654
+ return value.trim().replace(/^0x/iu, "").toLowerCase().padStart(COMMITMENT_HEX_LENGTH, "0");
5655
+ }
5656
+ function commitmentDecimalFromHex(hex) {
5657
+ return BigInt(`0x${normalizeCommitmentHex(hex)}`).toString();
5658
+ }
5659
+ function commitmentFieldsAgree(input) {
5660
+ const recomputedHex = normalizeCommitmentHex(input.recomputedCommitmentHex);
5661
+ if (recomputedHex !== normalizeCommitmentHex(input.deliveredCommitmentHex)) {
5662
+ return false;
5663
+ }
5664
+ try {
5665
+ return BigInt(input.noteCommitmentDecimal.trim()) === BigInt(`0x${recomputedHex}`);
5666
+ } catch {
5667
+ return false;
5668
+ }
5669
+ }
5670
+ async function assessIncomingNote(input) {
5671
+ const assessmentInput = {
5672
+ note: input.note,
5673
+ commitmentHex: input.commitmentHex,
5674
+ privKeyScalarHex: input.privKeyScalarHex
5675
+ };
5676
+ const recomputedHex = await input.ports.recomputeCommitmentHex(assessmentInput);
5677
+ if (!commitmentFieldsAgree({
5678
+ noteCommitmentDecimal: input.note.commitment,
5679
+ deliveredCommitmentHex: input.commitmentHex,
5680
+ recomputedCommitmentHex: recomputedHex
5681
+ })) {
5682
+ return { kind: "dead", reason: "commitment_mismatch" };
5683
+ }
5684
+ const commitmentDecimal = commitmentDecimalFromHex(recomputedHex);
5685
+ const leafPresent = await input.ports.hasCommitmentLeaf(commitmentDecimal);
5686
+ if (!leafPresent) {
5687
+ return { kind: "pending" };
5688
+ }
5689
+ const nullifierHashHex = await input.ports.calculateNullifierHash(
5690
+ input.note.nullifier,
5691
+ privKeyScalarDecimalFromRecipientScalarHex(input.privKeyScalarHex)
5692
+ );
5693
+ const consumed = await input.ports.isNullifierConsumed(nullifierHashHex);
5694
+ if (consumed) {
5695
+ return { kind: "dead", reason: "nullifier_consumed" };
5696
+ }
5697
+ return { kind: "spendable" };
5698
+ }
5699
+
5700
+ // src/client/assess-incoming-note-network.ts
5701
+ function noteApplicationId(note, environment) {
5702
+ const fromNote = note.application_id?.trim();
5703
+ if (fromNote) {
5704
+ return fromNote;
5705
+ }
5706
+ return environment.network.applicationId;
5707
+ }
5708
+ async function recomputeCommitmentHexFromNote(input) {
5709
+ return commitmentHexFromNoteOpening({
5710
+ value: input.note.value,
5711
+ secret: input.note.secret,
5712
+ nullifier: input.note.nullifier,
5713
+ assetHi: input.note.asset_hi,
5714
+ assetLo: input.note.asset_lo,
5715
+ applicationId: input.applicationId,
5716
+ recipientScalarHex: input.privKeyScalarHex
5717
+ });
5718
+ }
5719
+ async function hasCommitmentLeafInPoolState(input) {
5720
+ const cached = await input.state.getPoolMerkleState(input.poolContractId);
5721
+ if ((cached?.commitments ?? []).includes(input.commitmentDecimal)) {
5722
+ return true;
5723
+ }
5724
+ await syncPoolMerkleStateWithEnvironment(input.environment, {
5725
+ poolContractId: input.poolContractId,
5726
+ walletPublicKey: input.walletPublicKey
5727
+ });
5728
+ const synced = await input.state.getPoolMerkleState(input.poolContractId);
5729
+ return (synced?.commitments ?? []).includes(input.commitmentDecimal);
5730
+ }
5731
+ function createAssessIncomingNotePorts(input) {
5732
+ const { environment, state, poolContractId, walletPublicKey } = input;
5733
+ return {
5734
+ recomputeCommitmentHex: ({ note, privKeyScalarHex }) => recomputeCommitmentHexFromNote({
5735
+ note,
5736
+ privKeyScalarHex,
5737
+ applicationId: noteApplicationId(note, environment)
5738
+ }),
5739
+ hasCommitmentLeaf: (commitmentDecimal) => hasCommitmentLeafInPoolState({
5740
+ environment,
5741
+ state,
5742
+ poolContractId,
5743
+ walletPublicKey,
5744
+ commitmentDecimal
5745
+ }),
5746
+ calculateNullifierHash: (nullifier, privKeyScalarDecimal) => getPrivacyPoolService().calculateNullifierHash(nullifier, privKeyScalarDecimal),
5747
+ isNullifierConsumed: async (nullifierHashHex) => {
5748
+ const contractContext = requireContractContext(environment);
5749
+ return readNullifierConsumedOnChain({
5750
+ contractContext,
5751
+ poolContractId,
5752
+ walletPublicKey,
5753
+ nullifierHashHex
5754
+ });
5755
+ }
5756
+ };
5757
+ }
5758
+ async function assessIncomingNoteWithEnvironment(input) {
5759
+ const environment = requireNetworkEnvironment(input.transactEnvironment);
5760
+ const poolContractId = input.poolContractId?.trim() || environment.network.poolContract;
5761
+ return assessIncomingNote({
5762
+ note: input.note,
5763
+ commitmentHex: input.commitmentHex,
5764
+ privKeyScalarHex: input.privKeyScalarHex,
5765
+ ports: createAssessIncomingNotePorts({
5766
+ environment,
5767
+ state: input.state,
5768
+ poolContractId,
5769
+ walletPublicKey: input.walletPublicKey
5770
+ })
5771
+ });
5772
+ }
5773
+
5601
5774
  // src/client/network-facet.ts
5602
5775
  function createPoolNetworkFacet(input) {
5603
5776
  const { transactEnvironment } = input;
@@ -5631,6 +5804,16 @@ function createRegistryNetworkFacet(input) {
5631
5804
  })
5632
5805
  };
5633
5806
  }
5807
+ function createAssessmentNetworkFacet(input) {
5808
+ const { transactEnvironment, state } = input;
5809
+ return {
5810
+ assessIncomingNote: (assessmentInput) => assessIncomingNoteWithEnvironment({
5811
+ transactEnvironment,
5812
+ state,
5813
+ ...assessmentInput
5814
+ })
5815
+ };
5816
+ }
5634
5817
  function createRpcNetworkFacet(input) {
5635
5818
  const { transactEnvironment } = input;
5636
5819
  return {
@@ -5662,6 +5845,7 @@ function createNetworkFacet(input) {
5662
5845
  return {
5663
5846
  ...createPoolNetworkFacet(input),
5664
5847
  ...createRegistryNetworkFacet(input),
5848
+ ...createAssessmentNetworkFacet(input),
5665
5849
  ...createRpcNetworkFacet(input)
5666
5850
  };
5667
5851
  }
@@ -5874,6 +6058,7 @@ function createStellarPrivacyClientInstance(config) {
5874
6058
  registerPrivateAddress: (input) => composed.network.registerPrivateAddress(input),
5875
6059
  resolveTransferRecipient: (input) => composed.network.resolveTransferRecipient(input),
5876
6060
  checkPrivateRecordSpendStatus: (input) => composed.network.checkPrivateRecordSpendStatus(input),
6061
+ assessIncomingNote: (input) => composed.network.assessIncomingNote(input),
5877
6062
  waitForTransactionConfirmation: (input) => composed.network.waitForTransactionConfirmation(input),
5878
6063
  fetchTransactionConfirmationStatus: (txHash) => composed.network.fetchTransactionConfirmationStatus(txHash),
5879
6064
  getTransactionDetails: (txHash) => composed.network.getTransactionDetails(txHash)
@@ -6395,14 +6580,63 @@ async function buildSenderTransferDepositsAndPublicInput(parameters) {
6395
6580
  });
6396
6581
  }
6397
6582
 
6398
- // src/transact/proofs/confidential/dual.ts
6399
- function confidentialEscrowFields(parameters) {
6583
+ // src/transact/proofs/confidential/transfer-spend.ts
6584
+ function confidentialEscrowFields(input) {
6400
6585
  return {
6401
- ...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
6402
- ...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
6586
+ ...input.escrowSend ? { escrowSend: input.escrowSend } : {},
6587
+ ...input.escrowClaimantLimbs ? { escrowClaimantLimbs: input.escrowClaimantLimbs } : {}
6403
6588
  };
6404
6589
  }
6590
+ function transferDepositInputFromProof(input, changeStroops, stateRoot) {
6591
+ return {
6592
+ senderPrivKeyScalarHex: input.senderPrivKeyScalarHex,
6593
+ recipientPrivateAddressStpl1: input.recipientPrivateAddressStpl1,
6594
+ transferStroops: input.transferStroops,
6595
+ changeStroops,
6596
+ selfPrivateAddressStpl1ForChange: input.selfPrivateAddressStpl1ForChange,
6597
+ tokenAddress: input.tokenAddress,
6598
+ stateRoot,
6599
+ ...confidentialEscrowFields(input),
6600
+ ...input.feeOutput ? { feeOutput: input.feeOutput } : {}
6601
+ };
6602
+ }
6603
+ function spendWithdrawForTransfer(parameters) {
6604
+ const limbs = parameters.input.escrowClaimantLimbs;
6605
+ const { privKeyScalar, ownerScalarHex } = resolveTransferSpendScalars({
6606
+ senderPrivKeyScalarHex: parameters.input.senderPrivKeyScalarHex,
6607
+ escrowSweep: Boolean(limbs)
6608
+ });
6609
+ const spent = withdrawWitnessForCoin({
6610
+ sdk: parameters.sdk,
6611
+ coin: parameters.input.coin,
6612
+ state: parameters.input.state,
6613
+ ownerPubHex: parameters.sdk.ecdhEphemeralPublicKeyFromScalarHex(ownerScalarHex),
6614
+ privKeyScalar,
6615
+ applicationId: parameters.applicationId,
6616
+ ...limbs ? {
6617
+ escrow: escrowSpendWitnessFromLimbs(
6618
+ limbs,
6619
+ parameters.input.senderPrivKeyScalarHex
6620
+ )
6621
+ } : {}
6622
+ });
6623
+ if (limbs) {
6624
+ return spent;
6625
+ }
6626
+ return {
6627
+ witness: spent.witness,
6628
+ withdrawObject: stampWithdrawEscrowLimbs(
6629
+ spent.withdrawObject,
6630
+ sweepWithdrawStamp(confidentialEscrowFields(parameters.input))
6631
+ )
6632
+ };
6633
+ }
6634
+
6635
+ // src/transact/proofs/confidential/dual.ts
6405
6636
  function stampDualWithdrawLegs(legs, parameters) {
6637
+ if (parameters.escrowClaimantLimbs) {
6638
+ return legs;
6639
+ }
6406
6640
  const escrowLimbs = sweepWithdrawStamp(confidentialEscrowFields(parameters));
6407
6641
  return {
6408
6642
  legA: {
@@ -6466,12 +6700,12 @@ function dualTransferChangeStroops(parameters) {
6466
6700
  }
6467
6701
  async function buildDualTransferProofContext(parameters, applicationId, sdk) {
6468
6702
  const changeStroops = dualTransferChangeStroops(parameters);
6469
- const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
6470
- parameters.senderPrivKeyScalarHex
6471
- );
6472
- const ownerPubHex = sdk.ecdhEphemeralPublicKeyFromScalarHex(
6473
- parameters.senderPrivKeyScalarHex
6474
- );
6703
+ const limbs = parameters.escrowClaimantLimbs;
6704
+ const { privKeyScalar, ownerScalarHex } = resolveTransferSpendScalars({
6705
+ senderPrivKeyScalarHex: parameters.senderPrivKeyScalarHex,
6706
+ escrowSweep: Boolean(limbs)
6707
+ });
6708
+ const ownerPubHex = sdk.ecdhEphemeralPublicKeyFromScalarHex(ownerScalarHex);
6475
6709
  const { legA, legB } = stampDualWithdrawLegs(
6476
6710
  dualWithdrawLegsWithSharedRoot({
6477
6711
  sdk,
@@ -6480,7 +6714,13 @@ async function buildDualTransferProofContext(parameters, applicationId, sdk) {
6480
6714
  state: parameters.state,
6481
6715
  ownerPubHex,
6482
6716
  privKeyScalar,
6483
- applicationId
6717
+ applicationId,
6718
+ ...limbs ? {
6719
+ escrow: escrowSpendWitnessFromLimbs(
6720
+ limbs,
6721
+ parameters.senderPrivKeyScalarHex
6722
+ )
6723
+ } : {}
6484
6724
  }),
6485
6725
  parameters
6486
6726
  );
@@ -6583,25 +6823,6 @@ async function proveTransaction(parameters) {
6583
6823
  parameters.audit
6584
6824
  );
6585
6825
  }
6586
- function confidentialEscrowFields2(input) {
6587
- return {
6588
- ...input.escrowSend ? { escrowSend: input.escrowSend } : {},
6589
- ...input.escrowClaimantLimbs ? { escrowClaimantLimbs: input.escrowClaimantLimbs } : {}
6590
- };
6591
- }
6592
- function transferDepositInputFromProof(input, changeStroops, stateRoot) {
6593
- return {
6594
- senderPrivKeyScalarHex: input.senderPrivKeyScalarHex,
6595
- recipientPrivateAddressStpl1: input.recipientPrivateAddressStpl1,
6596
- transferStroops: input.transferStroops,
6597
- changeStroops,
6598
- selfPrivateAddressStpl1ForChange: input.selfPrivateAddressStpl1ForChange,
6599
- tokenAddress: input.tokenAddress,
6600
- stateRoot,
6601
- ...confidentialEscrowFields2(input),
6602
- ...input.feeOutput ? { feeOutput: input.feeOutput } : {}
6603
- };
6604
- }
6605
6826
  async function buildTransferProofInputs(parameters) {
6606
6827
  const changeStroops = validateSingleCoinTransferAmounts(
6607
6828
  parameters.input.transferStroops,
@@ -6609,35 +6830,11 @@ async function buildTransferProofInputs(parameters) {
6609
6830
  parameters.input.selfPrivateAddressStpl1ForChange,
6610
6831
  parameters.input.feeOutput?.requiredFee ?? 0n
6611
6832
  );
6612
- const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
6613
- parameters.input.senderPrivKeyScalarHex
6614
- );
6615
- const { witness, withdrawObject } = withdrawWitnessForCoin({
6616
- sdk: parameters.sdk,
6617
- coin: parameters.input.coin,
6618
- state: parameters.input.state,
6619
- ownerPubHex: parameters.sdk.ecdhEphemeralPublicKeyFromScalarHex(
6620
- parameters.input.senderPrivKeyScalarHex
6621
- ),
6622
- privKeyScalar,
6623
- applicationId: parameters.applicationId
6624
- });
6625
- const stampedWithdraw = stampWithdrawEscrowLimbs(
6626
- withdrawObject,
6627
- sweepWithdrawStamp(confidentialEscrowFields2(parameters.input))
6628
- );
6629
- const { recipientSlot, deposits, changeCoin, feeCoin, publicInput } = await buildSenderTransferDepositsAndPublicInput(
6833
+ const { witness, withdrawObject } = spendWithdrawForTransfer(parameters);
6834
+ const depositsBuild = await buildSenderTransferDepositsAndPublicInput(
6630
6835
  transferDepositInputFromProof(parameters.input, changeStroops, witness.stateRoot)
6631
6836
  );
6632
- return {
6633
- witness,
6634
- withdrawObject: stampedWithdraw,
6635
- recipientSlot,
6636
- deposits,
6637
- changeCoin,
6638
- feeCoin,
6639
- publicInput
6640
- };
6837
+ return { witness, withdrawObject, ...depositsBuild };
6641
6838
  }
6642
6839
  async function prepareConfidentialTransferProof(parameters) {
6643
6840
  const poolService = getPrivacyPoolService();