@arcanetech/privacy-sdk-stellar 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,10 @@
1
1
  // src/transact/pool/service.ts
2
2
  import {
3
+ PrivacyPoolSDK as PrivacyPoolSDK2,
3
4
  decodeDecodedEphemeralKey,
4
5
  randomFrDecimal253,
5
6
  scalarHexToFrDecimal as scalarHexToFrDecimal2
6
- } from "@auditable/privacy-pool-zk-sdk";
7
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
7
8
 
8
9
  // src/transact/merkle/field-decimal.ts
9
10
  import { Buffer as Buffer2 } from "buffer";
@@ -26,11 +27,18 @@ import {
26
27
  decodeStealthAddress,
27
28
  encodeStealthAddress,
28
29
  recipientPublicKeysDecimalFromStealthAddress
29
- } from "@auditable/privacy-pool-zk-sdk";
30
- import { DEFAULT_STEALTH_SIGN_NONCE } from "@auditable/privacy-pool-zk-sdk";
31
- function buildPrivateAddressSignMessage(publicKey, nonce) {
30
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
31
+ import { DEFAULT_STEALTH_SIGN_NONCE } from "@arcanetech/stellar-privacy-pool-zk-sdk";
32
+ import {
33
+ OWNER_BOUND_NOTE_SCHEMA_VERSION,
34
+ spendScalarHexFromStellarSignature
35
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
36
+ function buildPrivateAddressSignMessage(publicKey, domain, nonce) {
32
37
  const buildMessage = buildStealthAddressSignMessage;
33
- return buildMessage(publicKey, nonce);
38
+ if (nonce === void 0) {
39
+ return buildMessage(publicKey, domain);
40
+ }
41
+ return buildMessage(publicKey, domain, nonce);
34
42
  }
35
43
  function decodePrivateAddress(value) {
36
44
  const decodeAddress = decodeStealthAddress;
@@ -60,12 +68,12 @@ function privateAddressSdk(sdk) {
60
68
  );
61
69
  }
62
70
  return {
63
- generatePrivateAddressFromStellarSignature: (signature) => generator.call(sdk, signature)
71
+ generatePrivateAddressFromStellarSignature: (signature, domain) => generator.call(sdk, signature, domain)
64
72
  };
65
73
  }
66
74
 
67
75
  // src/transact/proofs/withdraw/transact-proof.ts
68
- import { withdrawObjectFromMerkleWitness as withdrawObjectFromMerkleWitness2 } from "@auditable/privacy-pool-zk-sdk";
76
+ import { withdrawObjectFromMerkleWitness as withdrawObjectFromMerkleWitness2 } from "@arcanetech/stellar-privacy-pool-zk-sdk";
69
77
 
70
78
  // src/transact/proofs/transaction-input.ts
71
79
  import { Buffer as Buffer4 } from "buffer";
@@ -105,6 +113,10 @@ function resolveTokenContractId(tokenContractRaw) {
105
113
  }
106
114
 
107
115
  // src/transact/proofs/transaction-input.ts
116
+ var ZERO_PUBLIC_WITHDRAW_ADDRESS = {
117
+ withdrawAddressHi: "0",
118
+ withdrawAddressLo: "0"
119
+ };
108
120
  var CONTRACT_ADDRESS_HALF_BYTES = 16;
109
121
  var CONTRACT_ADDRESS_BYTES = 32;
110
122
  function bytes16ToDecimal(bytes) {
@@ -131,7 +143,25 @@ function withTokenAddressPublicInputs(base, tokenAddress) {
131
143
  return {
132
144
  ...base,
133
145
  tokenAddressHi: hi,
134
- tokenAddressLo: lo
146
+ tokenAddressLo: lo,
147
+ withdrawAddressHi: base.withdrawAddressHi ?? ZERO_PUBLIC_WITHDRAW_ADDRESS.withdrawAddressHi,
148
+ withdrawAddressLo: base.withdrawAddressLo ?? ZERO_PUBLIC_WITHDRAW_ADDRESS.withdrawAddressLo,
149
+ escrowRecipientHi: base.escrowRecipientHi ?? "0",
150
+ escrowRecipientLo: base.escrowRecipientLo ?? "0",
151
+ sweepOutputOwnerPubX: base.sweepOutputOwnerPubX ?? "0",
152
+ sweepOutputOwnerPubY: base.sweepOutputOwnerPubY ?? "0"
153
+ };
154
+ }
155
+ function publicWithdrawAddressLimbs(parameters) {
156
+ if (parameters.publicWithdrawalAmount === "0") {
157
+ return {
158
+ withdrawAddressHi: ZERO_PUBLIC_WITHDRAW_ADDRESS.withdrawAddressHi,
159
+ withdrawAddressLo: ZERO_PUBLIC_WITHDRAW_ADDRESS.withdrawAddressLo
160
+ };
161
+ }
162
+ return {
163
+ withdrawAddressHi: parameters.destinationHi,
164
+ withdrawAddressLo: parameters.destinationLo
135
165
  };
136
166
  }
137
167
  function tokenAddressToAssetLeg(tokenAddress) {
@@ -142,91 +172,91 @@ function assetLegToTokenAddress(assetHi, assetLo) {
142
172
  const payload = Buffer4.concat([decimalToBytes16(assetHi), decimalToBytes16(assetLo)]);
143
173
  return StrKey2.encodeContract(payload);
144
174
  }
145
- function buildZeroPublicLegs() {
175
+ function buildZeroPublicLegs(publicNInputs = 1, publicNOutputs = 1) {
146
176
  return {
147
- publicWithdrawnAssets: [["0", "0"]],
148
- publicDepositedAssets: [["0", "0"]],
149
- publicDeposits: ["0"],
150
- publicWithdrawals: ["0"]
177
+ publicWithdrawnAssets: Array.from(
178
+ { length: publicNOutputs },
179
+ () => ["0", "0"]
180
+ ),
181
+ publicDepositedAssets: Array.from(
182
+ { length: publicNInputs },
183
+ () => ["0", "0"]
184
+ ),
185
+ publicDeposits: Array.from({ length: publicNInputs }, () => "0"),
186
+ publicWithdrawals: Array.from({ length: publicNOutputs }, () => "0")
151
187
  };
152
188
  }
153
- function buildPublicDepositLegs(tokenAddress, amount) {
154
- const legs = buildZeroPublicLegs();
189
+ function buildPublicDepositLegs(tokenAddress, amount, publicNInputs = 1, publicNOutputs = 1) {
190
+ const legs = buildZeroPublicLegs(publicNInputs, publicNOutputs);
155
191
  return {
156
192
  ...legs,
157
- publicDepositedAssets: [tokenAddressToAssetLeg(tokenAddress)],
158
- publicDeposits: [amount]
193
+ publicDepositedAssets: [
194
+ tokenAddressToAssetLeg(tokenAddress),
195
+ ...legs.publicDepositedAssets.slice(1)
196
+ ],
197
+ publicDeposits: [amount, ...legs.publicDeposits.slice(1)]
159
198
  };
160
199
  }
161
- function buildPublicWithdrawLegs(tokenAddress, amount) {
162
- const legs = buildZeroPublicLegs();
200
+ function buildPublicWithdrawLegs(tokenAddress, amount, publicNInputs = 1, publicNOutputs = 1) {
201
+ const legs = buildZeroPublicLegs(publicNInputs, publicNOutputs);
163
202
  return {
164
203
  ...legs,
165
- publicWithdrawnAssets: [tokenAddressToAssetLeg(tokenAddress)],
166
- publicWithdrawals: [amount]
204
+ publicWithdrawnAssets: [
205
+ tokenAddressToAssetLeg(tokenAddress),
206
+ ...legs.publicWithdrawnAssets.slice(1)
207
+ ],
208
+ publicWithdrawals: [amount, ...legs.publicWithdrawals.slice(1)]
167
209
  };
168
210
  }
169
211
 
170
- // src/transact/proofs/confidential/helpers.ts
212
+ // src/transact/zk/slots.ts
171
213
  import {
172
- ed25519PubkeyPayloadHexToWithdrawFrDecimals,
173
- withdrawObjectFromMerkleWitness
174
- } from "@auditable/privacy-pool-zk-sdk";
175
- import { StrKey as StrKey3 } from "@stellar/stellar-sdk";
176
- import { Buffer as Buffer5 } from "buffer";
177
-
178
- // src/transact/encoding/priv-key-scalar-from-recipient-hex.ts
179
- import { BN254_BABYJUB_SCALAR_MAX_EXCLUSIVE } from "@auditable/privacy-pool-zk-sdk";
180
- var SCALAR_HEX_CHAR_LENGTH = 64;
181
- var DECIMAL_RADIX = 10;
182
- var BIGINT_ONE = 1n;
183
- function normalizeRecipientScalarHex(hexInput) {
184
- const trimmed = hexInput.trim().replace(/^0x/iu, "");
185
- if (!/^[0-9a-f]*$/iu.test(trimmed)) {
186
- throw new Error("recipient scalar hex must be hexadecimal");
187
- }
188
- const withLeadingNibble = trimmed.length % 2 === 0 ? trimmed : `0${trimmed}`;
189
- const lower = withLeadingNibble.toLowerCase();
190
- const padded = lower.padStart(SCALAR_HEX_CHAR_LENGTH, "0").slice(-SCALAR_HEX_CHAR_LENGTH);
191
- if (padded.length !== SCALAR_HEX_CHAR_LENGTH) {
214
+ padDepositSlots,
215
+ padPublicLegs,
216
+ padWithdrawSlots
217
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
218
+ function padWithdrawSlotsToLayout(sdk, slots) {
219
+ return padWithdrawSlots(slots, sdk.getLayout().nIns);
220
+ }
221
+ function padDepositSlotsToLayout(sdk, slots) {
222
+ return padDepositSlots(slots, sdk.getLayout().nOuts);
223
+ }
224
+ function padPublicLegsToLayout(sdk, legs) {
225
+ const { publicNInputs, publicNOutputs } = sdk.getLayout();
226
+ return padPublicLegs(legs, publicNInputs, publicNOutputs);
227
+ }
228
+ function padStrings(values, length, fill) {
229
+ if (values.length > length) {
192
230
  throw new Error(
193
- `recipient scalar hex must fit 32 bytes (${SCALAR_HEX_CHAR_LENGTH} hex chars)`
231
+ `expected at most ${String(length)} application-id slots, got ${String(values.length)}`
194
232
  );
195
233
  }
196
- return padded;
234
+ return [...values, ...Array.from({ length: length - values.length }, () => fill)];
197
235
  }
198
- function privKeyScalarDecimalFromRecipientScalarHex(hexInput) {
199
- const hex = normalizeRecipientScalarHex(hexInput);
200
- const value = BigInt(`0x${hex}`);
201
- const mask = BN254_BABYJUB_SCALAR_MAX_EXCLUSIVE - BIGINT_ONE;
202
- return (value & mask).toString(DECIMAL_RADIX);
236
+ function buildApplicationIdHints(input) {
237
+ const { nIns, nOuts } = input.sdk.getLayout();
238
+ return [
239
+ ...padStrings(input.inputIds, nIns, "0"),
240
+ ...padStrings(input.outputIds, nOuts, "0")
241
+ ];
242
+ }
243
+ function uniformApplicationIdHints(applicationId, nAuditSlots) {
244
+ return Array.from({ length: nAuditSlots }, () => applicationId);
203
245
  }
204
246
 
205
247
  // src/transact/proofs/confidential/helpers.ts
248
+ import { withdrawObjectFromMerkleWitness } from "@arcanetech/stellar-privacy-pool-zk-sdk";
206
249
  var MIN_CONFIDENTIAL_TRANSFER_STROOPS = 1n;
207
250
  var ZERO_STROOPS = 0n;
208
- function leafEphemeralCoords(xHex, yHex) {
209
- const coords = {};
210
- Object.defineProperty(coords, "x", {
211
- value: xHex,
212
- enumerable: true,
213
- writable: true
214
- });
215
- Object.defineProperty(coords, "y", {
216
- value: yHex,
217
- enumerable: true,
218
- writable: true
219
- });
220
- return coords;
221
- }
222
251
  function withdrawWitnessForCoin(parameters) {
223
- const { sdk, coin, state, xHex, yHex } = parameters;
252
+ const { sdk, coin, state } = parameters;
224
253
  const witness = sdk.buildWithdrawMerkleWitness(coin, state);
225
254
  const withdrawApplicationId = coin.application_id ?? parameters.applicationId;
226
255
  const withdrawObject = withdrawObjectFromMerkleWitness(
227
256
  witness,
228
- leafEphemeralCoords(xHex, yHex),
229
- withdrawApplicationId
257
+ parameters.ownerPubHex,
258
+ withdrawApplicationId,
259
+ parameters.privKeyScalar
230
260
  );
231
261
  return { witness, withdrawObject };
232
262
  }
@@ -235,16 +265,16 @@ function dualWithdrawLegsWithSharedRoot(parameters) {
235
265
  sdk: parameters.sdk,
236
266
  coin: parameters.coinA,
237
267
  state: parameters.state,
238
- xHex: parameters.ephemeralA.xHex,
239
- yHex: parameters.ephemeralA.yHex,
268
+ ownerPubHex: parameters.ownerPubHex,
269
+ privKeyScalar: parameters.privKeyScalar,
240
270
  applicationId: parameters.applicationId
241
271
  });
242
272
  const legB = withdrawWitnessForCoin({
243
273
  sdk: parameters.sdk,
244
274
  coin: parameters.coinB,
245
275
  state: parameters.state,
246
- xHex: parameters.ephemeralB.xHex,
247
- yHex: parameters.ephemeralB.yHex,
276
+ ownerPubHex: parameters.ownerPubHex,
277
+ privKeyScalar: parameters.privKeyScalar,
248
278
  applicationId: parameters.applicationId
249
279
  });
250
280
  if (legA.witness.stateRoot !== legB.witness.stateRoot) {
@@ -252,15 +282,6 @@ function dualWithdrawLegsWithSharedRoot(parameters) {
252
282
  }
253
283
  return { legA, legB };
254
284
  }
255
- function senderWithdrawFrAndScalar(parameters) {
256
- const pkRaw = StrKey3.decodeEd25519PublicKey(parameters.senderGAddress);
257
- const pkHex = Buffer5.from(pkRaw).toString("hex");
258
- const { hi, lo } = ed25519PubkeyPayloadHexToWithdrawFrDecimals(pkHex);
259
- const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
260
- parameters.senderPrivKeyScalarHex
261
- );
262
- return { hi, lo, privKeyScalar };
263
- }
264
285
  function requireChangeRecipientWhenPartial(changeStroops, selfPrivateAddressStpl1ForChange) {
265
286
  if (changeStroops > ZERO_STROOPS) {
266
287
  const stpl1 = selfPrivateAddressStpl1ForChange?.trim() ?? "";
@@ -285,15 +306,15 @@ function changeStroopsAfterDualTransfer(transferStroops, totalNotes) {
285
306
  import {
286
307
  DEMO_AUDIT_PUBLIC_KEY,
287
308
  resolveTransactionAuditParams
288
- } from "@auditable/privacy-pool-zk-sdk";
289
- import { Buffer as Buffer6 } from "buffer";
309
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
310
+ import { Buffer as Buffer5 } from "buffer";
290
311
  var UNCOMPRESSED_PREFIX = "04";
291
312
  var UNCOMPRESSED_HEX_LENGTH = 130;
292
313
  var XY_HEX_LENGTH = 128;
293
314
  var X_OFFSET_END = 32;
294
315
  var Y_OFFSET_START = 32;
295
316
  var Y_OFFSET_END = 64;
296
- var DECIMAL_RADIX2 = 10;
317
+ var DECIMAL_RADIX = 10;
297
318
  var BN254_FR_MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
298
319
  var BABYJUBJUB_A = 168700n;
299
320
  var BABYJUBJUB_D = 168696n;
@@ -313,13 +334,13 @@ function parseAuditPublicKeyFromEnvHex(raw) {
313
334
  "Audit public key must be uncompressed 65-byte hex (04 + X + Y) or 64-byte X+Y hex"
314
335
  );
315
336
  }
316
- const bytes = Buffer6.from(payload, "hex");
337
+ const bytes = Buffer5.from(payload, "hex");
317
338
  const auditPublicKeyXDecimal = BigInt(
318
339
  `0x${bytes.subarray(0, X_OFFSET_END).toString("hex")}`
319
- ).toString(DECIMAL_RADIX2);
340
+ ).toString(DECIMAL_RADIX);
320
341
  const auditPublicKeyYDecimal = BigInt(
321
342
  `0x${bytes.subarray(Y_OFFSET_START, Y_OFFSET_END).toString("hex")}`
322
- ).toString(DECIMAL_RADIX2);
343
+ ).toString(DECIMAL_RADIX);
323
344
  if (!passesBabyJubCurveCheck(
324
345
  BigInt(auditPublicKeyXDecimal),
325
346
  BigInt(auditPublicKeyYDecimal)
@@ -331,7 +352,8 @@ function parseAuditPublicKeyFromEnvHex(raw) {
331
352
  function buildPoolTransactionAuditParameters(input) {
332
353
  return resolveTransactionAuditParams(
333
354
  input.applicationId,
334
- input.auditPublicKey ?? DEMO_AUDIT_PUBLIC_KEY
355
+ input.auditPublicKey ?? DEMO_AUDIT_PUBLIC_KEY,
356
+ input.nAuditSlots
335
357
  );
336
358
  }
337
359
  function resolvePoolApplicationId(applicationId) {
@@ -345,24 +367,24 @@ function resolvePoolApplicationId(applicationId) {
345
367
  }
346
368
 
347
369
  // src/transact/proofs/withdraw/helpers.ts
348
- import { ed25519PubkeyPayloadHexToWithdrawFrDecimals as ed25519PubkeyPayloadHexToWithdrawFrDecimals2 } from "@auditable/privacy-pool-zk-sdk";
370
+ import { ed25519PubkeyPayloadHexToWithdrawFrDecimals } from "@arcanetech/stellar-privacy-pool-zk-sdk";
349
371
 
350
372
  // src/transact/stellar/account.ts
351
- import { StrKey as StrKey4 } from "@stellar/stellar-sdk";
352
- import { Buffer as Buffer7 } from "buffer";
373
+ import { StrKey as StrKey3 } from "@stellar/stellar-sdk";
374
+ import { Buffer as Buffer6 } from "buffer";
353
375
  var MUXED_ACCOUNT_ID_BYTE_LENGTH = 8;
354
376
  var ED25519_PUBLIC_KEY_BYTE_LENGTH = 32;
355
377
  function ed25519HexFromGAddress(trimmed) {
356
378
  try {
357
- const raw = StrKey4.decodeEd25519PublicKey(trimmed);
358
- return Buffer7.from(raw).toString("hex");
379
+ const raw = StrKey3.decodeEd25519PublicKey(trimmed);
380
+ return Buffer6.from(raw).toString("hex");
359
381
  } catch {
360
382
  return void 0;
361
383
  }
362
384
  }
363
385
  function ed25519HexFromMuxedAddress(trimmed) {
364
386
  try {
365
- const raw = StrKey4.decodeMed25519PublicKey(trimmed);
387
+ const raw = StrKey3.decodeMed25519PublicKey(trimmed);
366
388
  if (raw.length === MUXED_ACCOUNT_ID_BYTE_LENGTH + ED25519_PUBLIC_KEY_BYTE_LENGTH) {
367
389
  return raw.subarray(MUXED_ACCOUNT_ID_BYTE_LENGTH).toString("hex");
368
390
  }
@@ -387,26 +409,29 @@ function ed25519PublicKeyHexFromStellarAccount(address) {
387
409
  throw new Error("Invalid destination Stellar address");
388
410
  }
389
411
 
390
- // src/transact/encoding/ephemeral-key.ts
391
- var HEX_64_RE = /^[\da-f]{64}$/iu;
392
- function normalizeCoordinate(value) {
393
- const hex = value.trim().replace(/^0x/iu, "").toLowerCase();
394
- if (!HEX_64_RE.test(hex)) {
395
- throw new Error("Ephemeral key coordinate must be a 32-byte hex string.");
412
+ // src/transact/encoding/priv-key-scalar-from-recipient-hex.ts
413
+ import { canonicalBabyJubScalarFromInteger } from "@arcanetech/stellar-privacy-pool-zk-sdk";
414
+ var SCALAR_HEX_CHAR_LENGTH = 64;
415
+ var DECIMAL_RADIX2 = 10;
416
+ function normalizeRecipientScalarHex(hexInput) {
417
+ const trimmed = hexInput.trim().replace(/^0x/iu, "");
418
+ if (!/^[0-9a-f]*$/iu.test(trimmed)) {
419
+ throw new Error("recipient scalar hex must be hexadecimal");
396
420
  }
397
- return hex;
398
- }
399
- function parseEphemeralKeyString(input) {
400
- const [xRaw, yRaw, extra] = input.split(":");
401
- if (!xRaw || !yRaw || extra !== void 0) {
421
+ const withLeadingNibble = trimmed.length % 2 === 0 ? trimmed : `0${trimmed}`;
422
+ const lower = withLeadingNibble.toLowerCase();
423
+ const padded = lower.padStart(SCALAR_HEX_CHAR_LENGTH, "0").slice(-SCALAR_HEX_CHAR_LENGTH);
424
+ if (padded.length !== SCALAR_HEX_CHAR_LENGTH) {
402
425
  throw new Error(
403
- 'Ephemeral key must be a string in "xHex:yHex" format (32-byte hex each).'
426
+ `recipient scalar hex must fit 32 bytes (${SCALAR_HEX_CHAR_LENGTH} hex chars)`
404
427
  );
405
428
  }
406
- return {
407
- xHex: normalizeCoordinate(xRaw),
408
- yHex: normalizeCoordinate(yRaw)
409
- };
429
+ return padded;
430
+ }
431
+ function privKeyScalarDecimalFromRecipientScalarHex(hexInput) {
432
+ const hex = normalizeRecipientScalarHex(hexInput);
433
+ const value = BigInt(`0x${hex}`);
434
+ return canonicalBabyJubScalarFromInteger(value).toString(DECIMAL_RADIX2);
410
435
  }
411
436
 
412
437
  // src/transact/proofs/withdraw/helpers.ts
@@ -414,7 +439,7 @@ function destinationWithdrawFrAndScalar(parameters) {
414
439
  const pkHex = ed25519PublicKeyHexFromStellarAccount(
415
440
  parameters.destinationStellarAddress
416
441
  );
417
- const { hi, lo } = ed25519PubkeyPayloadHexToWithdrawFrDecimals2(pkHex);
442
+ const { hi, lo } = ed25519PubkeyPayloadHexToWithdrawFrDecimals(pkHex);
418
443
  const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
419
444
  parameters.privKeyScalarHex
420
445
  );
@@ -428,8 +453,11 @@ function buildWithdrawPublicInput(parameters) {
428
453
  return withTokenAddressPublicInputs(
429
454
  {
430
455
  stateRoot: parameters.stateRoot,
431
- withdrawAddressHi: hi,
432
- withdrawAddressLo: lo,
456
+ ...publicWithdrawAddressLimbs({
457
+ publicWithdrawalAmount: parameters.publicWithdrawalAmount,
458
+ destinationHi: hi,
459
+ destinationLo: lo
460
+ }),
433
461
  privKeyScalar
434
462
  },
435
463
  parameters.tokenAddress
@@ -437,7 +465,7 @@ function buildWithdrawPublicInput(parameters) {
437
465
  }
438
466
  async function resolveWithdrawChangeDeposits(parameters) {
439
467
  if (parameters.changeStroops <= ZERO_STROOPS) {
440
- return { deposits: ["dummy", "dummy"] };
468
+ return { deposits: [] };
441
469
  }
442
470
  const stpl1 = parameters.changePrivateAddressStpl1?.trim() ?? "";
443
471
  if (!stpl1) {
@@ -451,7 +479,7 @@ async function resolveWithdrawChangeDeposits(parameters) {
451
479
  tokenAddress: parameters.tokenAddress
452
480
  });
453
481
  return {
454
- deposits: [slot.deposit, "dummy"],
482
+ deposits: [slot.deposit],
455
483
  changeCoin: {
456
484
  commitment_hex: slot.commitment_hex,
457
485
  coin: slot.coin,
@@ -476,14 +504,14 @@ function buildDualWithdrawPublicInput(parameters) {
476
504
  stateRoot: parameters.stateRoot,
477
505
  destinationStellarAddress: parameters.destinationStellarAddress,
478
506
  privKeyScalarHex: parameters.privKeyScalarHex,
479
- tokenAddress: parameters.tokenAddress
507
+ tokenAddress: parameters.tokenAddress,
508
+ publicWithdrawalAmount: parameters.publicWithdrawalAmount
480
509
  });
481
510
  }
482
511
  async function prepareDualWithdrawProofInputs(parameters) {
483
- const totalNotes = BigInt(parameters.coinA.value) + BigInt(parameters.coinB.value);
484
512
  const changeStroops = validateDualWithdrawAmounts(
485
513
  parameters.withdrawAmountStroops,
486
- totalNotes,
514
+ BigInt(parameters.coinA.value) + BigInt(parameters.coinB.value),
487
515
  parameters.changePrivateAddressStpl1
488
516
  );
489
517
  const { legA, legB } = dualWithdrawLegsWithSharedRoot({
@@ -491,8 +519,12 @@ async function prepareDualWithdrawProofInputs(parameters) {
491
519
  coinA: parameters.coinA,
492
520
  coinB: parameters.coinB,
493
521
  state: parameters.state,
494
- ephemeralA: parseEphemeralKeyString(parameters.ephemeralAKey),
495
- ephemeralB: parseEphemeralKeyString(parameters.ephemeralBKey),
522
+ ownerPubHex: parameters.sdk.ecdhEphemeralPublicKeyFromScalarHex(
523
+ parameters.privKeyScalarHex
524
+ ),
525
+ privKeyScalar: privKeyScalarDecimalFromRecipientScalarHex(
526
+ parameters.privKeyScalarHex
527
+ ),
496
528
  applicationId: parameters.applicationId
497
529
  });
498
530
  const { deposits, changeCoin } = await resolveWithdrawChangeDeposits({
@@ -505,17 +537,19 @@ async function prepareDualWithdrawProofInputs(parameters) {
505
537
  destinationStellarAddress: parameters.destinationStellarAddress,
506
538
  privKeyScalarHex: parameters.privKeyScalarHex,
507
539
  tokenAddress: parameters.tokenAddress,
508
- stateRoot: legA.witness.stateRoot
540
+ stateRoot: legA.witness.stateRoot,
541
+ publicWithdrawalAmount: parameters.withdrawAmountStroops.toString()
509
542
  });
510
543
  const audit = buildPoolTransactionAuditParameters({
511
544
  applicationId: parameters.applicationId,
545
+ nAuditSlots: parameters.sdk.getLayout().nAuditSlots,
512
546
  ...parameters.auditPublicKey ? { auditPublicKey: parameters.auditPublicKey } : {}
513
547
  });
514
548
  return {
515
549
  publicInput,
516
550
  audit,
517
- withdrawLegs: [legA.withdrawObject, legB.withdrawObject],
518
551
  deposits,
552
+ withdrawLegs: [legA.withdrawObject, legB.withdrawObject],
519
553
  ...changeCoin ? { changeCoin } : {}
520
554
  };
521
555
  }
@@ -533,35 +567,49 @@ function validateSingleWithdrawAmounts(withdrawAmountStroops, noteStroops) {
533
567
  async function proveSingleWithdrawTransaction(parameters) {
534
568
  return parameters.sdk.proveTransaction(
535
569
  parameters.publicInput,
536
- buildPublicWithdrawLegs(
537
- parameters.tokenAddress,
538
- parameters.withdrawAmountStroops.toString()
570
+ padPublicLegsToLayout(
571
+ parameters.sdk,
572
+ buildPublicWithdrawLegs(
573
+ parameters.tokenAddress,
574
+ parameters.withdrawAmountStroops.toString()
575
+ )
539
576
  ),
540
- [parameters.primaryWithdraw, "dummy"],
541
- parameters.deposits,
577
+ padWithdrawSlotsToLayout(parameters.sdk, [parameters.primaryWithdraw]),
578
+ padDepositSlotsToLayout(parameters.sdk, parameters.deposits),
542
579
  parameters.audit
543
580
  );
544
581
  }
545
582
  function buildPrimaryWithdrawForCoin(parameters) {
546
- const ephemeralPoint = parseEphemeralKeyString(parameters.depositorEphemeralKey);
547
583
  const witness = parameters.sdk.buildWithdrawMerkleWitness(
548
584
  parameters.coin,
549
585
  parameters.state
550
586
  );
587
+ const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
588
+ parameters.privKeyScalarHex
589
+ );
590
+ const ownerPubHex = parameters.sdk.ecdhEphemeralPublicKeyFromScalarHex(
591
+ parameters.privKeyScalarHex
592
+ );
551
593
  const primaryWithdraw = withdrawObjectFromMerkleWitness2(
552
594
  witness,
553
- leafEphemeralCoords(ephemeralPoint.xHex, ephemeralPoint.yHex),
554
- parameters.applicationId
595
+ ownerPubHex,
596
+ parameters.applicationId,
597
+ privKeyScalar
555
598
  );
556
599
  return { witness, primaryWithdraw };
557
600
  }
558
601
  async function prepareSingleWithdrawProofInputs(parameters) {
559
- const noteStroops = BigInt(parameters.coin.value);
560
602
  const changeStroops = validateSingleWithdrawAmounts(
561
603
  parameters.withdrawAmountStroops,
562
- noteStroops
604
+ BigInt(parameters.coin.value)
563
605
  );
564
- const { witness, primaryWithdraw } = buildPrimaryWithdrawForCoin(parameters);
606
+ const { witness, primaryWithdraw } = buildPrimaryWithdrawForCoin({
607
+ sdk: parameters.sdk,
608
+ applicationId: parameters.applicationId,
609
+ coin: parameters.coin,
610
+ state: parameters.state,
611
+ privKeyScalarHex: parameters.privKeyScalarHex
612
+ });
565
613
  const { deposits, changeCoin } = await resolveWithdrawChangeDeposits({
566
614
  changeStroops,
567
615
  changePrivateAddressStpl1: parameters.changePrivateAddressStpl1,
@@ -572,18 +620,19 @@ async function prepareSingleWithdrawProofInputs(parameters) {
572
620
  stateRoot: witness.stateRoot,
573
621
  destinationStellarAddress: parameters.destinationStellarAddress,
574
622
  privKeyScalarHex: parameters.privKeyScalarHex,
575
- tokenAddress: parameters.tokenAddress
576
- });
577
- const audit = buildPoolTransactionAuditParameters({
578
- applicationId: parameters.applicationId,
579
- ...parameters.auditPublicKey ? { auditPublicKey: parameters.auditPublicKey } : {}
623
+ tokenAddress: parameters.tokenAddress,
624
+ publicWithdrawalAmount: parameters.withdrawAmountStroops.toString()
580
625
  });
581
626
  return {
582
627
  primaryWithdraw,
583
628
  deposits,
584
629
  changeCoin,
585
630
  publicInput,
586
- audit
631
+ audit: buildPoolTransactionAuditParameters({
632
+ applicationId: parameters.applicationId,
633
+ nAuditSlots: parameters.sdk.getLayout().nAuditSlots,
634
+ ...parameters.auditPublicKey ? { auditPublicKey: parameters.auditPublicKey } : {}
635
+ })
587
636
  };
588
637
  }
589
638
  async function proveWithdrawTransact(parameters) {
@@ -599,12 +648,11 @@ async function proveWithdrawTransact(parameters) {
599
648
  });
600
649
  return {
601
650
  ...proof,
602
- applicationIdsPlaintext: [
603
- parameters.applicationId,
604
- "0",
605
- changeCoin ? parameters.applicationId : "0",
606
- "0"
607
- ],
651
+ applicationIdsPlaintext: buildApplicationIdHints({
652
+ sdk: parameters.sdk,
653
+ inputIds: [parameters.applicationId],
654
+ outputIds: [changeCoin ? parameters.applicationId : "0"]
655
+ }),
608
656
  ...changeCoin ? { changeCoin } : {}
609
657
  };
610
658
  }
@@ -612,33 +660,146 @@ async function proveWithdrawTransactDual(parameters) {
612
660
  const { publicInput, audit, withdrawLegs, deposits, changeCoin } = await prepareDualWithdrawProofInputs(parameters);
613
661
  const proof = await parameters.sdk.proveTransaction(
614
662
  publicInput,
615
- buildPublicWithdrawLegs(
616
- parameters.tokenAddress,
617
- parameters.withdrawAmountStroops.toString()
663
+ padPublicLegsToLayout(
664
+ parameters.sdk,
665
+ buildPublicWithdrawLegs(
666
+ parameters.tokenAddress,
667
+ parameters.withdrawAmountStroops.toString()
668
+ )
618
669
  ),
619
- withdrawLegs,
620
- deposits,
670
+ padWithdrawSlotsToLayout(parameters.sdk, withdrawLegs),
671
+ padDepositSlotsToLayout(parameters.sdk, deposits),
621
672
  audit
622
673
  );
623
674
  return {
624
675
  ...proof,
625
- applicationIdsPlaintext: [
626
- audit.applicationId,
627
- audit.applicationId,
628
- changeCoin ? audit.applicationId : "0",
629
- "0"
630
- ],
676
+ applicationIdsPlaintext: buildApplicationIdHints({
677
+ sdk: parameters.sdk,
678
+ inputIds: [audit.applicationId, audit.applicationId],
679
+ outputIds: [changeCoin ? audit.applicationId : "0"]
680
+ }),
631
681
  ...changeCoin ? { changeCoin } : {}
632
682
  };
633
683
  }
634
684
 
635
685
  // src/transact/pool/service.ts
636
686
  import "buffer";
637
- import { PrivacyPoolSDK as PrivacyPoolSdkClass } from "@auditable/privacy-pool-zk-sdk";
687
+
688
+ // src/transact/zk/circuit-config.ts
689
+ import {
690
+ BundledZkCircuit
691
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
692
+
693
+ // src/transact/environment/zk-config-nonce.ts
694
+ var STANDARD_ZK_CONFIG_NONCE = 0n;
695
+ var COMMITMENT_V2_ZK_NONCE = 2n;
696
+ var BINDING_ZK_NONCE = 3n;
697
+ var SIX_BY_SIX_ZK_NONCE = 6n;
698
+ var SIX_BY_SIX_BINDING_ZK_NONCE = 7n;
699
+ var DEFAULT_ZK_CONFIG_NONCE = BINDING_ZK_NONCE;
700
+ function resolveZkConfigNonce(transactEnvironment) {
701
+ return transactEnvironment.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
702
+ }
703
+
704
+ // src/transact/zk/circuit-config.ts
705
+ import { BundledZkCircuit as BundledZkCircuit2 } from "@arcanetech/stellar-privacy-pool-zk-sdk";
706
+ var DEFAULT_STELLAR_ZK_CIRCUITS = {
707
+ [BINDING_ZK_NONCE.toString()]: {
708
+ nIns: 2,
709
+ nOuts: 2,
710
+ publicNInputs: 1,
711
+ publicNOutputs: 1,
712
+ circuit: BundledZkCircuit.TwoByTwo
713
+ },
714
+ [SIX_BY_SIX_BINDING_ZK_NONCE.toString()]: {
715
+ nIns: 6,
716
+ nOuts: 6,
717
+ publicNInputs: 1,
718
+ publicNOutputs: 1,
719
+ circuit: BundledZkCircuit.SixBySix
720
+ }
721
+ };
722
+ function isBundledDefinition(definition) {
723
+ return "circuit" in definition;
724
+ }
725
+ async function fetchBuffer(url) {
726
+ const response = await fetch(url);
727
+ if (!response.ok) {
728
+ throw new Error(`Failed to fetch ZK artifact ${url}: ${String(response.status)}`);
729
+ }
730
+ return response.arrayBuffer();
731
+ }
732
+ async function materializeDefinition(definition) {
733
+ if (isBundledDefinition(definition)) {
734
+ const bundled = {
735
+ nIns: definition.nIns,
736
+ nOuts: definition.nOuts,
737
+ publicNInputs: definition.publicNInputs,
738
+ publicNOutputs: definition.publicNOutputs,
739
+ circuit: definition.circuit
740
+ };
741
+ return bundled;
742
+ }
743
+ const [zkey, circuitGraph, r1cs, provingKey] = await Promise.all([
744
+ fetchBuffer(definition.zkeyUrl),
745
+ fetchBuffer(definition.circuitGraphUrl),
746
+ fetchBuffer(definition.r1csUrl),
747
+ fetchBuffer(definition.provingKeyUrl)
748
+ ]);
749
+ const custom = {
750
+ nIns: definition.nIns,
751
+ nOuts: definition.nOuts,
752
+ publicNInputs: definition.publicNInputs,
753
+ publicNOutputs: definition.publicNOutputs,
754
+ zkey,
755
+ circuitGraph,
756
+ r1cs,
757
+ provingKey
758
+ };
759
+ return custom;
760
+ }
761
+ async function materializeSelectedZkCircuit(circuits, nonce) {
762
+ const map = stellarCircuitsOrDefault(circuits);
763
+ const key = nonce.toString();
764
+ const definition = Object.entries(map).find(([nonceKey]) => nonceKey === key)?.[1];
765
+ if (!definition) {
766
+ throw new Error(`no zk circuit configured for nonce ${key}`);
767
+ }
768
+ return { [key]: await materializeDefinition(definition) };
769
+ }
770
+ function stellarCircuitsOrDefault(circuits) {
771
+ return circuits ?? DEFAULT_STELLAR_ZK_CIRCUITS;
772
+ }
773
+ function optionalZkArtifactBaseUrl(value) {
774
+ if (value === void 0) {
775
+ return {};
776
+ }
777
+ const trimmed = value.trim();
778
+ if (trimmed === "") {
779
+ return {};
780
+ }
781
+ let withoutSlash = trimmed;
782
+ while (withoutSlash.endsWith("/")) {
783
+ withoutSlash = withoutSlash.slice(0, -1);
784
+ }
785
+ return { zkArtifactBaseUrl: withoutSlash };
786
+ }
638
787
 
639
788
  // src/transact/pool/aligned-deposit.ts
640
- import { PrivacyPoolSDK, scalarHexToFrDecimal } from "@auditable/privacy-pool-zk-sdk";
789
+ import {
790
+ PrivacyPoolSDK,
791
+ scalarHexToFrDecimal
792
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
641
793
  var SAMPLE_SCALAR_ATTEMPTS = 10;
794
+ function escrowDepositFields(parameters) {
795
+ if (!parameters.recipientHi || !parameters.recipientLo) {
796
+ return {};
797
+ }
798
+ return {
799
+ ...parameters.escrowNonce ? { escrowNonce: parameters.escrowNonce } : {},
800
+ recipientStellar: [parameters.recipientHi, parameters.recipientLo]
801
+ };
802
+ }
642
803
  function sampleValidDepositScalarHex() {
643
804
  for (let index = 0; index < SAMPLE_SCALAR_ATTEMPTS; index++) {
644
805
  const candidate = PrivacyPoolSDK.generateRandomScalarHex32();
@@ -654,17 +815,12 @@ function sampleValidDepositScalarHex() {
654
815
  async function buildAlignedDepositSlotForSdk(sdk, applicationId, parameters) {
655
816
  const privateAddressPoint = decodePrivateAddress(parameters.privateAddressStpl1);
656
817
  const scalarHex = sampleValidDepositScalarHex();
657
- const shared = sdk.ecdhSharedKey(
658
- scalarHex,
659
- privateAddressPoint.x,
660
- privateAddressPoint.y
661
- );
662
818
  const [assetHi, assetLo] = tokenAddressToAssetLeg(parameters.tokenAddress);
663
819
  const resolvedApplicationId = resolvePoolApplicationId(applicationId);
664
- const generated = sdk.generateCoinForDepositWithSharedHex(
820
+ const generated = sdk.generateCoinForDepositWithOwnerPubHex(
665
821
  scalarHex,
666
- shared.x,
667
- shared.y,
822
+ privateAddressPoint.x,
823
+ privateAddressPoint.y,
668
824
  parameters.amountStroops,
669
825
  assetHi,
670
826
  assetLo,
@@ -679,27 +835,34 @@ async function buildAlignedDepositSlotForSdk(sdk, applicationId, parameters) {
679
835
  ephemeralKeyScalar: scalarHexToFrDecimal(scalarHex),
680
836
  asset: [generated.coin.asset_hi, generated.coin.asset_lo],
681
837
  applicationId: resolvedApplicationId,
682
- recipientPublicKeys
838
+ recipientPublicKeys,
839
+ ...escrowDepositFields(parameters)
683
840
  };
684
841
  return {
685
842
  deposit,
686
843
  commitment_hex: generated.commitment_hex,
687
844
  coin: generated.coin,
688
845
  depositScalarHex: scalarHex,
689
- precommitementHex: generated.precommitement_hex
846
+ precommitementHex: generated.precommitementHex
690
847
  };
691
848
  }
692
849
 
693
850
  // src/transact/pool/service.ts
694
851
  var PrivacyPoolService = class {
695
- constructor(assets, applicationId, auditPublicKey) {
852
+ constructor(assets, applicationId, auditPublicKey, zkCircuits, zkConfigNonce, zkArtifactBaseUrl) {
696
853
  this.assets = assets;
697
854
  this.applicationId = applicationId;
698
855
  this.auditPublicKey = auditPublicKey;
856
+ this.zkCircuits = zkCircuits;
857
+ this.zkConfigNonce = zkConfigNonce;
858
+ this.zkArtifactBaseUrl = zkArtifactBaseUrl;
699
859
  }
700
860
  assets;
701
861
  applicationId;
702
862
  auditPublicKey;
863
+ zkCircuits;
864
+ zkConfigNonce;
865
+ zkArtifactBaseUrl;
703
866
  sdk = void 0;
704
867
  initPromise = void 0;
705
868
  async ensureInit() {
@@ -715,10 +878,16 @@ var PrivacyPoolService = class {
715
878
  "PrivacyPoolService requires browser ZK assets before initialization."
716
879
  );
717
880
  }
718
- this.sdk = await PrivacyPoolSdkClass.init({
881
+ const zkConfigNonce = this.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
882
+ const zkCircuits = await materializeSelectedZkCircuit(
883
+ this.zkCircuits,
884
+ zkConfigNonce
885
+ );
886
+ this.sdk = await PrivacyPoolSDK2.init({
719
887
  wasmBinary: this.assets.sdkWasm,
720
- circuitWasm: this.assets.circuitWasm,
721
- zkey: this.assets.provingKey
888
+ zkCircuits,
889
+ zkConfigNonce,
890
+ ...optionalZkArtifactBaseUrl(this.zkArtifactBaseUrl)
722
891
  });
723
892
  })();
724
893
  return this.initPromise;
@@ -736,22 +905,17 @@ var PrivacyPoolService = class {
736
905
  getApplicationId() {
737
906
  return resolvePoolApplicationId(this.applicationId);
738
907
  }
739
- async generatePrivateAddressFromStellarSignature(signature) {
740
- await this.ensureInit();
741
- if (!this.sdk) {
742
- throw new Error("SDK not initialized");
743
- }
744
- return privateAddressSdk(this.sdk).generatePrivateAddressFromStellarSignature(
745
- signature
908
+ async generatePrivateAddressFromStellarSignature(signature, domain) {
909
+ const sdk = await this.getInitializedSdk();
910
+ return privateAddressSdk(sdk).generatePrivateAddressFromStellarSignature(
911
+ signature,
912
+ domain
746
913
  );
747
914
  }
748
915
  async sharedSecretX(recipientScalarHex, ephemeralKeyEncoded) {
749
- await this.ensureInit();
750
- if (!this.sdk) {
751
- throw new Error("SDK not initialized");
752
- }
916
+ const sdk = await this.getInitializedSdk();
753
917
  const ephemeralKey = decodeDecodedEphemeralKey(ephemeralKeyEncoded);
754
- const shared = this.sdk.sharedSecretFromRecipientPreimage({
918
+ const shared = sdk.sharedSecretFromRecipientPreimage({
755
919
  recipientScalar: recipientScalarHex,
756
920
  ephemeralKey
757
921
  });
@@ -774,6 +938,7 @@ var PrivacyPoolService = class {
774
938
  const applicationId = this.getApplicationId();
775
939
  const audit = buildPoolTransactionAuditParameters({
776
940
  applicationId,
941
+ nAuditSlots: sdk.getLayout().nAuditSlots,
777
942
  ...this.auditPublicKey ? { auditPublicKey: this.auditPublicKey } : {}
778
943
  });
779
944
  const deposit = {
@@ -787,38 +952,35 @@ var PrivacyPoolService = class {
787
952
  const publicInput = withTokenAddressPublicInputs(
788
953
  {
789
954
  stateRoot,
790
- withdrawAddressHi: "0",
791
- withdrawAddressLo: "0",
792
955
  privKeyScalar: randomFrDecimal253()
793
956
  },
794
957
  parameters.tokenAddress
795
958
  );
796
959
  const proof = await sdk.proveTransaction(
797
960
  publicInput,
798
- buildPublicDepositLegs(parameters.tokenAddress, parameters.coin.value),
799
- ["dummy", "dummy"],
800
- [deposit, "dummy"],
961
+ padPublicLegsToLayout(
962
+ sdk,
963
+ buildPublicDepositLegs(parameters.tokenAddress, parameters.coin.value)
964
+ ),
965
+ padWithdrawSlotsToLayout(sdk, []),
966
+ padDepositSlotsToLayout(sdk, [deposit]),
801
967
  audit
802
968
  );
803
- const applicationIdsPlaintext = [
804
- "0",
805
- "0",
806
- applicationId,
807
- "0"
808
- ];
969
+ const applicationIdsPlaintext = buildApplicationIdHints({
970
+ sdk,
971
+ inputIds: [],
972
+ outputIds: [applicationId]
973
+ });
809
974
  return { ...proof, applicationIdsPlaintext };
810
975
  }
811
- async calculateNullifierHash(nullifier) {
976
+ async calculateNullifierHash(nullifier, privKeyScalar) {
812
977
  const sdk = await this.getInitializedSdk();
813
- return sdk.calculateNullifierHash(nullifier);
978
+ return sdk.calculateNullifierHash(nullifier, privKeyScalar);
814
979
  }
815
980
  async prepareWithdrawTransactProof(parameters) {
816
- await this.ensureInit();
817
- if (!this.sdk) {
818
- throw new Error("SDK not initialized");
819
- }
981
+ const sdk = await this.getInitializedSdk();
820
982
  return proveWithdrawTransact({
821
- sdk: this.sdk,
983
+ sdk,
822
984
  applicationId: this.getApplicationId(),
823
985
  buildAlignedDepositSlot: (input) => this.buildAlignedDepositSlot(input),
824
986
  ...this.auditPublicKey ? { auditPublicKey: this.auditPublicKey } : {},
@@ -826,12 +988,9 @@ var PrivacyPoolService = class {
826
988
  });
827
989
  }
828
990
  async prepareWithdrawTransactProofDual(parameters) {
829
- await this.ensureInit();
830
- if (!this.sdk) {
831
- throw new Error("SDK not initialized");
832
- }
991
+ const sdk = await this.getInitializedSdk();
833
992
  return proveWithdrawTransactDual({
834
- sdk: this.sdk,
993
+ sdk,
835
994
  applicationId: this.getApplicationId(),
836
995
  buildAlignedDepositSlot: (input) => this.buildAlignedDepositSlot(input),
837
996
  ...this.auditPublicKey ? { auditPublicKey: this.auditPublicKey } : {},
@@ -854,7 +1013,10 @@ function createPrivacyPoolService(input) {
854
1013
  return new PrivacyPoolService(
855
1014
  input?.assets,
856
1015
  input?.applicationId,
857
- input?.auditPublicKey
1016
+ input?.auditPublicKey,
1017
+ input?.zkCircuits,
1018
+ input?.zkConfigNonce,
1019
+ input?.zkArtifactBaseUrl
858
1020
  );
859
1021
  }
860
1022
  var configuredPrivacyPoolService;
@@ -870,143 +1032,473 @@ function getPrivacyPoolService() {
870
1032
  return configuredPrivacyPoolService;
871
1033
  }
872
1034
 
873
- // src/transact/assets/load-browser.ts
874
- async function loadStellarBrowserAssets(input) {
875
- const cacheKey = input.cacheBust ? `?v=${Date.now()}` : "";
876
- const [sdkWasm, circuitWasm, provingKey] = await Promise.all([
877
- fetch(`${input.sdkWasmUrl}${cacheKey}`).then((response) => response.arrayBuffer()),
878
- fetch(input.circuitWasmUrl).then((response) => response.arrayBuffer()),
879
- fetch(input.provingKeyUrl).then((response) => response.arrayBuffer())
880
- ]);
881
- return { sdkWasm, circuitWasm, provingKey };
882
- }
883
- async function loadDefaultStellarBrowserAssets(options) {
884
- await import("@auditable/privacy-pool-zk-sdk");
885
- const sdkWasmUrl = new URL("@auditable/privacy-pool-zk-sdk/sdk.wasm", import.meta.url).href;
886
- const circuitWasmUrl = new URL(
887
- "@auditable/privacy-pool-zk-sdk/witness.wasm",
888
- import.meta.url
889
- ).href;
890
- const provingKeyUrl = new URL(
891
- "@auditable/privacy-pool-zk-sdk/main.zkey",
892
- import.meta.url
893
- ).href;
894
- return loadStellarBrowserAssets({
895
- sdkWasmUrl,
896
- circuitWasmUrl,
897
- provingKeyUrl,
898
- ...options?.cacheBust ? { cacheBust: true } : {}
899
- });
1035
+ // src/transact/escrow/tag-challenge-message.ts
1036
+ function buildBlindedRecipientTagChallengeMessage(fields) {
1037
+ return [
1038
+ "Arcane privacy layer: issue your blinded recipient tags.",
1039
+ "",
1040
+ `Wallet: ${fields.stellarAddress}`,
1041
+ `Network: ${fields.networkPassphrase}`,
1042
+ `Issued: ${fields.issuedAt}`,
1043
+ `Expires: ${fields.expiresAt}`,
1044
+ `Nonce: ${fields.nonce}`,
1045
+ "",
1046
+ "This signature proves you control the wallet. It is the same kind of signed challenge used to derive your private-note spend key."
1047
+ ].join("\n");
900
1048
  }
901
1049
 
902
- // src/transact/onboarding/build-payload.ts
903
- import { Buffer as Buffer9 } from "buffer";
904
- import { PrivacyPoolSDK as PrivacyPoolSDK4 } from "@auditable/privacy-pool-zk-sdk";
1050
+ // src/transact/escrow/derived-escrow-recipient.ts
1051
+ import { Buffer as Buffer8 } from "buffer";
1052
+ import { StrKey as StrKey4 } from "@stellar/stellar-sdk";
1053
+ import {
1054
+ derivedEscrowKey,
1055
+ ed25519PubkeyPayloadHexToWithdrawFrDecimals as ed25519PubkeyPayloadHexToWithdrawFrDecimals2,
1056
+ sampleDerivedEscrowKey
1057
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
1058
+ var COORDINATE_HEX_LENGTH = 64;
1059
+ function stellarAccountToFieldLimbs(stellarAddress) {
1060
+ const pkRaw = StrKey4.decodeEd25519PublicKey(stellarAddress.trim());
1061
+ const pkHex = Buffer8.from(pkRaw).toString("hex");
1062
+ const { hi, lo } = ed25519PubkeyPayloadHexToWithdrawFrDecimals2(pkHex);
1063
+ return { recipientHi: hi, recipientLo: lo };
1064
+ }
1065
+ function padCoordinateHex(value) {
1066
+ return value.replace(/^0x/iu, "").padStart(COORDINATE_HEX_LENGTH, "0");
1067
+ }
1068
+ async function deriveEscrowRecipientFromStellarAddress(input) {
1069
+ const recipientStellarAddress = input.recipientStellarAddress.trim();
1070
+ if (!StrKey4.isValidEd25519PublicKey(recipientStellarAddress)) {
1071
+ throw new Error("Escrow recipient must be a Stellar G-address.");
1072
+ }
1073
+ const { recipientHi, recipientLo } = stellarAccountToFieldLimbs(
1074
+ recipientStellarAddress
1075
+ );
1076
+ const deriveKey = input.deriveKey ?? derivedEscrowKey;
1077
+ let nonceDecimal;
1078
+ let key;
1079
+ if (input.nonceDecimal) {
1080
+ nonceDecimal = input.nonceDecimal;
1081
+ key = await deriveKey(
1082
+ BigInt(nonceDecimal),
1083
+ BigInt(recipientHi),
1084
+ BigInt(recipientLo)
1085
+ );
1086
+ } else {
1087
+ const sampled = await sampleDerivedEscrowKey(
1088
+ BigInt(recipientHi),
1089
+ BigInt(recipientLo)
1090
+ );
1091
+ nonceDecimal = sampled.nonce.toString();
1092
+ key = sampled.key;
1093
+ }
1094
+ return {
1095
+ nonceDecimal,
1096
+ recipientHi,
1097
+ recipientLo,
1098
+ recipientStellarAddress,
1099
+ privateAddressStpl1: encodePrivateAddressFromHexCoordinates(
1100
+ padCoordinateHex(key.pointXHex),
1101
+ padCoordinateHex(key.pointYHex)
1102
+ ),
1103
+ scalarHex: padCoordinateHex(key.scalarHex)
1104
+ };
1105
+ }
905
1106
 
906
- // src/transact/encoding/fr-decimal-to-bytes.ts
907
- var BN254_SCALAR_MOD = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
908
- var FIELD_BYTE_LENGTH = 32;
909
- var BYTE_MASK = 0xffn;
910
- var BITS_PER_BYTE = 8n;
911
- function frDecimalToPaddedBytes32(decimal) {
912
- let value = BigInt(decimal.trim());
913
- value = (value % BN254_SCALAR_MOD + BN254_SCALAR_MOD) % BN254_SCALAR_MOD;
914
- const bytes = Buffer.alloc(FIELD_BYTE_LENGTH);
915
- for (let index = FIELD_BYTE_LENGTH - 1; index >= 0; index -= 1) {
916
- bytes[index] = Number(value & BYTE_MASK);
917
- value >>= BITS_PER_BYTE;
1107
+ // src/transact/escrow/assert-escrow-sweep-claimant.ts
1108
+ import { insufficientStateError } from "@arcanetech/privacy-sdk-core";
1109
+ function assertEscrowSweepClaimant(input) {
1110
+ const walletPublicKey = input.walletPublicKey.trim();
1111
+ const claimantAddress = input.claimantAddress.trim();
1112
+ if (!walletPublicKey || walletPublicKey !== claimantAddress) {
1113
+ const error = insufficientStateError(
1114
+ "escrow_sweep_claimant_mismatch",
1115
+ "Escrow sweep requires the connected account that owns the note.",
1116
+ { walletPublicKey, claimantAddress }
1117
+ );
1118
+ throw new Error(error.message, { cause: error });
918
1119
  }
919
- return bytes;
920
1120
  }
921
1121
 
922
- // src/transact/onboarding/recipient.ts
923
- import { PrivacyPoolSDK as PrivacyPoolSDK3 } from "@auditable/privacy-pool-zk-sdk";
924
- var COORDINATE_HEX_LENGTH = 64;
925
- async function generateTemporaryRecipientPrivateAddress() {
926
- await getPrivacyPoolService().getInitializedSdk();
927
- const temporaryScalarHex = PrivacyPoolSDK3.generateRandomScalarHex32();
928
- const sdk = await getPrivacyPoolService().getInitializedSdk();
929
- const point = sdk.ecdhEphemeralPublicKeyFromScalarHex(temporaryScalarHex);
930
- const publicKeyXHex = point.x.padStart(COORDINATE_HEX_LENGTH, "0");
931
- const publicKeyYHex = point.y.padStart(COORDINATE_HEX_LENGTH, "0");
1122
+ // src/transact/escrow/reconstruct-escrow-note.ts
1123
+ var FIELD_HEX_LENGTH = 64;
1124
+ function hexToDecimal(hex) {
1125
+ const clean = hex.trim().replace(/^0x/u, "");
1126
+ return BigInt(`0x${clean || "0"}`).toString();
1127
+ }
1128
+ function padFieldHex(value) {
1129
+ return value.replace(/^0x/iu, "").padStart(FIELD_HEX_LENGTH, "0");
1130
+ }
1131
+ async function defaultDecryptOutputNote(input) {
1132
+ const module = await import("@arcanetech/stellar-privacy-pool-zk-sdk");
1133
+ if (typeof module.decryptOutputNoteEvent !== "function") {
1134
+ throw new TypeError("Output note decryption is not available.");
1135
+ }
1136
+ return module.decryptOutputNoteEvent(input);
1137
+ }
1138
+ async function reconstructEscrowNote(input) {
1139
+ const derived = await deriveEscrowRecipientFromStellarAddress({
1140
+ recipientStellarAddress: input.claimantAddress,
1141
+ nonceDecimal: input.nonceDecimal,
1142
+ ...input.deriveKey ? { deriveKey: input.deriveKey } : {}
1143
+ });
1144
+ const event = input.events.find((entry) => entry.outputIndex === input.seq);
1145
+ if (!event) {
1146
+ throw new Error("Escrow output note event was not found for this sequence.");
1147
+ }
1148
+ const decrypt = input.decrypt ?? defaultDecryptOutputNote;
1149
+ const decrypted = await decrypt({
1150
+ recipientScalarHex: derived.scalarHex,
1151
+ commitmentHashHex: event.commitmentHashHex,
1152
+ createdEphemeralKey: event.createdEphemeralKey,
1153
+ ciphertext: event.ciphertext,
1154
+ tag: event.tag,
1155
+ ownerMode: 1n
1156
+ });
932
1157
  return {
933
- temporaryScalarHex,
934
- temporaryPrivateAddressStpl1: encodePrivateAddressFromHexCoordinates(
935
- publicKeyXHex,
936
- publicKeyYHex
937
- )
1158
+ coin: {
1159
+ value: decrypted.value,
1160
+ nullifier: decrypted.nullifier,
1161
+ secret: decrypted.secret,
1162
+ commitment: hexToDecimal(decrypted.commitmentHex),
1163
+ asset_hi: decrypted.assetHi,
1164
+ asset_lo: decrypted.assetLo,
1165
+ application_id: decrypted.applicationId
1166
+ },
1167
+ scalarHex: derived.scalarHex,
1168
+ privateAddressStpl1: derived.privateAddressStpl1,
1169
+ recipientHi: derived.recipientHi,
1170
+ recipientLo: derived.recipientLo,
1171
+ nonceDecimal: derived.nonceDecimal,
1172
+ tokenAddress: assetLegToTokenAddress(decrypted.assetHi, decrypted.assetLo),
1173
+ commitmentHex: padFieldHex(decrypted.commitmentHex)
938
1174
  };
939
1175
  }
940
1176
 
941
- // src/transact/onboarding/build-payload.ts
942
- var COORDINATE_HEX_LENGTH2 = 64;
943
- function noneOptionalRegistration() {
944
- return { tag: "None", values: void 0 };
1177
+ // src/transact/escrow/prepare-escrow-sweep.ts
1178
+ import { StrKey as StrKey5 } from "@stellar/stellar-sdk";
1179
+ var PRIVATE_DISCLOSURE = {
1180
+ senderAddress: "private",
1181
+ recipientAddress: "private",
1182
+ assetAddress: "private",
1183
+ amount: "private"
1184
+ };
1185
+ function requireRegisteredPrivateAddress(value) {
1186
+ const trimmed = value.trim();
1187
+ if (!trimmed || StrKey5.isValidEd25519PublicKey(trimmed)) {
1188
+ throw new Error("Escrow sweep recipient must be a registered private address.");
1189
+ }
1190
+ return trimmed;
945
1191
  }
946
- function coinToPlaintextNote(coin) {
947
- const [assetHi, assetLo] = tokenAddressToAssetLeg(coin.tokenAddress);
1192
+ function consumedEscrowRecord(input) {
948
1193
  return {
949
- asset_hi: frDecimalToPaddedBytes32(assetHi),
950
- asset_lo: frDecimalToPaddedBytes32(assetLo),
951
- deposited_ephemeral_scalar: void 0,
952
- nullifier: frDecimalToPaddedBytes32(coin.nullifier),
953
- secret: frDecimalToPaddedBytes32(coin.secret),
954
- value: BigInt(coin.value)
1194
+ id: input.reconstructed.commitmentHex,
1195
+ owner: input.walletPublicKey,
1196
+ asset: input.asset,
1197
+ amount: BigInt(input.reconstructed.coin.value),
1198
+ consumed: false,
1199
+ status: "finalized",
1200
+ poolContract: input.poolContract,
1201
+ coinNote: input.reconstructed.coin,
1202
+ privateAddress: input.reconstructed.privateAddressStpl1,
1203
+ commitmentHex: input.reconstructed.commitmentHex
955
1204
  };
956
1205
  }
957
- async function generateRandomDepositScalarHex() {
958
- await getPrivacyPoolService().getInitializedSdk();
959
- return PrivacyPoolSDK4.generateRandomScalarHex32();
960
- }
961
- function buildOnboardingPayload(parameters) {
962
- const notes = parameters.recipientNotes.map((coin) => coinToPlaintextNote(coin));
963
- const temporaryDecoded = decodePrivateAddress(
964
- parameters.temporaryKey.temporaryPrivateAddressStpl1.trim()
965
- );
966
- let privateAddressRegistration = noneOptionalRegistration();
967
- if (parameters.permanentPrivateAddressStpl1?.trim()) {
968
- const decoded = decodePrivateAddress(
969
- parameters.permanentPrivateAddressStpl1.trim()
970
- );
971
- const registration = {
972
- owner: parameters.ownerStellarAddress.trim(),
973
- public_key_x: Buffer9.from(decoded.x.padStart(COORDINATE_HEX_LENGTH2, "0"), "hex"),
974
- public_key_y: Buffer9.from(decoded.y.padStart(COORDINATE_HEX_LENGTH2, "0"), "hex")
975
- };
976
- privateAddressRegistration = { tag: "Some", values: [registration] };
1206
+ function attachEscrowAuthorization(prepared, escrowAuthorization) {
1207
+ const credential = escrowAuthorization.trim();
1208
+ if (!credential) {
1209
+ throw new Error("Escrow sweep requires a signed authorization entry.");
977
1210
  }
978
1211
  return {
979
- owner: parameters.ownerStellarAddress.trim(),
980
- temp_public_key_x: Buffer9.from(
981
- temporaryDecoded.x.padStart(COORDINATE_HEX_LENGTH2, "0"),
982
- "hex"
983
- ),
984
- temp_public_key_y: Buffer9.from(
985
- temporaryDecoded.y.padStart(COORDINATE_HEX_LENGTH2, "0"),
986
- "hex"
987
- ),
988
- encrypted_private_key: Buffer9.from(
989
- parameters.temporaryKey.temporaryScalarHex,
990
- "utf8"
991
- ),
992
- notes: { notes },
993
- private_address_registration: privateAddressRegistration
1212
+ ...prepared,
1213
+ transactArtifacts: {
1214
+ ...prepared.transactArtifacts,
1215
+ escrowAuthorization: credential
1216
+ }
994
1217
  };
995
1218
  }
996
- async function buildTransferOnboardingAtExecute(input) {
997
- return buildOnboardingPayload({
998
- ownerStellarAddress: input.ownerStellarAddress,
999
- temporaryKey: {
1000
- temporaryScalarHex: input.temporaryRecipientKey.temporaryScalarHex,
1001
- temporaryPrivateAddressStpl1: input.temporaryRecipientKey.temporaryPrivateAddressStpl1
1219
+ function sweepTransactArtifacts(input) {
1220
+ return {
1221
+ spendSource: "escrow",
1222
+ escrowRecipient: input.claimantAddress.trim(),
1223
+ escrowSpendScalarHex: input.reconstructed.scalarHex,
1224
+ escrowClaimantLimbs: {
1225
+ recipientHi: input.reconstructed.recipientHi,
1226
+ recipientLo: input.reconstructed.recipientLo,
1227
+ nonceDecimal: input.reconstructed.nonceDecimal
1002
1228
  },
1003
- recipientNotes: [input.recipientNote]
1004
- });
1229
+ executeFinalizeRequired: true,
1230
+ walletPublicKey: input.walletPublicKey
1231
+ };
1005
1232
  }
1006
-
1007
- // src/transact/kyt/inspect-error.ts
1008
- var KytInspectError = class extends Error {
1009
- reasonCode;
1233
+ function prepareEscrowSweepOperation(input) {
1234
+ assertEscrowSweepClaimant({
1235
+ walletPublicKey: input.walletPublicKey,
1236
+ claimantAddress: input.claimantAddress
1237
+ });
1238
+ const walletPublicKey = input.walletPublicKey.trim();
1239
+ const registeredPrivateAddress = requireRegisteredPrivateAddress(
1240
+ input.registeredPrivateAddress
1241
+ );
1242
+ const amount = BigInt(input.reconstructed.coin.value);
1243
+ return {
1244
+ kind: "transfer",
1245
+ intent: {
1246
+ from: input.reconstructed.privateAddressStpl1,
1247
+ to: registeredPrivateAddress,
1248
+ asset: input.asset,
1249
+ amount,
1250
+ disclosure: PRIVATE_DISCLOSURE
1251
+ },
1252
+ consumedRecords: [
1253
+ consumedEscrowRecord({
1254
+ reconstructed: input.reconstructed,
1255
+ walletPublicKey,
1256
+ poolContract: input.poolContract,
1257
+ asset: input.asset
1258
+ })
1259
+ ],
1260
+ outputRecords: [],
1261
+ submissionPayload: { operationId: crypto.randomUUID(), signed: false },
1262
+ transactArtifacts: sweepTransactArtifacts({
1263
+ claimantAddress: input.claimantAddress,
1264
+ reconstructed: input.reconstructed,
1265
+ walletPublicKey
1266
+ })
1267
+ };
1268
+ }
1269
+
1270
+ // src/transact/escrow/fetch-output-note-events.ts
1271
+ import { Api } from "@stellar/stellar-sdk/rpc";
1272
+
1273
+ // src/rpc/soroban-transaction-meta.ts
1274
+ import { Address, StrKey as StrKey6 } from "@stellar/stellar-sdk";
1275
+ var TRANSACTION_META_SWITCH_SOROBAN_V3 = 3;
1276
+ var TRANSACTION_META_SWITCH_SOROBAN_V4 = 4;
1277
+ function pushSorobanV3ContractEvents(out, meta) {
1278
+ const soroban = meta.v3().sorobanMeta();
1279
+ if (!soroban) {
1280
+ return;
1281
+ }
1282
+ for (const event of soroban.events()) {
1283
+ out.push(event);
1284
+ }
1285
+ }
1286
+ function pushSorobanV4ContractEvents(out, meta) {
1287
+ const v4 = meta.v4();
1288
+ for (const txEvent of v4.events()) {
1289
+ out.push(txEvent.event());
1290
+ }
1291
+ for (const op of v4.operations()) {
1292
+ for (const event of op.events()) {
1293
+ out.push(event);
1294
+ }
1295
+ }
1296
+ }
1297
+ function collectContractEventsFromMeta(meta) {
1298
+ const out = [];
1299
+ const code = meta.switch();
1300
+ if (code === TRANSACTION_META_SWITCH_SOROBAN_V3) {
1301
+ pushSorobanV3ContractEvents(out, meta);
1302
+ }
1303
+ if (code === TRANSACTION_META_SWITCH_SOROBAN_V4) {
1304
+ pushSorobanV4ContractEvents(out, meta);
1305
+ }
1306
+ return out;
1307
+ }
1308
+
1309
+ // src/rpc/server.ts
1310
+ import { rpc } from "@stellar/stellar-sdk";
1311
+ function createStellarRpcServer(rpcUrl) {
1312
+ return new rpc.Server(rpcUrl.trim(), { allowHttp: true });
1313
+ }
1314
+
1315
+ // src/transact/escrow/parse-output-note-events.ts
1316
+ import { StrKey as StrKey7 } from "@stellar/stellar-sdk";
1317
+ var FIELD_BYTE_LENGTH = 32;
1318
+ var FIELD_HEX_LENGTH2 = 64;
1319
+ var CONTRACT_EVENT_BODY_V0 = 0;
1320
+ var OUTPUT_NOTE_TOPIC_COUNT = 3;
1321
+ function extractSymbol(value) {
1322
+ try {
1323
+ if (value.switch().name === "scvSymbol") {
1324
+ return value.sym().toString();
1325
+ }
1326
+ if (value.switch().name === "scvString") {
1327
+ return value.str().toString();
1328
+ }
1329
+ } catch {
1330
+ return void 0;
1331
+ }
1332
+ return void 0;
1333
+ }
1334
+ function readBytes(value) {
1335
+ if (!value) {
1336
+ return void 0;
1337
+ }
1338
+ try {
1339
+ if (value.switch().name !== "scvBytes") {
1340
+ return void 0;
1341
+ }
1342
+ return Buffer.from(value.bytes());
1343
+ } catch {
1344
+ return void 0;
1345
+ }
1346
+ }
1347
+ function readU32(value) {
1348
+ if (!value) {
1349
+ return void 0;
1350
+ }
1351
+ try {
1352
+ if (value.switch().name !== "scvU32") {
1353
+ return void 0;
1354
+ }
1355
+ return value.u32();
1356
+ } catch {
1357
+ return void 0;
1358
+ }
1359
+ }
1360
+ function fieldHex(bytes) {
1361
+ return bytes.toString("hex").padStart(FIELD_HEX_LENGTH2, "0");
1362
+ }
1363
+ function ciphertextLimbs(bytes) {
1364
+ if (bytes.length === 0 || bytes.length % FIELD_BYTE_LENGTH !== 0) {
1365
+ return [];
1366
+ }
1367
+ const limbs = [];
1368
+ for (let offset = 0; offset < bytes.length; offset += FIELD_BYTE_LENGTH) {
1369
+ limbs.push(fieldHex(bytes.subarray(offset, offset + FIELD_BYTE_LENGTH)));
1370
+ }
1371
+ return limbs;
1372
+ }
1373
+ function payloadMap(data) {
1374
+ const entries = /* @__PURE__ */ new Map();
1375
+ try {
1376
+ if (data.switch().name !== "scvMap") {
1377
+ return entries;
1378
+ }
1379
+ const mapped = data.map();
1380
+ if (!mapped) {
1381
+ return entries;
1382
+ }
1383
+ for (const entry of mapped) {
1384
+ const key = extractSymbol(entry.key());
1385
+ if (key) {
1386
+ entries.set(key, entry.val());
1387
+ }
1388
+ }
1389
+ } catch {
1390
+ return entries;
1391
+ }
1392
+ return entries;
1393
+ }
1394
+ function hashToBuffer(value) {
1395
+ return Buffer.isBuffer(value) ? value : void 0;
1396
+ }
1397
+ function eventContractId(event) {
1398
+ try {
1399
+ const contractId = hashToBuffer(event.contractId());
1400
+ if (!contractId) {
1401
+ return void 0;
1402
+ }
1403
+ return StrKey7.encodeContract(contractId);
1404
+ } catch {
1405
+ return void 0;
1406
+ }
1407
+ }
1408
+ function eventMatchesPool(event, poolAddress) {
1409
+ const contractId = eventContractId(event);
1410
+ return contractId === void 0 || contractId === poolAddress.trim();
1411
+ }
1412
+ function outputNoteEventBody(event) {
1413
+ if (event.type().name !== "contract") {
1414
+ return void 0;
1415
+ }
1416
+ const body = event.body();
1417
+ if (body.switch() !== CONTRACT_EVENT_BODY_V0) {
1418
+ return void 0;
1419
+ }
1420
+ return body.v0();
1421
+ }
1422
+ function outputNoteFromPayload(topics, payload) {
1423
+ const commitment = readBytes(topics[2]);
1424
+ const outputIndex = readU32(payload.get("output_index"));
1425
+ const ephemeralX = readBytes(payload.get("ephemeral_x"));
1426
+ const ephemeralY = readBytes(payload.get("ephemeral_y"));
1427
+ const ciphertextBytes = readBytes(payload.get("ciphertext"));
1428
+ const tag = readBytes(payload.get("tag"));
1429
+ const ciphertext = ciphertextBytes ? ciphertextLimbs(ciphertextBytes) : [];
1430
+ if (!commitment || outputIndex === void 0 || !ephemeralX || !ephemeralY || ciphertext.length === 0 || !tag) {
1431
+ return void 0;
1432
+ }
1433
+ return {
1434
+ outputIndex,
1435
+ commitmentHashHex: fieldHex(commitment),
1436
+ createdEphemeralKey: [fieldHex(ephemeralX), fieldHex(ephemeralY)],
1437
+ ciphertext,
1438
+ tag: fieldHex(tag)
1439
+ };
1440
+ }
1441
+ function parseEscrowOutputNoteEvent(event, poolAddress) {
1442
+ if (!eventMatchesPool(event, poolAddress)) {
1443
+ return void 0;
1444
+ }
1445
+ const v0 = outputNoteEventBody(event);
1446
+ const topics = v0?.topics();
1447
+ if (!v0 || !Array.isArray(topics) || topics.length < OUTPUT_NOTE_TOPIC_COUNT) {
1448
+ return void 0;
1449
+ }
1450
+ if (extractSymbol(topics[0]) !== "audit" || extractSymbol(topics[1]) !== "output_note") {
1451
+ return void 0;
1452
+ }
1453
+ return outputNoteFromPayload(topics, payloadMap(v0.data()));
1454
+ }
1455
+
1456
+ // src/transact/escrow/fetch-output-note-events.ts
1457
+ async function fetchEscrowOutputNoteEvents(input) {
1458
+ const txId = input.txId.trim();
1459
+ if (!txId) {
1460
+ throw new Error("Escrow output-note transaction id is missing.");
1461
+ }
1462
+ const response = await createStellarRpcServer(
1463
+ input.transactEnvironment.network.rpcUrl
1464
+ ).getTransaction(txId);
1465
+ if (response.status !== Api.GetTransactionStatus.SUCCESS) {
1466
+ throw new Error("Escrow output-note transaction was not found.");
1467
+ }
1468
+ const meta = response.resultMetaXdr;
1469
+ if (!meta) {
1470
+ return [];
1471
+ }
1472
+ const events = [];
1473
+ for (const event of collectContractEventsFromMeta(meta)) {
1474
+ const parsed = parseEscrowOutputNoteEvent(event, input.poolAddress);
1475
+ if (parsed) {
1476
+ events.push(parsed);
1477
+ }
1478
+ }
1479
+ return events;
1480
+ }
1481
+
1482
+ // src/transact/escrow/simulate-escrow-authorization.ts
1483
+ import {
1484
+ Account,
1485
+ Address as Address3,
1486
+ Contract,
1487
+ nativeToScVal as nativeToScVal2,
1488
+ TransactionBuilder as TransactionBuilder2,
1489
+ rpc as rpc4
1490
+ } from "@stellar/stellar-sdk";
1491
+ import { Buffer as Buffer10 } from "buffer";
1492
+
1493
+ // src/transact/kyt/passage/inspect.ts
1494
+ import {
1495
+ layoutForKnownNonce,
1496
+ zeroBindingTagsInPublicSignals
1497
+ } from "@arcanetech/stellar-privacy-pool-zk-sdk";
1498
+
1499
+ // src/transact/kyt/inspect-error.ts
1500
+ var KytInspectError = class extends Error {
1501
+ reasonCode;
1010
1502
  decisionId;
1011
1503
  detailAddress;
1012
1504
  constructor(parameters) {
@@ -1032,18 +1524,6 @@ function parseKytReasonCode(reasonCode) {
1032
1524
  };
1033
1525
  }
1034
1526
 
1035
- // src/contracts/contract-context.ts
1036
- function requireContractContext(environment) {
1037
- if (!environment || !("contractContext" in environment)) {
1038
- throw new Error("Contract context is not configured on the transact environment.");
1039
- }
1040
- const resolved = environment;
1041
- return resolved.contractContext;
1042
- }
1043
- function readPoolClientFactory(environment) {
1044
- return requireContractContext(environment).createPoolClient;
1045
- }
1046
-
1047
1527
  // src/transact/kyt/passage/poll.ts
1048
1528
  import "@stellar/stellar-sdk";
1049
1529
  var KYT_REGISTER_MAX_POLLS = 60;
@@ -1098,20 +1578,20 @@ async function waitForKytRegistration(parameters) {
1098
1578
  }
1099
1579
 
1100
1580
  // src/transact/kyt/passage/submit.ts
1101
- import { Buffer as Buffer10 } from "buffer";
1102
- import { Operation, TransactionBuilder, rpc as rpc2, xdr } from "@stellar/stellar-sdk";
1581
+ import { Buffer as Buffer9 } from "buffer";
1582
+ import { Operation, TransactionBuilder, rpc as rpc3, xdr as xdr3 } from "@stellar/stellar-sdk";
1103
1583
  var KYT_REGISTER_FEE_STROOPS = "1000000";
1104
1584
  var KYT_REGISTER_TIMEOUT_SECONDS = 300;
1105
1585
  function passageIdToScValue(passageId) {
1106
- return xdr.ScVal.scvBytes(Buffer10.from(passageId.replace(/^0x/, ""), "hex"));
1586
+ return xdr3.ScVal.scvBytes(Buffer9.from(passageId.replace(/^0x/, ""), "hex"));
1107
1587
  }
1108
1588
  function approvalSignatureToBytes(signature) {
1109
1589
  const clean = signature.trim();
1110
- return /^(0x)?[0-9a-fA-F]{128}$/.test(clean) ? Buffer10.from(clean.replace(/^0x/i, ""), "hex") : Buffer10.from(clean, "base64");
1590
+ return /^(0x)?[0-9a-fA-F]{128}$/.test(clean) ? Buffer9.from(clean.replace(/^0x/i, ""), "hex") : Buffer9.from(clean, "base64");
1111
1591
  }
1112
1592
  function signatureToScValue(signature) {
1113
1593
  const bytes = approvalSignatureToBytes(signature);
1114
- return xdr.ScVal.scvBytes(bytes);
1594
+ return xdr3.ScVal.scvBytes(bytes);
1115
1595
  }
1116
1596
  async function registerKytPassage(parameters) {
1117
1597
  const signTransaction = parameters.transactEnvironment.signTransaction;
@@ -1121,7 +1601,7 @@ async function registerKytPassage(parameters) {
1121
1601
  );
1122
1602
  }
1123
1603
  const kytRegistry = parameters.transactEnvironment.kyt.kytPassageRegistryContract;
1124
- const server = new rpc2.Server(parameters.sorobanRpcUrl, { allowHttp: true });
1604
+ const server = new rpc3.Server(parameters.sorobanRpcUrl, { allowHttp: true });
1125
1605
  const sourceAccount = await server.getAccount(parameters.owner);
1126
1606
  const transaction = new TransactionBuilder(sourceAccount, {
1127
1607
  fee: KYT_REGISTER_FEE_STROOPS,
@@ -1132,7 +1612,7 @@ async function registerKytPassage(parameters) {
1132
1612
  function: "register_passage",
1133
1613
  args: [
1134
1614
  passageIdToScValue(parameters.approval.passageId),
1135
- xdr.ScVal.scvU32(parameters.approval.expiresAtLedger),
1615
+ xdr3.ScVal.scvU32(parameters.approval.expiresAtLedger),
1136
1616
  signatureToScValue(parameters.approval.signature)
1137
1617
  ]
1138
1618
  })
@@ -1155,15 +1635,9 @@ async function registerKytPassage(parameters) {
1155
1635
  await waitForKytRegistration({ server, hash: result.hash });
1156
1636
  }
1157
1637
 
1158
- // src/transact/environment/zk-config-nonce.ts
1159
- var DEFAULT_ZK_CONFIG_NONCE = 0n;
1160
- function resolveZkConfigNonce(transactEnvironment) {
1161
- return transactEnvironment.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
1162
- }
1163
-
1164
1638
  // src/transact/kyt/passage/inspect.ts
1165
- function buildApplicationIdHints(applicationId) {
1166
- return [applicationId, applicationId, applicationId, applicationId];
1639
+ function buildApplicationIdHints2(applicationId, nAuditSlots) {
1640
+ return uniformApplicationIdHints(applicationId, nAuditSlots);
1167
1641
  }
1168
1642
  function buildNonce() {
1169
1643
  return globalThis.crypto?.randomUUID?.() ?? `${Date.now()}`;
@@ -1191,37 +1665,61 @@ function throwKytInspectRejected(body) {
1191
1665
  ...parsed.address ? { detailAddress: parsed.address } : {}
1192
1666
  });
1193
1667
  }
1194
- async function requestKytPassageForPoolInteraction(input) {
1195
- const applicationId = resolvePoolApplicationId(
1196
- input.transactEnvironment.network.applicationId
1197
- );
1198
- const applicationIdsPlaintext = input.applicationIdsPlaintext ?? buildApplicationIdHints(applicationId);
1199
- const kytRegistry = input.transactEnvironment.kyt.kytPassageRegistryContract;
1200
- const currentLedger = await fetchCurrentLedger(input.sorobanRpcUrl);
1668
+ function inspectRequestHeaders(inspectAuthorization) {
1669
+ const token = inspectAuthorization?.trim();
1670
+ return {
1671
+ "content-type": "application/json",
1672
+ ...token ? { authorization: `Bearer ${token}` } : {}
1673
+ };
1674
+ }
1675
+ async function postKytInspect(input, applicationIdsPlaintext, zkConfigNonce, currentLedger) {
1201
1676
  const response = await fetch(
1202
1677
  `${input.transactEnvironment.kyt.apiBaseUrl}/kyt/passages/inspect`,
1203
1678
  {
1204
1679
  method: "POST",
1205
- headers: { "content-type": "application/json" },
1680
+ headers: inspectRequestHeaders(
1681
+ input.transactEnvironment.kyt.inspectAuthorization
1682
+ ),
1206
1683
  body: JSON.stringify(
1207
1684
  {
1208
1685
  owner: input.owner,
1209
1686
  poolContract: input.poolContract,
1210
- kytRegistry,
1687
+ kytRegistry: input.transactEnvironment.kyt.kytPassageRegistryContract,
1211
1688
  proofBytes: input.proofHex,
1212
- publicSignalsBytes: input.publicHex,
1689
+ publicSignalsBytes: zeroBindingTagsInPublicSignals(
1690
+ input.publicHex,
1691
+ zkConfigNonce
1692
+ ).toString("hex"),
1213
1693
  applicationIdsPlaintext,
1214
1694
  decryptedAuditSlots: input.decryptedAuditSlots,
1215
- onboarding: input.onboarding,
1216
1695
  nonce: buildNonce(),
1217
- zkConfigNonce: resolveZkConfigNonce(input.transactEnvironment),
1218
- currentLedger
1696
+ zkConfigNonce,
1697
+ currentLedger,
1698
+ ...input.ciphertextHex ? { ciphertextBytes: input.ciphertextHex } : {},
1699
+ ...input.outputNoteEphemeralScalars ? { outputNoteEphemeralScalars: input.outputNoteEphemeralScalars } : {}
1219
1700
  },
1220
1701
  kytJsonReplacer
1221
1702
  )
1222
1703
  }
1223
1704
  );
1224
- const body = await parseInspectResponse(response);
1705
+ return parseInspectResponse(response);
1706
+ }
1707
+ async function requestKytPassageForPoolInteraction(input) {
1708
+ const applicationId = resolvePoolApplicationId(
1709
+ input.transactEnvironment.network.applicationId
1710
+ );
1711
+ const zkConfigNonce = resolveZkConfigNonce(input.transactEnvironment);
1712
+ const applicationIdsPlaintext = input.applicationIdsPlaintext ?? buildApplicationIdHints2(
1713
+ applicationId,
1714
+ layoutForKnownNonce(zkConfigNonce).nAuditSlots
1715
+ );
1716
+ const currentLedger = await fetchCurrentLedger(input.sorobanRpcUrl);
1717
+ const body = await postKytInspect(
1718
+ input,
1719
+ applicationIdsPlaintext,
1720
+ zkConfigNonce,
1721
+ currentLedger
1722
+ );
1225
1723
  if (body.status !== "approved") {
1226
1724
  throwKytInspectRejected(body);
1227
1725
  }
@@ -1237,6 +1735,216 @@ async function requestKytPassageForPoolInteraction(input) {
1237
1735
  return body;
1238
1736
  }
1239
1737
 
1738
+ // src/transact/escrow/kyt-authorization-sc-value.ts
1739
+ import { nativeToScVal } from "@stellar/stellar-sdk";
1740
+ function kytAuthorizationScValue(parameters) {
1741
+ return nativeToScVal(
1742
+ {
1743
+ expiration_ledger: parameters.expirationLedger,
1744
+ signature: parameters.signature
1745
+ },
1746
+ {
1747
+ type: {
1748
+ expiration_ledger: ["symbol", "u32"],
1749
+ signature: ["symbol", "bytes"]
1750
+ }
1751
+ }
1752
+ );
1753
+ }
1754
+
1755
+ // src/transact/escrow/pick-escrow-authorization.ts
1756
+ import { Address as Address2 } from "@stellar/stellar-sdk";
1757
+ function credentialAddress(entry) {
1758
+ try {
1759
+ const credentials = entry.credentials();
1760
+ if (credentials.switch().name !== "sorobanCredentialsAddress") {
1761
+ return void 0;
1762
+ }
1763
+ return Address2.fromScAddress(credentials.address().address()).toString();
1764
+ } catch {
1765
+ return void 0;
1766
+ }
1767
+ }
1768
+ function pickUnsignedEscrowAuthorization(input) {
1769
+ const claimant = input.claimantAddress.trim();
1770
+ const match = input.auth.find((entry) => credentialAddress(entry) === claimant);
1771
+ if (!match) {
1772
+ throw new Error("Simulation did not return a claimant authorization entry.");
1773
+ }
1774
+ return match.toXDR("base64");
1775
+ }
1776
+
1777
+ // src/transact/escrow/simulate-escrow-authorization.ts
1778
+ var SIMULATE_FEE = "100";
1779
+ var SIMULATE_TIMEOUT_SECONDS = 30;
1780
+ var RECORD_NONROOT_AUTH = "record_allow_nonroot";
1781
+ function hexToBytes(hex) {
1782
+ return Buffer10.from(hex.replace(/^0x/iu, ""), "hex");
1783
+ }
1784
+ function optionalSweepCiphertext(artifacts) {
1785
+ return {
1786
+ ...artifacts?.ciphertextHex ? { ciphertextHex: artifacts.ciphertextHex } : {},
1787
+ ...artifacts?.outputNoteEphemeralScalars ? { outputNoteEphemeralScalars: artifacts.outputNoteEphemeralScalars } : {}
1788
+ };
1789
+ }
1790
+ function requireSweepArtifacts(prepared) {
1791
+ const artifacts = prepared.transactArtifacts;
1792
+ const proofHex = artifacts?.proofHex?.trim();
1793
+ const publicHex = artifacts?.publicHex?.trim();
1794
+ const escrowRecipient = artifacts?.escrowRecipient?.trim();
1795
+ if (!proofHex || !publicHex || !escrowRecipient) {
1796
+ throw new Error("Prepared sweep is missing proof, public signals, or claimant.");
1797
+ }
1798
+ return {
1799
+ proofHex,
1800
+ publicHex,
1801
+ escrowRecipient,
1802
+ ...optionalSweepCiphertext(artifacts)
1803
+ };
1804
+ }
1805
+ function requireRelayerPublicKey(value) {
1806
+ const relayerPublicKey = value.trim();
1807
+ if (!relayerPublicKey) {
1808
+ throw new Error("Escrow sweep simulation requires the relayer public key.");
1809
+ }
1810
+ return relayerPublicKey;
1811
+ }
1812
+ async function inspectRelayerSweepKyt(input) {
1813
+ const environment = input.transactEnvironment;
1814
+ return requestKytPassageForPoolInteraction({
1815
+ owner: input.relayerPublicKey,
1816
+ poolContract: environment.network.poolContract,
1817
+ proofHex: input.artifacts.proofHex,
1818
+ publicHex: input.artifacts.publicHex,
1819
+ ...input.artifacts.ciphertextHex ? { ciphertextHex: input.artifacts.ciphertextHex } : {},
1820
+ ...input.artifacts.outputNoteEphemeralScalars ? { outputNoteEphemeralScalars: input.artifacts.outputNoteEphemeralScalars } : {},
1821
+ ...input.prepared.transactArtifacts?.applicationIdsPlaintext ? {
1822
+ applicationIdsPlaintext: input.prepared.transactArtifacts.applicationIdsPlaintext
1823
+ } : {},
1824
+ networkPassphrase: environment.network.networkPassphrase,
1825
+ sorobanRpcUrl: environment.network.rpcUrl,
1826
+ transactEnvironment: environment
1827
+ });
1828
+ }
1829
+ async function simulateSweepAuthEntries(input) {
1830
+ const environment = input.transactEnvironment;
1831
+ const server = createStellarRpcServer(environment.network.rpcUrl);
1832
+ const account = await server.getAccount(input.relayerPublicKey);
1833
+ const operation = new Contract(environment.network.poolContract).call(
1834
+ "transact",
1835
+ new Address3(input.relayerPublicKey).toScVal(),
1836
+ nativeToScVal2(resolveZkConfigNonce(environment), { type: "u64" }),
1837
+ nativeToScVal2(hexToBytes(input.artifacts.proofHex), { type: "bytes" }),
1838
+ nativeToScVal2(hexToBytes(input.artifacts.publicHex), { type: "bytes" }),
1839
+ nativeToScVal2(hexToBytes(input.artifacts.ciphertextHex ?? ""), { type: "bytes" }),
1840
+ kytAuthorizationScValue({
1841
+ expirationLedger: input.approval.expiresAtLedger,
1842
+ signature: approvalSignatureToBytes(input.approval.signature)
1843
+ })
1844
+ );
1845
+ const built = new TransactionBuilder2(
1846
+ new Account(account.accountId(), account.sequenceNumber()),
1847
+ {
1848
+ fee: SIMULATE_FEE,
1849
+ networkPassphrase: environment.network.networkPassphrase
1850
+ }
1851
+ ).addOperation(operation).setTimeout(SIMULATE_TIMEOUT_SECONDS).build();
1852
+ const simulated = await server.simulateTransaction(
1853
+ built,
1854
+ { cpuInstructions: 0 },
1855
+ RECORD_NONROOT_AUTH
1856
+ );
1857
+ if (rpc4.Api.isSimulationError(simulated)) {
1858
+ throw new Error(`Escrow sweep authorization simulation failed: ${simulated.error}`);
1859
+ }
1860
+ return simulated.result?.auth ?? [];
1861
+ }
1862
+ async function unsignedEscrowAuthorizationForSweep(input) {
1863
+ const relayerPublicKey = requireRelayerPublicKey(input.relayerPublicKey);
1864
+ const artifacts = requireSweepArtifacts(input.prepared);
1865
+ const approval = await inspectRelayerSweepKyt({
1866
+ artifacts,
1867
+ prepared: input.prepared,
1868
+ transactEnvironment: input.transactEnvironment,
1869
+ relayerPublicKey
1870
+ });
1871
+ const auth = await simulateSweepAuthEntries({
1872
+ artifacts,
1873
+ transactEnvironment: input.transactEnvironment,
1874
+ relayerPublicKey,
1875
+ approval
1876
+ });
1877
+ return pickUnsignedEscrowAuthorization({
1878
+ auth,
1879
+ claimantAddress: artifacts.escrowRecipient
1880
+ });
1881
+ }
1882
+
1883
+ // src/transact/assets/load-browser.ts
1884
+ async function loadStellarBrowserAssets(input) {
1885
+ const cacheKey = input.cacheBust ? `?v=${Date.now()}` : "";
1886
+ const sdkWasm = await fetch(`${input.sdkWasmUrl}${cacheKey}`).then(
1887
+ (response) => response.arrayBuffer()
1888
+ );
1889
+ return { sdkWasm };
1890
+ }
1891
+ async function loadDefaultStellarBrowserAssets(options) {
1892
+ await import("@arcanetech/stellar-privacy-pool-zk-sdk");
1893
+ const sdkWasmUrl = new URL(
1894
+ "@arcanetech/stellar-privacy-pool-zk-sdk/sdk.wasm",
1895
+ import.meta.url
1896
+ ).href;
1897
+ return loadStellarBrowserAssets({
1898
+ sdkWasmUrl,
1899
+ ...options?.cacheBust ? { cacheBust: true } : {}
1900
+ });
1901
+ }
1902
+
1903
+ // src/transact/private-address/temporary-recipient.ts
1904
+ import { PrivacyPoolSDK as PrivacyPoolSDK3 } from "@arcanetech/stellar-privacy-pool-zk-sdk";
1905
+ var COORDINATE_HEX_LENGTH2 = 64;
1906
+ async function generateRandomDepositScalarHex() {
1907
+ await getPrivacyPoolService().getInitializedSdk();
1908
+ return PrivacyPoolSDK3.generateRandomScalarHex32();
1909
+ }
1910
+ async function generateTemporaryRecipientPrivateAddress() {
1911
+ await getPrivacyPoolService().getInitializedSdk();
1912
+ const temporaryScalarHex = PrivacyPoolSDK3.generateRandomScalarHex32();
1913
+ const sdk = await getPrivacyPoolService().getInitializedSdk();
1914
+ const point = sdk.ecdhEphemeralPublicKeyFromScalarHex(temporaryScalarHex);
1915
+ const publicKeyXHex = point.x.padStart(COORDINATE_HEX_LENGTH2, "0");
1916
+ const publicKeyYHex = point.y.padStart(COORDINATE_HEX_LENGTH2, "0");
1917
+ return {
1918
+ temporaryScalarHex,
1919
+ temporaryPrivateAddressStpl1: encodePrivateAddressFromHexCoordinates(
1920
+ publicKeyXHex,
1921
+ publicKeyYHex
1922
+ )
1923
+ };
1924
+ }
1925
+
1926
+ // src/contracts/contract-context.ts
1927
+ function requireContractContext(environment) {
1928
+ if (!environment || !("contractContext" in environment)) {
1929
+ throw new Error("Contract context is not configured on the transact environment.");
1930
+ }
1931
+ const resolved = environment;
1932
+ return resolved.contractContext;
1933
+ }
1934
+ function readPoolClientFactory(environment) {
1935
+ return requireContractContext(environment).createPoolClient;
1936
+ }
1937
+
1938
+ // src/transact/pool/proof-types.ts
1939
+ function ciphertextArtifactsFromProof(proof) {
1940
+ return {
1941
+ ...proof.ciphertext_hex === void 0 ? {} : { ciphertextHex: proof.ciphertext_hex },
1942
+ ...proof.output_note_ephemeral_scalars === void 0 ? {} : {
1943
+ outputNoteEphemeralScalars: [...proof.output_note_ephemeral_scalars]
1944
+ }
1945
+ };
1946
+ }
1947
+
1240
1948
  // src/transact/submit/ttl-preflight.ts
1241
1949
  function getNested(source, path) {
1242
1950
  let cursor = source;
@@ -1283,12 +1991,12 @@ async function runTtlPreflight(assembledTransaction) {
1283
1991
 
1284
1992
  // src/transact/submit/zk-config-ttl.ts
1285
1993
  import {
1286
- Address,
1994
+ Address as Address4,
1287
1995
  Operation as Operation2,
1288
1996
  SorobanDataBuilder,
1289
- TransactionBuilder as TransactionBuilder2,
1290
- rpc as rpc3,
1291
- xdr as xdr2
1997
+ TransactionBuilder as TransactionBuilder3,
1998
+ rpc as rpc5,
1999
+ xdr as xdr5
1292
2000
  } from "@stellar/stellar-sdk";
1293
2001
  var ZK_CONFIG_TTL_THRESHOLD_LEDGERS = 1e5;
1294
2002
  var ZK_CONFIG_TTL_EXTEND_TO_LEDGERS = 5e5;
@@ -1312,15 +2020,15 @@ async function waitForExtendFootprintTtlConfirmation(parameters) {
1312
2020
  throw new Error("ZK config TTL extension was not confirmed in time");
1313
2021
  }
1314
2022
  function zkConfigLedgerKey(contractId, nonce) {
1315
- const configKeyScValue = xdr2.ScVal.scvVec([
1316
- xdr2.ScVal.scvSymbol("Config"),
1317
- xdr2.ScVal.scvU64(xdr2.Uint64.fromString(nonce.toString()))
2023
+ const configKeyScValue = xdr5.ScVal.scvVec([
2024
+ xdr5.ScVal.scvSymbol("Config"),
2025
+ xdr5.ScVal.scvU64(xdr5.Uint64.fromString(nonce.toString()))
1318
2026
  ]);
1319
- return xdr2.LedgerKey.contractData(
1320
- new xdr2.LedgerKeyContractData({
1321
- contract: new Address(contractId).toScAddress(),
2027
+ return xdr5.LedgerKey.contractData(
2028
+ new xdr5.LedgerKeyContractData({
2029
+ contract: new Address4(contractId).toScAddress(),
1322
2030
  key: configKeyScValue,
1323
- durability: xdr2.ContractDataDurability.persistent()
2031
+ durability: xdr5.ContractDataDurability.persistent()
1324
2032
  })
1325
2033
  );
1326
2034
  }
@@ -1338,7 +2046,7 @@ async function needsTtlExtension(parameters) {
1338
2046
  }
1339
2047
  async function submitExtendFootprintTtlTransaction(parameters) {
1340
2048
  const sourceAccount = await parameters.server.getAccount(parameters.sourcePublicKey);
1341
- const transaction = new TransactionBuilder2(sourceAccount, {
2049
+ const transaction = new TransactionBuilder3(sourceAccount, {
1342
2050
  fee: EXTEND_TTL_FEE_STROOPS,
1343
2051
  networkPassphrase: parameters.networkPassphrase
1344
2052
  }).addOperation(
@@ -1352,7 +2060,7 @@ async function submitExtendFootprintTtlTransaction(parameters) {
1352
2060
  networkPassphrase: parameters.networkPassphrase,
1353
2061
  address: parameters.sourcePublicKey
1354
2062
  });
1355
- const signedTransaction = TransactionBuilder2.fromXDR(
2063
+ const signedTransaction = TransactionBuilder3.fromXDR(
1356
2064
  signedTxXdr,
1357
2065
  parameters.networkPassphrase
1358
2066
  );
@@ -1370,7 +2078,7 @@ async function extendZkConfigTtlIfNeeded(parameters) {
1370
2078
  if (!parameters.signTransaction) {
1371
2079
  return;
1372
2080
  }
1373
- const server = new rpc3.Server(parameters.sorobanRpcUrl, { allowHttp: true });
2081
+ const server = new rpc5.Server(parameters.sorobanRpcUrl, { allowHttp: true });
1374
2082
  const ledgerKey = zkConfigLedgerKey(parameters.contractId, parameters.nonce);
1375
2083
  if (!await needsTtlExtension({ server, ledgerKey })) {
1376
2084
  return;
@@ -1400,7 +2108,10 @@ async function submitPoolTransact(parameters) {
1400
2108
  nonce: parameters.nonce,
1401
2109
  proof_bytes: Buffer11.from(parameters.proofHex.replace(/^0x/iu, ""), "hex"),
1402
2110
  pub_signals_bytes: Buffer11.from(parameters.publicHex.replace(/^0x/iu, ""), "hex"),
1403
- onboarding: parameters.onboarding,
2111
+ ciphertext_bytes: Buffer11.from(
2112
+ (parameters.ciphertextHex ?? "").replace(/^0x/iu, ""),
2113
+ "hex"
2114
+ ),
1404
2115
  kyt_authorization: {
1405
2116
  expiration_ledger: parameters.approval.expiresAtLedger,
1406
2117
  signature: approvalSignatureToBytes(parameters.approval.signature)
@@ -1425,19 +2136,21 @@ async function submitSorobanDeposit(input) {
1425
2136
  });
1426
2137
  const merkleTx = await poolClient.get_merkle_root();
1427
2138
  const merkleRootBuffer = merkleTx.result;
1428
- const { applicationIdsPlaintext, proof_hex, public_hex } = await input.privacyPoolService.prepareDepositTransactProof({
2139
+ const proof = await input.privacyPoolService.prepareDepositTransactProof({
1429
2140
  privateAddressStpl1: input.privateAddressStpl1,
1430
2141
  coin: input.coin,
1431
2142
  depositScalarHex: input.depositScalarHex,
1432
2143
  merkleRootBytes: merkleRootBuffer,
1433
2144
  tokenAddress: input.tokenAddress
1434
2145
  });
2146
+ const ciphertext = ciphertextArtifactsFromProof(proof);
1435
2147
  const approval = await requestKytPassageForPoolInteraction({
1436
2148
  owner: input.walletPublicKey,
1437
2149
  poolContract: input.contractId,
1438
- proofHex: proof_hex,
1439
- publicHex: public_hex,
1440
- applicationIdsPlaintext,
2150
+ proofHex: proof.proof_hex,
2151
+ publicHex: proof.public_hex,
2152
+ applicationIdsPlaintext: proof.applicationIdsPlaintext,
2153
+ ...ciphertext,
1441
2154
  networkPassphrase: input.networkPassphrase,
1442
2155
  sorobanRpcUrl: input.sorobanRpcUrl,
1443
2156
  transactEnvironment: input.transactEnvironment
@@ -1447,8 +2160,9 @@ async function submitSorobanDeposit(input) {
1447
2160
  contractId: input.contractId,
1448
2161
  from: input.walletPublicKey,
1449
2162
  nonce: resolveZkConfigNonce(input.transactEnvironment),
1450
- proofHex: proof_hex,
1451
- publicHex: public_hex,
2163
+ proofHex: proof.proof_hex,
2164
+ publicHex: proof.public_hex,
2165
+ ...ciphertext,
1452
2166
  approval,
1453
2167
  networkPassphrase: input.networkPassphrase,
1454
2168
  sorobanRpcUrl: input.sorobanRpcUrl,
@@ -1469,7 +2183,8 @@ async function submitSorobanConfidentialTransfer(input) {
1469
2183
  poolContract: input.contractId,
1470
2184
  proofHex: input.proofHex,
1471
2185
  publicHex: input.publicHex,
1472
- ...input.onboarding ? { onboarding: input.onboarding } : {},
2186
+ ...input.ciphertextHex ? { ciphertextHex: input.ciphertextHex } : {},
2187
+ ...input.outputNoteEphemeralScalars ? { outputNoteEphemeralScalars: input.outputNoteEphemeralScalars } : {},
1473
2188
  ...input.applicationIdsPlaintext ? { applicationIdsPlaintext: input.applicationIdsPlaintext } : {},
1474
2189
  networkPassphrase: input.networkPassphrase,
1475
2190
  sorobanRpcUrl: input.sorobanRpcUrl,
@@ -1482,7 +2197,7 @@ async function submitSorobanConfidentialTransfer(input) {
1482
2197
  nonce: resolveZkConfigNonce(input.transactEnvironment),
1483
2198
  proofHex: input.proofHex,
1484
2199
  publicHex: input.publicHex,
1485
- ...input.onboarding ? { onboarding: input.onboarding } : {},
2200
+ ...input.ciphertextHex ? { ciphertextHex: input.ciphertextHex } : {},
1486
2201
  approval,
1487
2202
  networkPassphrase: input.networkPassphrase,
1488
2203
  sorobanRpcUrl: input.sorobanRpcUrl,
@@ -1490,14 +2205,19 @@ async function submitSorobanConfidentialTransfer(input) {
1490
2205
  });
1491
2206
  }
1492
2207
 
1493
- // src/transact/onboarding/recipient-change-deposits.ts
1494
- async function buildPaddingDepositPair(recipientPrivateAddressStpl1, tokenAddress, recipientDeposit) {
1495
- const paddingSlot = await getPrivacyPoolService().buildAlignedDepositSlot({
1496
- privateAddressStpl1: recipientPrivateAddressStpl1,
1497
- amountStroops: ZERO_STROOPS,
1498
- tokenAddress
1499
- });
1500
- return [recipientDeposit, paddingSlot.deposit];
2208
+ // src/transact/proofs/confidential/recipient-change-deposits.ts
2209
+ function escrowOutputFields(input) {
2210
+ if (!input.escrowSend) {
2211
+ return {};
2212
+ }
2213
+ return {
2214
+ escrowNonce: input.escrowSend.nonceDecimal,
2215
+ recipientHi: input.escrowSend.recipientHi,
2216
+ recipientLo: input.escrowSend.recipientLo
2217
+ };
2218
+ }
2219
+ function paddingDepositPair(recipientDeposit) {
2220
+ return [recipientDeposit, "dummy"];
1501
2221
  }
1502
2222
  async function buildChangeDepositPair(parameters) {
1503
2223
  const changeSlot = await getPrivacyPoolService().buildAlignedDepositSlot({
@@ -1516,24 +2236,24 @@ async function buildChangeDepositPair(parameters) {
1516
2236
  };
1517
2237
  }
1518
2238
  async function buildRecipientAndOptionalChangeDeposits(parameters) {
2239
+ const escrow = {
2240
+ ...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
2241
+ ...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
2242
+ };
1519
2243
  const recipientPrivateAddress = parameters.recipientPrivateAddressStpl1.trim();
1520
2244
  const recipientSlot = await getPrivacyPoolService().buildAlignedDepositSlot({
1521
2245
  privateAddressStpl1: recipientPrivateAddress,
1522
2246
  amountStroops: parameters.transferStroops,
1523
- tokenAddress: parameters.tokenAddress
2247
+ tokenAddress: parameters.tokenAddress,
2248
+ ...escrowOutputFields(escrow)
1524
2249
  });
1525
2250
  if (parameters.changeStroops <= ZERO_STROOPS) {
1526
2251
  return {
1527
2252
  recipientSlot,
1528
- deposits: await buildPaddingDepositPair(
1529
- recipientPrivateAddress,
1530
- parameters.tokenAddress,
1531
- recipientSlot.deposit
1532
- )
2253
+ deposits: paddingDepositPair(recipientSlot.deposit)
1533
2254
  };
1534
2255
  }
1535
2256
  const changeResult = await buildChangeDepositPair({
1536
- recipientPrivateAddressStpl1: recipientPrivateAddress,
1537
2257
  selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
1538
2258
  changeStroops: parameters.changeStroops,
1539
2259
  tokenAddress: parameters.tokenAddress,
@@ -1555,20 +2275,61 @@ function generatedOutputCoinFromSlot(slot) {
1555
2275
  precommitementHex: slot.precommitementHex
1556
2276
  };
1557
2277
  }
2278
+ function publicEscrowRecipientLimbs(parameters) {
2279
+ const limbs = parameters.escrowClaimantLimbs;
2280
+ if (!limbs) {
2281
+ return void 0;
2282
+ }
2283
+ return {
2284
+ escrowRecipientHi: limbs.recipientHi,
2285
+ escrowRecipientLo: limbs.recipientLo
2286
+ };
2287
+ }
2288
+ function sweepWithdrawStamp(parameters) {
2289
+ const publicLimbs = publicEscrowRecipientLimbs(parameters);
2290
+ if (!publicLimbs) {
2291
+ return void 0;
2292
+ }
2293
+ return {
2294
+ ...publicLimbs,
2295
+ ...parameters.escrowClaimantLimbs?.nonceDecimal ? { escrowNonce: parameters.escrowClaimantLimbs.nonceDecimal } : {}
2296
+ };
2297
+ }
2298
+ function stampWithdrawEscrowLimbs(withdrawObject, limbs) {
2299
+ if (!limbs) {
2300
+ return withdrawObject;
2301
+ }
2302
+ return {
2303
+ ...withdrawObject,
2304
+ recipientStellar: [limbs.escrowRecipientHi, limbs.escrowRecipientLo],
2305
+ ...limbs.escrowNonce ? { escrowNonce: limbs.escrowNonce } : {}
2306
+ };
2307
+ }
2308
+ function sweepOutputOwnerFields(parameters) {
2309
+ if (!parameters.escrowClaimantLimbs) {
2310
+ return void 0;
2311
+ }
2312
+ const [sweepOutputOwnerPubX, sweepOutputOwnerPubY] = recipientPublicKeysDecimalFromPrivateAddress(
2313
+ parameters.recipientPrivateAddressStpl1
2314
+ );
2315
+ return { sweepOutputOwnerPubX, sweepOutputOwnerPubY };
2316
+ }
1558
2317
  async function buildTransferDepositsAndPublicInput(parameters) {
1559
2318
  const { recipientSlot, deposits, changeCoin } = await buildRecipientAndOptionalChangeDeposits({
1560
2319
  recipientPrivateAddressStpl1: parameters.recipientPrivateAddressStpl1,
1561
2320
  transferStroops: parameters.transferStroops,
1562
2321
  changeStroops: parameters.changeStroops,
1563
2322
  selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
1564
- tokenAddress: parameters.tokenAddress
2323
+ tokenAddress: parameters.tokenAddress,
2324
+ ...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
2325
+ ...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
1565
2326
  });
1566
2327
  const publicInput = withTokenAddressPublicInputs(
1567
2328
  {
1568
2329
  stateRoot: parameters.stateRoot,
1569
- withdrawAddressHi: parameters.withdrawAddressHi,
1570
- withdrawAddressLo: parameters.withdrawAddressLo,
1571
- privKeyScalar: parameters.privKeyScalar
2330
+ privKeyScalar: parameters.privKeyScalar,
2331
+ ...publicEscrowRecipientLimbs(parameters),
2332
+ ...sweepOutputOwnerFields(parameters)
1572
2333
  },
1573
2334
  parameters.tokenAddress
1574
2335
  );
@@ -1580,10 +2341,6 @@ async function buildTransferDepositsAndPublicInput(parameters) {
1580
2341
  };
1581
2342
  }
1582
2343
  async function buildSenderTransferDepositsAndPublicInput(parameters) {
1583
- const { hi, lo, privKeyScalar } = senderWithdrawFrAndScalar({
1584
- senderGAddress: parameters.senderGAddress,
1585
- senderPrivKeyScalarHex: parameters.senderPrivKeyScalarHex
1586
- });
1587
2344
  return buildTransferDepositsAndPublicInput({
1588
2345
  recipientPrivateAddressStpl1: parameters.recipientPrivateAddressStpl1,
1589
2346
  transferStroops: parameters.transferStroops,
@@ -1591,31 +2348,55 @@ async function buildSenderTransferDepositsAndPublicInput(parameters) {
1591
2348
  selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
1592
2349
  tokenAddress: parameters.tokenAddress,
1593
2350
  stateRoot: parameters.stateRoot,
1594
- withdrawAddressHi: hi,
1595
- withdrawAddressLo: lo,
1596
- privKeyScalar
2351
+ privKeyScalar: privKeyScalarDecimalFromRecipientScalarHex(
2352
+ parameters.senderPrivKeyScalarHex
2353
+ ),
2354
+ ...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
2355
+ ...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
1597
2356
  });
1598
2357
  }
1599
2358
 
1600
2359
  // src/transact/proofs/confidential/dual.ts
1601
- function buildDualTransferApplicationIds(applicationId, changeCoin) {
1602
- return [
1603
- applicationId,
1604
- applicationId,
1605
- applicationId,
1606
- changeCoin ? applicationId : "0"
1607
- ];
2360
+ function confidentialEscrowFields(parameters) {
2361
+ return {
2362
+ ...parameters.escrowSend ? { escrowSend: parameters.escrowSend } : {},
2363
+ ...parameters.escrowClaimantLimbs ? { escrowClaimantLimbs: parameters.escrowClaimantLimbs } : {}
2364
+ };
2365
+ }
2366
+ function stampDualWithdrawLegs(legs, parameters) {
2367
+ const escrowLimbs = sweepWithdrawStamp(confidentialEscrowFields(parameters));
2368
+ return {
2369
+ legA: {
2370
+ ...legs.legA,
2371
+ withdrawObject: stampWithdrawEscrowLimbs(legs.legA.withdrawObject, escrowLimbs)
2372
+ },
2373
+ legB: {
2374
+ ...legs.legB,
2375
+ withdrawObject: stampWithdrawEscrowLimbs(legs.legB.withdrawObject, escrowLimbs)
2376
+ }
2377
+ };
2378
+ }
2379
+ function buildDualTransferApplicationIds(sdk, applicationId, changeCoin) {
2380
+ return buildApplicationIdHints({
2381
+ sdk,
2382
+ inputIds: [applicationId, applicationId],
2383
+ outputIds: [applicationId, changeCoin ? applicationId : "0"]
2384
+ });
1608
2385
  }
1609
2386
  async function proveDualConfidentialTransfer(parameters) {
1610
2387
  const audit = buildPoolTransactionAuditParameters({
1611
2388
  applicationId: parameters.applicationId,
2389
+ nAuditSlots: parameters.sdk.getLayout().nAuditSlots,
1612
2390
  ...parameters.auditPublicKey ? { auditPublicKey: parameters.auditPublicKey } : {}
1613
2391
  });
1614
2392
  return parameters.sdk.proveTransaction(
1615
2393
  parameters.publicInput,
1616
- buildZeroPublicLegs(),
1617
- [parameters.legA.withdrawObject, parameters.legB.withdrawObject],
1618
- parameters.deposits,
2394
+ padPublicLegsToLayout(parameters.sdk, buildZeroPublicLegs()),
2395
+ padWithdrawSlotsToLayout(parameters.sdk, [
2396
+ parameters.legA.withdrawObject,
2397
+ parameters.legB.withdrawObject
2398
+ ]),
2399
+ padDepositSlotsToLayout(parameters.sdk, parameters.deposits),
1619
2400
  audit
1620
2401
  );
1621
2402
  }
@@ -1629,24 +2410,33 @@ async function buildDualTransferProofContext(parameters, applicationId, sdk) {
1629
2410
  changeStroops,
1630
2411
  parameters.selfPrivateAddressStpl1ForChange
1631
2412
  );
1632
- const { legA, legB } = dualWithdrawLegsWithSharedRoot({
1633
- sdk,
1634
- coinA: parameters.coinA,
1635
- coinB: parameters.coinB,
1636
- state: parameters.state,
1637
- ephemeralA: parseEphemeralKeyString(parameters.ephemeralAKey),
1638
- ephemeralB: parseEphemeralKeyString(parameters.ephemeralBKey),
1639
- applicationId
1640
- });
2413
+ const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
2414
+ parameters.senderPrivKeyScalarHex
2415
+ );
2416
+ const ownerPubHex = sdk.ecdhEphemeralPublicKeyFromScalarHex(
2417
+ parameters.senderPrivKeyScalarHex
2418
+ );
2419
+ const { legA, legB } = stampDualWithdrawLegs(
2420
+ dualWithdrawLegsWithSharedRoot({
2421
+ sdk,
2422
+ coinA: parameters.coinA,
2423
+ coinB: parameters.coinB,
2424
+ state: parameters.state,
2425
+ ownerPubHex,
2426
+ privKeyScalar,
2427
+ applicationId
2428
+ }),
2429
+ parameters
2430
+ );
1641
2431
  const transferInputs = await buildSenderTransferDepositsAndPublicInput({
1642
- senderGAddress: parameters.senderGAddress,
1643
2432
  senderPrivKeyScalarHex: parameters.senderPrivKeyScalarHex,
1644
2433
  recipientPrivateAddressStpl1: parameters.recipientPrivateAddressStpl1,
1645
2434
  transferStroops: parameters.transferStroops,
1646
2435
  changeStroops,
1647
2436
  selfPrivateAddressStpl1ForChange: parameters.selfPrivateAddressStpl1ForChange,
1648
2437
  tokenAddress: parameters.tokenAddress,
1649
- stateRoot: legA.witness.stateRoot
2438
+ stateRoot: legA.witness.stateRoot,
2439
+ ...confidentialEscrowFields(parameters)
1650
2440
  });
1651
2441
  return { legA, legB, applicationId, ...transferInputs };
1652
2442
  }
@@ -1674,7 +2464,11 @@ async function prepareConfidentialTransferProofDual(parameters) {
1674
2464
  }));
1675
2465
  return {
1676
2466
  ...proof,
1677
- applicationIdsPlaintext: buildDualTransferApplicationIds(applicationId, changeCoin),
2467
+ applicationIdsPlaintext: buildDualTransferApplicationIds(
2468
+ sdk,
2469
+ applicationId,
2470
+ changeCoin
2471
+ ),
1678
2472
  recipientCoin: generatedOutputCoinFromSlot(recipientSlot),
1679
2473
  ...changeCoin ? { changeCoin } : {}
1680
2474
  };
@@ -1692,51 +2486,72 @@ function validateSingleCoinTransferAmounts(transferStroops, noteStroops, selfPri
1692
2486
  requireChangeRecipientWhenPartial(changeStroops, selfPrivateAddressStpl1ForChange);
1693
2487
  return changeStroops;
1694
2488
  }
1695
- function buildSingleTransferApplicationIds(applicationId, changeCoin) {
1696
- return [applicationId, "0", applicationId, changeCoin ? applicationId : "0"];
2489
+ function buildSingleTransferApplicationIds(sdk, applicationId, changeCoin) {
2490
+ return buildApplicationIdHints({
2491
+ sdk,
2492
+ inputIds: [applicationId],
2493
+ outputIds: [applicationId, changeCoin ? applicationId : "0"]
2494
+ });
1697
2495
  }
1698
2496
  function buildTransferAuditParameters(parameters) {
1699
2497
  const auditPublicKey = parameters.poolService.getAuditPublicKey();
1700
2498
  return buildPoolTransactionAuditParameters({
1701
2499
  applicationId: parameters.applicationId,
2500
+ nAuditSlots: parameters.nAuditSlots,
1702
2501
  ...auditPublicKey ? { auditPublicKey } : {}
1703
2502
  });
1704
2503
  }
1705
2504
  async function proveTransaction(parameters) {
1706
2505
  return parameters.sdk.proveTransaction(
1707
2506
  parameters.publicInput,
1708
- buildZeroPublicLegs(),
1709
- [parameters.withdrawObject, "dummy"],
1710
- parameters.deposits,
2507
+ padPublicLegsToLayout(parameters.sdk, buildZeroPublicLegs()),
2508
+ padWithdrawSlotsToLayout(parameters.sdk, [parameters.withdrawObject]),
2509
+ padDepositSlotsToLayout(parameters.sdk, parameters.deposits),
1711
2510
  parameters.audit
1712
2511
  );
1713
2512
  }
2513
+ function confidentialEscrowFields2(input) {
2514
+ return {
2515
+ ...input.escrowSend ? { escrowSend: input.escrowSend } : {},
2516
+ ...input.escrowClaimantLimbs ? { escrowClaimantLimbs: input.escrowClaimantLimbs } : {}
2517
+ };
2518
+ }
1714
2519
  async function buildTransferProofInputs(parameters) {
1715
2520
  const changeStroops = validateSingleCoinTransferAmounts(
1716
2521
  parameters.input.transferStroops,
1717
2522
  parameters.noteStroops,
1718
2523
  parameters.input.selfPrivateAddressStpl1ForChange
1719
2524
  );
2525
+ const privKeyScalar = privKeyScalarDecimalFromRecipientScalarHex(
2526
+ parameters.input.senderPrivKeyScalarHex
2527
+ );
1720
2528
  const { witness, withdrawObject } = withdrawWitnessForCoin({
1721
2529
  sdk: parameters.sdk,
1722
2530
  coin: parameters.input.coin,
1723
2531
  state: parameters.input.state,
1724
- ...parseEphemeralKeyString(parameters.input.depositorEphemeralKey),
2532
+ ownerPubHex: parameters.sdk.ecdhEphemeralPublicKeyFromScalarHex(
2533
+ parameters.input.senderPrivKeyScalarHex
2534
+ ),
2535
+ privKeyScalar,
1725
2536
  applicationId: parameters.applicationId
1726
2537
  });
2538
+ const stampedWithdraw = stampWithdrawEscrowLimbs(
2539
+ withdrawObject,
2540
+ sweepWithdrawStamp(confidentialEscrowFields2(parameters.input))
2541
+ );
1727
2542
  const { recipientSlot, deposits, changeCoin, publicInput } = await buildSenderTransferDepositsAndPublicInput({
1728
- senderGAddress: parameters.input.senderGAddress,
1729
2543
  senderPrivKeyScalarHex: parameters.input.senderPrivKeyScalarHex,
1730
2544
  recipientPrivateAddressStpl1: parameters.input.recipientPrivateAddressStpl1,
1731
2545
  transferStroops: parameters.input.transferStroops,
1732
2546
  changeStroops,
1733
2547
  selfPrivateAddressStpl1ForChange: parameters.input.selfPrivateAddressStpl1ForChange,
1734
2548
  tokenAddress: parameters.input.tokenAddress,
1735
- stateRoot: witness.stateRoot
2549
+ stateRoot: witness.stateRoot,
2550
+ ...confidentialEscrowFields2(parameters.input)
1736
2551
  });
1737
2552
  return {
1738
2553
  witness,
1739
- withdrawObject,
2554
+ withdrawObject: stampedWithdraw,
1740
2555
  recipientSlot,
1741
2556
  deposits,
1742
2557
  changeCoin,
@@ -1754,7 +2569,11 @@ async function prepareConfidentialTransferProof(parameters) {
1754
2569
  input: parameters,
1755
2570
  noteStroops
1756
2571
  });
1757
- const audit = buildTransferAuditParameters({ poolService, applicationId });
2572
+ const audit = buildTransferAuditParameters({
2573
+ poolService,
2574
+ applicationId,
2575
+ nAuditSlots: sdk.getLayout().nAuditSlots
2576
+ });
1758
2577
  const proof = await proveTransaction({
1759
2578
  sdk,
1760
2579
  publicInput,
@@ -1765,6 +2584,7 @@ async function prepareConfidentialTransferProof(parameters) {
1765
2584
  return {
1766
2585
  ...proof,
1767
2586
  applicationIdsPlaintext: buildSingleTransferApplicationIds(
2587
+ sdk,
1768
2588
  applicationId,
1769
2589
  changeCoin
1770
2590
  ),
@@ -1896,12 +2716,25 @@ async function readLeafEphemeralHex(parameters) {
1896
2716
  return { xHex, yHex };
1897
2717
  }
1898
2718
 
2719
+ // src/transact/encoding/fr-decimal-to-bytes.ts
2720
+ var BN254_SCALAR_MOD = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
2721
+ var FIELD_BYTE_LENGTH2 = 32;
2722
+ var BYTE_MASK = 0xffn;
2723
+ var BITS_PER_BYTE = 8n;
2724
+ function frDecimalToPaddedBytes32(decimal) {
2725
+ let value = BigInt(decimal.trim());
2726
+ value = (value % BN254_SCALAR_MOD + BN254_SCALAR_MOD) % BN254_SCALAR_MOD;
2727
+ const bytes = Buffer.alloc(FIELD_BYTE_LENGTH2);
2728
+ for (let index = FIELD_BYTE_LENGTH2 - 1; index >= 0; index -= 1) {
2729
+ bytes[index] = Number(value & BYTE_MASK);
2730
+ value >>= BITS_PER_BYTE;
2731
+ }
2732
+ return bytes;
2733
+ }
2734
+
1899
2735
  // src/state/foundation/paths.ts
1900
2736
  var STELLAR_STATE_PATHS = {
1901
2737
  privateRecords: "$.privateRecords",
1902
- pendingClaimsItems: "$.pendingClaims.items",
1903
- pendingClaimsPagination: "$.pendingClaims.pagination",
1904
- pendingClaimsCountByOwner: "$.pendingClaims.countByOwner",
1905
2738
  registryPrivateAddresses: "$.registry.privateAddresses",
1906
2739
  registryRegisteredAddresses: "$.registry.registeredAddresses",
1907
2740
  registryLookups: "$.registry.lookups",
@@ -1921,25 +2754,6 @@ var STELLAR_STATE_PATHS = {
1921
2754
 
1922
2755
  // src/state/schemas/shared.ts
1923
2756
  import { z } from "zod";
1924
- var pendingClaimSchema = z.object({
1925
- id: z.string().min(1),
1926
- owner: z.string().min(1),
1927
- asset: z.string().min(1),
1928
- amount: z.coerce.bigint(),
1929
- createdAt: z.string().min(1),
1930
- poolTxId: z.string().optional(),
1931
- commitmentHex: z.string().optional(),
1932
- nullifierHex: z.string().optional(),
1933
- futureNullifierHashHex: z.string().optional(),
1934
- assetHiHex: z.string().optional(),
1935
- assetLoHex: z.string().optional(),
1936
- nullifierFieldHex: z.string().optional(),
1937
- secretHex: z.string().optional(),
1938
- tempPublicKeyXHex: z.string().optional(),
1939
- tempPublicKeyYHex: z.string().optional(),
1940
- encryptedRecoveryBase64: z.string().optional(),
1941
- createdAtLedger: z.number().int().optional()
1942
- });
1943
2757
  var paginationSchema = z.object({
1944
2758
  total: z.number().int().nonnegative(),
1945
2759
  page: z.number().int().positive(),
@@ -2109,26 +2923,6 @@ function normalizePublicBalancesFromEntries(value, owner) {
2109
2923
  }).filter((balance) => balance !== void 0);
2110
2924
  }
2111
2925
 
2112
- // src/state/read/normalize/claims.ts
2113
- function normalizePendingClaimsState(value) {
2114
- if (typeof value !== "object" || value === null) {
2115
- return { items: [] };
2116
- }
2117
- const record = value;
2118
- const items = Array.isArray(record.items) ? record.items.flatMap((item) => {
2119
- const parsed = pendingClaimSchema.safeParse(item);
2120
- return parsed.success ? [withoutUndefinedFields(parsed.data)] : [];
2121
- }) : [];
2122
- const paginationResult = paginationSchema.safeParse(record.pagination);
2123
- if (paginationResult.success) {
2124
- return { items, pagination: paginationResult.data };
2125
- }
2126
- return { items };
2127
- }
2128
- function normalizePendingClaimsCount(value) {
2129
- return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : void 0;
2130
- }
2131
-
2132
2926
  // src/state/read/normalize/deliveries.ts
2133
2927
  function normalizeIncomingDeliveries(value) {
2134
2928
  const entries = typeof value === "object" && value !== null && !Array.isArray(value) ? Object.values(value) : value;
@@ -2251,8 +3045,7 @@ import { registerArrayFilterItemSchema } from "@arcanetech/privacy-sdk-core/stat
2251
3045
 
2252
3046
  // src/state/filters/ops.ts
2253
3047
  var stellarArrayFilterSchemaKeys = {
2254
- privateRecord: "privateRecord",
2255
- pendingClaim: "pendingClaim"
3048
+ privateRecord: "privateRecord"
2256
3049
  };
2257
3050
  function rejectPrivateRecordsByIds(ids) {
2258
3051
  return {
@@ -2278,56 +3071,6 @@ function rejectConsumedPrivateRecords() {
2278
3071
  }
2279
3072
  };
2280
3073
  }
2281
- function rejectPendingClaimsByOwner(owner) {
2282
- return {
2283
- opType: "arrayFilter",
2284
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsItems,
2285
- itemSchemaKey: stellarArrayFilterSchemaKeys.pendingClaim,
2286
- rejectWhen: {
2287
- op: "fieldEquals",
2288
- field: "owner",
2289
- value: owner
2290
- }
2291
- };
2292
- }
2293
- function rejectPendingClaimsByIds(ids) {
2294
- return {
2295
- opType: "arrayFilter",
2296
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsItems,
2297
- itemSchemaKey: stellarArrayFilterSchemaKeys.pendingClaim,
2298
- rejectWhen: {
2299
- op: "fieldIn",
2300
- field: "id",
2301
- values: ids
2302
- }
2303
- };
2304
- }
2305
- function rejectPendingClaimsByOwnerAndAsset(input) {
2306
- const matches = [];
2307
- if (input.owner !== void 0) {
2308
- matches.push({
2309
- op: "fieldEquals",
2310
- field: "owner",
2311
- value: input.owner
2312
- });
2313
- }
2314
- if (input.asset !== void 0) {
2315
- matches.push({
2316
- op: "fieldEquals",
2317
- field: "asset",
2318
- value: input.asset
2319
- });
2320
- }
2321
- return {
2322
- opType: "arrayFilter",
2323
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsItems,
2324
- itemSchemaKey: stellarArrayFilterSchemaKeys.pendingClaim,
2325
- rejectWhen: {
2326
- op: "and",
2327
- matches
2328
- }
2329
- };
2330
- }
2331
3074
 
2332
3075
  // src/state/filters/register-schemas.ts
2333
3076
  var registered = false;
@@ -2339,24 +3082,12 @@ function registerStellarArrayFilterSchemas() {
2339
3082
  stellarArrayFilterSchemaKeys.privateRecord,
2340
3083
  privateRecordSchema
2341
3084
  );
2342
- registerArrayFilterItemSchema(
2343
- stellarArrayFilterSchemaKeys.pendingClaim,
2344
- pendingClaimSchema
2345
- );
2346
3085
  registered = true;
2347
3086
  }
2348
3087
 
2349
3088
  // src/state/bridge/call-types.ts
2350
3089
  import "@arcanetech/privacy-sdk-core/state";
2351
3090
  var stellarStateCallTypes = {
2352
- pendingClaims: "pendingClaims",
2353
- clearPendingClaims: "clearPendingClaims",
2354
- readPendingClaims: "readPendingClaims",
2355
- replacePendingClaimsPage: "replacePendingClaimsPage",
2356
- upsertPendingClaims: "upsertPendingClaims",
2357
- removePendingClaims: "removePendingClaims",
2358
- setPendingClaimsCount: "setPendingClaimsCount",
2359
- readPendingClaimsCount: "readPendingClaimsCount",
2360
3091
  readStellarAddressRegistered: "readStellarAddressRegistered",
2361
3092
  readCachedPrivateAddress: "readCachedPrivateAddress",
2362
3093
  readRegistryLookup: "readRegistryLookup",
@@ -2583,194 +3314,10 @@ var stellarBalancesStateDefinitions = [
2583
3314
  }
2584
3315
  ];
2585
3316
 
2586
- // src/state/schemas/claims/write.ts
2587
- import { z as z5 } from "zod";
2588
- var pendingClaimsWriteSchema = z5.object({
2589
- type: z5.literal(stellarStateCallTypes.pendingClaims),
2590
- claims: z5.array(pendingClaimSchema),
2591
- paginationInfo: paginationSchema
2592
- }).transform(({ type, claims, paginationInfo }) => ({
2593
- type,
2594
- operations: [
2595
- {
2596
- opType: "arrayPush",
2597
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsItems,
2598
- items: claims
2599
- },
2600
- {
2601
- opType: "primitiveSet",
2602
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsPagination,
2603
- value: paginationInfo
2604
- }
2605
- ]
2606
- }));
2607
- var clearPendingClaimsSchema = z5.object({
2608
- type: z5.literal(stellarStateCallTypes.clearPendingClaims),
2609
- owner: z5.string().optional(),
2610
- asset: z5.string().optional()
2611
- }).transform(({ type, owner, asset }) => {
2612
- if (owner === void 0 && asset === void 0) {
2613
- return {
2614
- type,
2615
- operations: [
2616
- {
2617
- opType: "arrayClean",
2618
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsItems
2619
- }
2620
- ]
2621
- };
2622
- }
2623
- return {
2624
- type,
2625
- operations: [rejectPendingClaimsByOwnerAndAsset({ owner, asset })]
2626
- };
2627
- });
2628
- var readPendingClaimsSchema = z5.object({
2629
- type: z5.literal(stellarStateCallTypes.readPendingClaims)
2630
- }).transform(({ type }) => ({
2631
- type,
2632
- operations: [
2633
- {
2634
- opType: "primitiveGet",
2635
- jsonPath: "$.pendingClaims"
2636
- }
2637
- ]
2638
- }));
2639
-
2640
- // src/state/schemas/claims/page.ts
2641
- import { z as z6 } from "zod";
2642
- var pendingClaimBridgeItemSchema = pendingClaimSchema;
2643
- var replacePendingClaimsPageSchema = z6.object({
2644
- type: z6.literal(stellarStateCallTypes.replacePendingClaimsPage),
2645
- owner: z6.string().min(1),
2646
- claims: z6.array(pendingClaimBridgeItemSchema),
2647
- paginationInfo: z6.object({
2648
- total: z6.number().int().nonnegative(),
2649
- page: z6.number().int().positive(),
2650
- pageSize: z6.number().int().positive(),
2651
- hasMore: z6.boolean()
2652
- }),
2653
- count: z6.number().int().nonnegative().optional()
2654
- }).transform(({ type, owner, claims, paginationInfo, count }) => ({
2655
- type,
2656
- operations: [
2657
- rejectPendingClaimsByOwner(owner),
2658
- {
2659
- opType: "arrayPush",
2660
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsItems,
2661
- items: claims
2662
- },
2663
- {
2664
- opType: "primitiveSet",
2665
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsPagination,
2666
- value: paginationInfo
2667
- },
2668
- {
2669
- opType: "recordSet",
2670
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsCountByOwner,
2671
- key: owner,
2672
- value: count ?? paginationInfo.total
2673
- }
2674
- ]
2675
- }));
2676
- var upsertPendingClaimsSchema = z6.object({
2677
- type: z6.literal(stellarStateCallTypes.upsertPendingClaims),
2678
- claims: z6.array(pendingClaimBridgeItemSchema)
2679
- }).transform(({ type, claims }) => ({
2680
- type,
2681
- operations: [
2682
- rejectPendingClaimsByIds(claims.map((claim) => claim.id)),
2683
- {
2684
- opType: "arrayPush",
2685
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsItems,
2686
- items: claims
2687
- }
2688
- ]
2689
- }));
2690
- var removePendingClaimsSchema = z6.object({
2691
- type: z6.literal(stellarStateCallTypes.removePendingClaims),
2692
- ids: z6.array(z6.string().min(1))
2693
- }).transform(({ type, ids }) => ({
2694
- type,
2695
- operations: [rejectPendingClaimsByIds(ids)]
2696
- }));
2697
- var readPendingClaimsCountSchema = z6.object({
2698
- type: z6.literal(stellarStateCallTypes.readPendingClaimsCount),
2699
- owner: z6.string().min(1)
2700
- }).transform(({ type, owner }) => ({
2701
- type,
2702
- operations: [
2703
- {
2704
- opType: "recordGet",
2705
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsCountByOwner,
2706
- key: owner
2707
- }
2708
- ]
2709
- }));
2710
- var setPendingClaimsCountSchema = z6.object({
2711
- type: z6.literal(stellarStateCallTypes.setPendingClaimsCount),
2712
- owner: z6.string().min(1),
2713
- count: z6.number().int().nonnegative()
2714
- }).transform(({ type, owner, count }) => ({
2715
- type,
2716
- operations: [
2717
- {
2718
- opType: "recordSet",
2719
- jsonPath: STELLAR_STATE_PATHS.pendingClaimsCountByOwner,
2720
- key: owner,
2721
- value: count
2722
- }
2723
- ]
2724
- }));
2725
-
2726
- // src/state/definitions/claims.ts
2727
- var stellarClaimsStateDefinitions = [
2728
- {
2729
- type: stellarStateCallTypes.pendingClaims,
2730
- mode: "write",
2731
- schema: pendingClaimsWriteSchema
2732
- },
2733
- {
2734
- type: stellarStateCallTypes.clearPendingClaims,
2735
- mode: "write",
2736
- schema: clearPendingClaimsSchema
2737
- },
2738
- {
2739
- type: stellarStateCallTypes.readPendingClaims,
2740
- mode: "read",
2741
- schema: readPendingClaimsSchema
2742
- },
2743
- {
2744
- type: stellarStateCallTypes.replacePendingClaimsPage,
2745
- mode: "write",
2746
- schema: replacePendingClaimsPageSchema
2747
- },
2748
- {
2749
- type: stellarStateCallTypes.upsertPendingClaims,
2750
- mode: "write",
2751
- schema: upsertPendingClaimsSchema
2752
- },
2753
- {
2754
- type: stellarStateCallTypes.removePendingClaims,
2755
- mode: "write",
2756
- schema: removePendingClaimsSchema
2757
- },
2758
- {
2759
- type: stellarStateCallTypes.readPendingClaimsCount,
2760
- mode: "read",
2761
- schema: readPendingClaimsCountSchema
2762
- },
2763
- {
2764
- type: stellarStateCallTypes.setPendingClaimsCount,
2765
- mode: "write",
2766
- schema: setPendingClaimsCountSchema
2767
- }
2768
- ];
2769
-
2770
3317
  // src/state/schemas/claims/deliveries.ts
2771
- import { z as z7 } from "zod";
2772
- var readIncomingDeliveriesSchema = z7.object({
2773
- type: z7.literal(stellarStateCallTypes.readIncomingDeliveries)
3318
+ import { z as z5 } from "zod";
3319
+ var readIncomingDeliveriesSchema = z5.object({
3320
+ type: z5.literal(stellarStateCallTypes.readIncomingDeliveries)
2774
3321
  }).transform(({ type }) => ({
2775
3322
  type,
2776
3323
  operations: [
@@ -2780,9 +3327,9 @@ var readIncomingDeliveriesSchema = z7.object({
2780
3327
  }
2781
3328
  ]
2782
3329
  }));
2783
- var upsertIncomingDeliveriesSchema = z7.object({
2784
- type: z7.literal(stellarStateCallTypes.upsertIncomingDeliveries),
2785
- deliveries: z7.array(incomingDeliverySchema)
3330
+ var upsertIncomingDeliveriesSchema = z5.object({
3331
+ type: z5.literal(stellarStateCallTypes.upsertIncomingDeliveries),
3332
+ deliveries: z5.array(incomingDeliverySchema)
2786
3333
  }).transform(({ type, deliveries }) => ({
2787
3334
  type,
2788
3335
  operations: deliveries.map((delivery) => ({
@@ -2792,10 +3339,10 @@ var upsertIncomingDeliveriesSchema = z7.object({
2792
3339
  value: delivery
2793
3340
  }))
2794
3341
  }));
2795
- var readDeliverySyncStateSchema = z7.object({
2796
- type: z7.literal(stellarStateCallTypes.readDeliverySyncState),
2797
- privateAddress: z7.string().min(1),
2798
- asset: z7.string().min(1)
3342
+ var readDeliverySyncStateSchema = z5.object({
3343
+ type: z5.literal(stellarStateCallTypes.readDeliverySyncState),
3344
+ privateAddress: z5.string().min(1),
3345
+ asset: z5.string().min(1)
2799
3346
  }).transform(({ type, privateAddress, asset }) => ({
2800
3347
  type,
2801
3348
  operations: [
@@ -2806,8 +3353,8 @@ var readDeliverySyncStateSchema = z7.object({
2806
3353
  }
2807
3354
  ]
2808
3355
  }));
2809
- var setDeliverySyncStateSchema = z7.object({
2810
- type: z7.literal(stellarStateCallTypes.setDeliverySyncState),
3356
+ var setDeliverySyncStateSchema = z5.object({
3357
+ type: z5.literal(stellarStateCallTypes.setDeliverySyncState),
2811
3358
  syncState: deliverySyncStateSchema
2812
3359
  }).transform(({ type, syncState }) => ({
2813
3360
  type,
@@ -2846,10 +3393,10 @@ var stellarDeliveriesStateDefinitions = [
2846
3393
  ];
2847
3394
 
2848
3395
  // src/state/schemas/pool/merkle.ts
2849
- import { z as z8 } from "zod";
2850
- var readPoolMerkleStateSchema = z8.object({
2851
- type: z8.literal(stellarStateCallTypes.readPoolMerkleState),
2852
- poolContract: z8.string().min(1)
3396
+ import { z as z6 } from "zod";
3397
+ var readPoolMerkleStateSchema = z6.object({
3398
+ type: z6.literal(stellarStateCallTypes.readPoolMerkleState),
3399
+ poolContract: z6.string().min(1)
2853
3400
  }).transform(({ type, poolContract }) => ({
2854
3401
  type,
2855
3402
  operations: [
@@ -2860,8 +3407,8 @@ var readPoolMerkleStateSchema = z8.object({
2860
3407
  }
2861
3408
  ]
2862
3409
  }));
2863
- var setPoolMerkleStateSchema = z8.object({
2864
- type: z8.literal(stellarStateCallTypes.setPoolMerkleState),
3410
+ var setPoolMerkleStateSchema = z6.object({
3411
+ type: z6.literal(stellarStateCallTypes.setPoolMerkleState),
2865
3412
  state: poolMerkleStateSchema
2866
3413
  }).transform(({ type, state }) => ({
2867
3414
  type,
@@ -2874,10 +3421,10 @@ var setPoolMerkleStateSchema = z8.object({
2874
3421
  }
2875
3422
  ]
2876
3423
  }));
2877
- var readLeafEphemeralSchema = z8.object({
2878
- type: z8.literal(stellarStateCallTypes.readLeafEphemeral),
2879
- poolContract: z8.string().min(1),
2880
- leafIndex: z8.number().int().nonnegative()
3424
+ var readLeafEphemeralSchema = z6.object({
3425
+ type: z6.literal(stellarStateCallTypes.readLeafEphemeral),
3426
+ poolContract: z6.string().min(1),
3427
+ leafIndex: z6.number().int().nonnegative()
2881
3428
  }).transform(({ type, poolContract, leafIndex }) => ({
2882
3429
  type,
2883
3430
  operations: [
@@ -2888,8 +3435,8 @@ var readLeafEphemeralSchema = z8.object({
2888
3435
  }
2889
3436
  ]
2890
3437
  }));
2891
- var setLeafEphemeralSchema = z8.object({
2892
- type: z8.literal(stellarStateCallTypes.setLeafEphemeral),
3438
+ var setLeafEphemeralSchema = z6.object({
3439
+ type: z6.literal(stellarStateCallTypes.setLeafEphemeral),
2893
3440
  ephemeral: leafEphemeralSchema
2894
3441
  }).transform(({ type, ephemeral }) => ({
2895
3442
  type,
@@ -2928,9 +3475,9 @@ var stellarPoolStateDefinitions = [
2928
3475
  ];
2929
3476
 
2930
3477
  // src/state/schemas/records/private.ts
2931
- import { z as z9 } from "zod";
2932
- var listPrivateRecordsSchema = z9.object({
2933
- type: z9.literal(stellarStateCallTypes.listPrivateRecords)
3478
+ import { z as z7 } from "zod";
3479
+ var listPrivateRecordsSchema = z7.object({
3480
+ type: z7.literal(stellarStateCallTypes.listPrivateRecords)
2934
3481
  }).transform(({ type }) => ({
2935
3482
  type,
2936
3483
  operations: [
@@ -2940,9 +3487,9 @@ var listPrivateRecordsSchema = z9.object({
2940
3487
  }
2941
3488
  ]
2942
3489
  }));
2943
- var savePrivateRecordsSchema = z9.object({
2944
- type: z9.literal(stellarStateCallTypes.savePrivateRecords),
2945
- records: z9.array(privateRecordSchema)
3490
+ var savePrivateRecordsSchema = z7.object({
3491
+ type: z7.literal(stellarStateCallTypes.savePrivateRecords),
3492
+ records: z7.array(privateRecordSchema)
2946
3493
  }).transform(({ type, records }) => ({
2947
3494
  type,
2948
3495
  operations: [
@@ -2953,9 +3500,9 @@ var savePrivateRecordsSchema = z9.object({
2953
3500
  }
2954
3501
  ]
2955
3502
  }));
2956
- var replacePrivateRecordsSchema = z9.object({
2957
- type: z9.literal(stellarStateCallTypes.replacePrivateRecords),
2958
- records: z9.array(privateRecordSchema)
3503
+ var replacePrivateRecordsSchema = z7.object({
3504
+ type: z7.literal(stellarStateCallTypes.replacePrivateRecords),
3505
+ records: z7.array(privateRecordSchema)
2959
3506
  }).transform(({ type, records }) => ({
2960
3507
  type,
2961
3508
  operations: [
@@ -2970,18 +3517,18 @@ var replacePrivateRecordsSchema = z9.object({
2970
3517
  }
2971
3518
  ]
2972
3519
  }));
2973
- var pruneConsumedPrivateRecordsSchema = z9.object({
2974
- type: z9.literal(stellarStateCallTypes.pruneConsumedPrivateRecords)
3520
+ var pruneConsumedPrivateRecordsSchema = z7.object({
3521
+ type: z7.literal(stellarStateCallTypes.pruneConsumedPrivateRecords)
2975
3522
  }).transform(({ type }) => ({
2976
3523
  type,
2977
3524
  operations: [rejectConsumedPrivateRecords()]
2978
3525
  }));
2979
3526
 
2980
3527
  // src/state/schemas/records/transactions.ts
2981
- import { z as z10 } from "zod";
2982
- var upsertPrivateRecordsSchema = z10.object({
2983
- type: z10.literal(stellarStateCallTypes.upsertPrivateRecords),
2984
- records: z10.array(privateRecordSchema)
3528
+ import { z as z8 } from "zod";
3529
+ var upsertPrivateRecordsSchema = z8.object({
3530
+ type: z8.literal(stellarStateCallTypes.upsertPrivateRecords),
3531
+ records: z8.array(privateRecordSchema)
2985
3532
  }).transform(({ type, records }) => ({
2986
3533
  type,
2987
3534
  operations: [
@@ -2993,9 +3540,9 @@ var upsertPrivateRecordsSchema = z10.object({
2993
3540
  }
2994
3541
  ]
2995
3542
  }));
2996
- var readTransactionStatusSchema = z10.object({
2997
- type: z10.literal(stellarStateCallTypes.readTransactionStatus),
2998
- txHash: z10.string().min(1)
3543
+ var readTransactionStatusSchema = z8.object({
3544
+ type: z8.literal(stellarStateCallTypes.readTransactionStatus),
3545
+ txHash: z8.string().min(1)
2999
3546
  }).transform(({ type, txHash }) => ({
3000
3547
  type,
3001
3548
  operations: [
@@ -3006,8 +3553,8 @@ var readTransactionStatusSchema = z10.object({
3006
3553
  }
3007
3554
  ]
3008
3555
  }));
3009
- var setTransactionStatusSchema = z10.object({
3010
- type: z10.literal(stellarStateCallTypes.setTransactionStatus),
3556
+ var setTransactionStatusSchema = z8.object({
3557
+ type: z8.literal(stellarStateCallTypes.setTransactionStatus),
3011
3558
  status: transactionStatusSchema
3012
3559
  }).transform(({ type, status }) => ({
3013
3560
  type,
@@ -3020,9 +3567,9 @@ var setTransactionStatusSchema = z10.object({
3020
3567
  }
3021
3568
  ]
3022
3569
  }));
3023
- var clearTransactionStatusSchema = z10.object({
3024
- type: z10.literal(stellarStateCallTypes.clearTransactionStatus),
3025
- txHash: z10.string().min(1)
3570
+ var clearTransactionStatusSchema = z8.object({
3571
+ type: z8.literal(stellarStateCallTypes.clearTransactionStatus),
3572
+ txHash: z8.string().min(1)
3026
3573
  }).transform(({ type, txHash }) => ({
3027
3574
  type,
3028
3575
  operations: [
@@ -3064,10 +3611,10 @@ var stellarRecordsStateDefinitions = [
3064
3611
  ];
3065
3612
 
3066
3613
  // src/state/schemas/registry/lookup.ts
3067
- import { z as z11 } from "zod";
3068
- var readStellarAddressRegisteredSchema = z11.object({
3069
- type: z11.literal(stellarStateCallTypes.readStellarAddressRegistered),
3070
- address: z11.string().min(1)
3614
+ import { z as z9 } from "zod";
3615
+ var readStellarAddressRegisteredSchema = z9.object({
3616
+ type: z9.literal(stellarStateCallTypes.readStellarAddressRegistered),
3617
+ address: z9.string().min(1)
3071
3618
  }).transform(({ type, address }) => ({
3072
3619
  type,
3073
3620
  operations: [
@@ -3078,9 +3625,9 @@ var readStellarAddressRegisteredSchema = z11.object({
3078
3625
  }
3079
3626
  ]
3080
3627
  }));
3081
- var readCachedPrivateAddressSchema = z11.object({
3082
- type: z11.literal(stellarStateCallTypes.readCachedPrivateAddress),
3083
- address: z11.string().min(1)
3628
+ var readCachedPrivateAddressSchema = z9.object({
3629
+ type: z9.literal(stellarStateCallTypes.readCachedPrivateAddress),
3630
+ address: z9.string().min(1)
3084
3631
  }).transform(({ type, address }) => ({
3085
3632
  type,
3086
3633
  operations: [
@@ -3091,11 +3638,11 @@ var readCachedPrivateAddressSchema = z11.object({
3091
3638
  }
3092
3639
  ]
3093
3640
  }));
3094
- var saveRegisteredPrivateAddressSchema = z11.object({
3095
- type: z11.literal(stellarStateCallTypes.saveRegisteredPrivateAddress),
3096
- address: z11.string().min(1),
3097
- privateAddress: z11.string().min(1),
3098
- registered: z11.boolean()
3641
+ var saveRegisteredPrivateAddressSchema = z9.object({
3642
+ type: z9.literal(stellarStateCallTypes.saveRegisteredPrivateAddress),
3643
+ address: z9.string().min(1),
3644
+ privateAddress: z9.string().min(1),
3645
+ registered: z9.boolean()
3099
3646
  }).transform(({ type, address, privateAddress, registered: registered2 }) => {
3100
3647
  const lookup = registryLookupSchema.parse({
3101
3648
  owner: address,
@@ -3127,9 +3674,9 @@ var saveRegisteredPrivateAddressSchema = z11.object({
3127
3674
  ]
3128
3675
  };
3129
3676
  });
3130
- var invalidateRegisteredAddressSchema = z11.object({
3131
- type: z11.literal(stellarStateCallTypes.invalidateRegisteredAddress),
3132
- address: z11.string().min(1)
3677
+ var invalidateRegisteredAddressSchema = z9.object({
3678
+ type: z9.literal(stellarStateCallTypes.invalidateRegisteredAddress),
3679
+ address: z9.string().min(1)
3133
3680
  }).transform(({ type, address }) => ({
3134
3681
  type,
3135
3682
  operations: [
@@ -3150,9 +3697,9 @@ var invalidateRegisteredAddressSchema = z11.object({
3150
3697
  }
3151
3698
  ]
3152
3699
  }));
3153
- var readRegistryLookupSchema = z11.object({
3154
- type: z11.literal(stellarStateCallTypes.readRegistryLookup),
3155
- address: z11.string().min(1)
3700
+ var readRegistryLookupSchema = z9.object({
3701
+ type: z9.literal(stellarStateCallTypes.readRegistryLookup),
3702
+ address: z9.string().min(1)
3156
3703
  }).transform(({ type, address }) => ({
3157
3704
  type,
3158
3705
  operations: [
@@ -3163,8 +3710,8 @@ var readRegistryLookupSchema = z11.object({
3163
3710
  }
3164
3711
  ]
3165
3712
  }));
3166
- var saveRegistryLookupSchema = z11.object({
3167
- type: z11.literal(stellarStateCallTypes.saveRegistryLookup),
3713
+ var saveRegistryLookupSchema = z9.object({
3714
+ type: z9.literal(stellarStateCallTypes.saveRegistryLookup),
3168
3715
  lookup: registryLookupSchema
3169
3716
  }).transform(({ type, lookup }) => {
3170
3717
  const operations = [
@@ -3200,9 +3747,9 @@ var saveRegistryLookupSchema = z11.object({
3200
3747
  }
3201
3748
  return { type, operations };
3202
3749
  });
3203
- var invalidateRegistryLookupSchema = z11.object({
3204
- type: z11.literal(stellarStateCallTypes.invalidateRegistryLookup),
3205
- address: z11.string().min(1)
3750
+ var invalidateRegistryLookupSchema = z9.object({
3751
+ type: z9.literal(stellarStateCallTypes.invalidateRegistryLookup),
3752
+ address: z9.string().min(1)
3206
3753
  }).transform(({ type, address }) => ({
3207
3754
  type,
3208
3755
  operations: [
@@ -3283,9 +3830,9 @@ var stellarTransactionStateDefinitions = [
3283
3830
  ];
3284
3831
 
3285
3832
  // src/state/schemas/wallet/scalar.ts
3286
- import { z as z12 } from "zod";
3287
- var saveWalletPrivateAddressScalarSchema = z12.object({
3288
- type: z12.literal(stellarStateCallTypes.saveWalletPrivateAddressScalar),
3833
+ import { z as z10 } from "zod";
3834
+ var saveWalletPrivateAddressScalarSchema = z10.object({
3835
+ type: z10.literal(stellarStateCallTypes.saveWalletPrivateAddressScalar),
3289
3836
  scalar: walletPrivateAddressScalarSchema
3290
3837
  }).transform(({ type, scalar }) => ({
3291
3838
  type,
@@ -3298,10 +3845,10 @@ var saveWalletPrivateAddressScalarSchema = z12.object({
3298
3845
  }
3299
3846
  ]
3300
3847
  }));
3301
- var readWalletPrivateAddressScalarSchema = z12.object({
3302
- type: z12.literal(stellarStateCallTypes.readWalletPrivateAddressScalar),
3303
- owner: z12.string().min(1),
3304
- nonce: z12.string().min(1)
3848
+ var readWalletPrivateAddressScalarSchema = z10.object({
3849
+ type: z10.literal(stellarStateCallTypes.readWalletPrivateAddressScalar),
3850
+ owner: z10.string().min(1),
3851
+ nonce: z10.string().min(1)
3305
3852
  }).transform(({ type, owner, nonce }) => ({
3306
3853
  type,
3307
3854
  operations: [
@@ -3314,9 +3861,9 @@ var readWalletPrivateAddressScalarSchema = z12.object({
3314
3861
  }));
3315
3862
 
3316
3863
  // src/state/schemas/wallet/private-address.ts
3317
- import { z as z13 } from "zod";
3318
- var saveWalletPrivateAddressRecordSchema = z13.object({
3319
- type: z13.literal(stellarStateCallTypes.saveWalletPrivateAddressRecord),
3864
+ import { z as z11 } from "zod";
3865
+ var saveWalletPrivateAddressRecordSchema = z11.object({
3866
+ type: z11.literal(stellarStateCallTypes.saveWalletPrivateAddressRecord),
3320
3867
  record: walletPrivateAddressRecordSchema
3321
3868
  }).transform(({ type, record }) => ({
3322
3869
  type,
@@ -3329,10 +3876,10 @@ var saveWalletPrivateAddressRecordSchema = z13.object({
3329
3876
  }
3330
3877
  ]
3331
3878
  }));
3332
- var readWalletPrivateAddressRecordSchema = z13.object({
3333
- type: z13.literal(stellarStateCallTypes.readWalletPrivateAddressRecord),
3334
- owner: z13.string().min(1),
3335
- nonce: z13.string().min(1)
3879
+ var readWalletPrivateAddressRecordSchema = z11.object({
3880
+ type: z11.literal(stellarStateCallTypes.readWalletPrivateAddressRecord),
3881
+ owner: z11.string().min(1),
3882
+ nonce: z11.string().min(1)
3336
3883
  }).transform(({ type, owner, nonce }) => ({
3337
3884
  type,
3338
3885
  operations: [
@@ -3343,10 +3890,10 @@ var readWalletPrivateAddressRecordSchema = z13.object({
3343
3890
  }
3344
3891
  ]
3345
3892
  }));
3346
- var setWalletDefaultPrivateAddressNonceSchema = z13.object({
3347
- type: z13.literal(stellarStateCallTypes.setWalletDefaultPrivateAddressNonce),
3348
- owner: z13.string().min(1),
3349
- nonce: z13.string().min(1)
3893
+ var setWalletDefaultPrivateAddressNonceSchema = z11.object({
3894
+ type: z11.literal(stellarStateCallTypes.setWalletDefaultPrivateAddressNonce),
3895
+ owner: z11.string().min(1),
3896
+ nonce: z11.string().min(1)
3350
3897
  }).transform(({ type, owner, nonce }) => ({
3351
3898
  type,
3352
3899
  operations: [
@@ -3358,9 +3905,9 @@ var setWalletDefaultPrivateAddressNonceSchema = z13.object({
3358
3905
  }
3359
3906
  ]
3360
3907
  }));
3361
- var readWalletDefaultPrivateAddressNonceSchema = z13.object({
3362
- type: z13.literal(stellarStateCallTypes.readWalletDefaultPrivateAddressNonce),
3363
- owner: z13.string().min(1)
3908
+ var readWalletDefaultPrivateAddressNonceSchema = z11.object({
3909
+ type: z11.literal(stellarStateCallTypes.readWalletDefaultPrivateAddressNonce),
3910
+ owner: z11.string().min(1)
3364
3911
  }).transform(({ type, owner }) => ({
3365
3912
  type,
3366
3913
  operations: [
@@ -3371,10 +3918,10 @@ var readWalletDefaultPrivateAddressNonceSchema = z13.object({
3371
3918
  }
3372
3919
  ]
3373
3920
  }));
3374
- var deleteWalletPrivateAddressScalarSchema = z13.object({
3375
- type: z13.literal(stellarStateCallTypes.deleteWalletPrivateAddressScalar),
3376
- owner: z13.string().min(1),
3377
- nonce: z13.string().min(1)
3921
+ var deleteWalletPrivateAddressScalarSchema = z11.object({
3922
+ type: z11.literal(stellarStateCallTypes.deleteWalletPrivateAddressScalar),
3923
+ owner: z11.string().min(1),
3924
+ nonce: z11.string().min(1)
3378
3925
  }).transform(({ type, owner, nonce }) => ({
3379
3926
  type,
3380
3927
  operations: [
@@ -3428,7 +3975,6 @@ var stellarWalletStateDefinitions = [
3428
3975
  // src/state/definitions/index.ts
3429
3976
  registerStellarArrayFilterSchemas();
3430
3977
  var stellarStateDefinitions = [
3431
- ...stellarClaimsStateDefinitions,
3432
3978
  ...stellarRegistryStateDefinitions,
3433
3979
  ...stellarAssetsStateDefinitions,
3434
3980
  ...stellarBalancesStateDefinitions,
@@ -3552,112 +4098,10 @@ function createAssetsCatalogMethods(context) {
3552
4098
  }
3553
4099
 
3554
4100
  // src/state/service/assets/index.ts
3555
- function createAssetsService(context) {
3556
- return {
3557
- ...createAssetsCatalogMethods(context),
3558
- ...createPublicBalanceMethods(context)
3559
- };
3560
- }
3561
-
3562
- // src/state/service/claims/read-methods.ts
3563
- function createClaimsReadMethods(context) {
3564
- const { bridge } = context;
3565
- async function getPendingClaims(filter = {}) {
3566
- const value = await bridge.read({
3567
- type: stellarStateCallTypes.readPendingClaims
3568
- });
3569
- const state = normalizePendingClaimsState(value);
3570
- const items = state.items.filter((claim) => {
3571
- if (filter.owner !== void 0 && claim.owner !== filter.owner) {
3572
- return false;
3573
- }
3574
- if (filter.asset !== void 0 && claim.asset !== filter.asset) {
3575
- return false;
3576
- }
3577
- return true;
3578
- });
3579
- if (state.pagination !== void 0) {
3580
- return { items, pagination: state.pagination };
3581
- }
3582
- return { items };
3583
- }
3584
- return {
3585
- getPendingClaims,
3586
- async getPendingClaimsCount(owner) {
3587
- const value = await bridge.read({
3588
- type: stellarStateCallTypes.readPendingClaimsCount,
3589
- owner
3590
- });
3591
- const count = normalizePendingClaimsCount(value);
3592
- if (count !== void 0) {
3593
- return count;
3594
- }
3595
- const claims = await getPendingClaims({ owner });
3596
- return claims.items.length;
3597
- }
3598
- };
3599
- }
3600
-
3601
- // src/state/service/claims/write-methods.ts
3602
- function appendPendingClaims(bridge, claims, paginationInfo) {
3603
- return bridge.write({
3604
- type: stellarStateCallTypes.pendingClaims,
3605
- claims,
3606
- paginationInfo
3607
- });
3608
- }
3609
- function replacePendingClaimsPage(bridge, input) {
3610
- return bridge.write({
3611
- type: stellarStateCallTypes.replacePendingClaimsPage,
3612
- owner: input.owner,
3613
- claims: input.claims,
3614
- paginationInfo: input.paginationInfo,
3615
- ...input.count === void 0 ? {} : { count: input.count }
3616
- });
3617
- }
3618
- function upsertPendingClaims(bridge, claims) {
3619
- return bridge.write({
3620
- type: stellarStateCallTypes.upsertPendingClaims,
3621
- claims
3622
- });
3623
- }
3624
- function removePendingClaims(bridge, ids) {
3625
- return bridge.write({
3626
- type: stellarStateCallTypes.removePendingClaims,
3627
- ids
3628
- });
3629
- }
3630
- function clearPendingClaims(bridge, input = {}) {
3631
- return bridge.write({
3632
- type: stellarStateCallTypes.clearPendingClaims,
3633
- ...input.owner === void 0 ? {} : { owner: input.owner },
3634
- ...input.asset === void 0 ? {} : { asset: input.asset }
3635
- });
3636
- }
3637
- function setPendingClaimsCount(bridge, owner, count) {
3638
- return bridge.write({
3639
- type: stellarStateCallTypes.setPendingClaimsCount,
3640
- owner,
3641
- count
3642
- });
3643
- }
3644
- function createClaimsWriteMethods(context) {
3645
- const { bridge } = context;
3646
- return {
3647
- appendPendingClaims: (claims, paginationInfo) => appendPendingClaims(bridge, claims, paginationInfo),
3648
- replacePendingClaimsPage: (input) => replacePendingClaimsPage(bridge, input),
3649
- upsertPendingClaims: (claims) => upsertPendingClaims(bridge, claims),
3650
- removePendingClaims: (ids) => removePendingClaims(bridge, ids),
3651
- clearPendingClaims: (input = {}) => clearPendingClaims(bridge, input),
3652
- setPendingClaimsCount: (owner, count) => setPendingClaimsCount(bridge, owner, count)
3653
- };
3654
- }
3655
-
3656
- // src/state/service/claims/index.ts
3657
- function createClaimsService(context) {
4101
+ function createAssetsService(context) {
3658
4102
  return {
3659
- ...createClaimsWriteMethods(context),
3660
- ...createClaimsReadMethods(context)
4103
+ ...createAssetsCatalogMethods(context),
4104
+ ...createPublicBalanceMethods(context)
3661
4105
  };
3662
4106
  }
3663
4107
 
@@ -4186,7 +4630,6 @@ function composeStellarStateService(adapter) {
4186
4630
  ...createWalletAddressService(base),
4187
4631
  ...createPoolMerkleService(base),
4188
4632
  ...createPoolEphemeralService(base),
4189
- ...createClaimsService(base),
4190
4633
  ...createDeliveriesService(base),
4191
4634
  ...createRecordsService(base)
4192
4635
  };
@@ -4251,42 +4694,1030 @@ function attachPoolStatePorts(transactEnvironment, state) {
4251
4694
  resolveSenderPrivKeyScalarFromState: createSenderScalarStateResolver(state)
4252
4695
  };
4253
4696
  }
4697
+
4698
+ // src/transact/encoding/ephemeral-key.ts
4699
+ var HEX_64_RE = /^[\da-f]{64}$/iu;
4700
+ function normalizeCoordinate(value) {
4701
+ const hex = value.trim().replace(/^0x/iu, "").toLowerCase();
4702
+ if (!HEX_64_RE.test(hex)) {
4703
+ throw new Error("Ephemeral key coordinate must be a 32-byte hex string.");
4704
+ }
4705
+ return hex;
4706
+ }
4707
+ function serializeEphemeralKeyString(point) {
4708
+ return `${normalizeCoordinate(point.xHex)}:${normalizeCoordinate(point.yHex)}`;
4709
+ }
4710
+
4711
+ // src/transact/private-address/record-coin.ts
4712
+ function requireCoinNoteFromRecord(record) {
4713
+ if (!record.coinNote) {
4714
+ throw new Error(`Private record ${record.id} is missing coin note data.`);
4715
+ }
4716
+ return record.coinNote;
4717
+ }
4718
+ function findCommitmentLeafIndex(commitments, commitment) {
4719
+ return commitments.indexOf(commitment);
4720
+ }
4721
+
4722
+ // src/transact/engine/prepare/shared.ts
4723
+ async function resolveTokenContractId2(environment, assetId) {
4724
+ if (environment.resolveTokenContractId) {
4725
+ return environment.resolveTokenContractId(assetId);
4726
+ }
4727
+ throw new Error(`Token contract is not configured for asset ${assetId}.`);
4728
+ }
4729
+ async function resolveSenderPrivKeyScalarHex(environment, privateAddressStpl1, owner) {
4730
+ const cached = await readSenderPrivKeyScalarHex(
4731
+ environment,
4732
+ privateAddressStpl1,
4733
+ owner
4734
+ );
4735
+ if (cached) {
4736
+ return cached;
4737
+ }
4738
+ if (environment.ensureSenderPrivKeyScalarHex) {
4739
+ return environment.ensureSenderPrivKeyScalarHex(privateAddressStpl1);
4740
+ }
4741
+ if (!environment.resolveSenderPrivKeyScalarHex) {
4742
+ throw new Error("Sender private key scalar resolver is not configured.");
4743
+ }
4744
+ return environment.resolveSenderPrivKeyScalarHex(privateAddressStpl1);
4745
+ }
4746
+ async function readSenderPrivKeyScalarHex(environment, privateAddressStpl1, owner) {
4747
+ if (owner && environment.resolveSenderPrivKeyScalarFromState) {
4748
+ const fromState = await environment.resolveSenderPrivKeyScalarFromState({
4749
+ owner,
4750
+ privateAddressStpl1
4751
+ });
4752
+ if (fromState?.trim()) {
4753
+ return fromState.trim();
4754
+ }
4755
+ }
4756
+ if (environment.readSenderPrivKeyScalarHex) {
4757
+ const cached = await environment.readSenderPrivKeyScalarHex(privateAddressStpl1);
4758
+ if (cached?.trim()) {
4759
+ return cached.trim();
4760
+ }
4761
+ }
4762
+ return void 0;
4763
+ }
4764
+ async function ensureSenderPrivKeyScalarHex(environment, privateAddressStpl1, owner) {
4765
+ const cached = await readSenderPrivKeyScalarHex(
4766
+ environment,
4767
+ privateAddressStpl1,
4768
+ owner
4769
+ );
4770
+ if (cached) {
4771
+ return cached;
4772
+ }
4773
+ if (environment.ensureSenderPrivKeyScalarHex) {
4774
+ return environment.ensureSenderPrivKeyScalarHex(privateAddressStpl1);
4775
+ }
4776
+ return resolveSenderPrivKeyScalarHex(environment, privateAddressStpl1, owner);
4777
+ }
4778
+ async function loadMerkleState(environment, walletPublicKey) {
4779
+ const merged = await fetchAndMergeMerkleState({
4780
+ poolContractId: environment.network.poolContract,
4781
+ walletPublicKey,
4782
+ transactEnvironment: environment,
4783
+ ...environment.poolMerkleState ? { poolMerkleState: environment.poolMerkleState } : {}
4784
+ });
4785
+ return { commitments: merged.commitments };
4786
+ }
4787
+
4788
+ // src/transact/escrow/require-escrow-spend-scalar.ts
4789
+ function isEscrowSweepSpend(artifacts) {
4790
+ return artifacts?.spendSource === "escrow" && artifacts.escrowSend !== true;
4791
+ }
4792
+ function requireEscrowSpendScalarHex(artifacts) {
4793
+ if (!isEscrowSweepSpend(artifacts)) {
4794
+ throw new Error("Escrow sweep requires spendSource escrow.");
4795
+ }
4796
+ const hex = artifacts?.escrowSpendScalarHex?.trim();
4797
+ if (!hex) {
4798
+ throw new Error("Escrow sweep requires the reconstructed note owner scalar.");
4799
+ }
4800
+ return hex;
4801
+ }
4802
+ function nullifierCheckSpendScalarHex(artifacts) {
4803
+ if (!isEscrowSweepSpend(artifacts)) {
4804
+ return void 0;
4805
+ }
4806
+ return requireEscrowSpendScalarHex(artifacts);
4807
+ }
4808
+
4809
+ // src/transact/transfer-source/resolve.ts
4810
+ function readTransferFromPrivateAddress(from) {
4811
+ return from.trim();
4812
+ }
4813
+
4814
+ // src/transact/transfer-source/verify-private-records.ts
4815
+ import { executionError, insufficientStateError as insufficientStateError2 } from "@arcanetech/privacy-sdk-core";
4816
+
4817
+ // src/contracts/pool/pool-domain-service.ts
4818
+ import { Buffer as Buffer14 } from "buffer";
4819
+ function hexToBuffer(hex) {
4820
+ const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
4821
+ return Buffer14.from(clean, "hex");
4822
+ }
4823
+ async function readNullifierConsumedOnChain(input) {
4824
+ const client = input.contractContext.createPoolClient({
4825
+ contractId: input.poolContractId,
4826
+ walletPublicKey: input.walletPublicKey,
4827
+ networkPassphrase: input.contractContext.network.networkPassphrase,
4828
+ sorobanRpcUrl: input.contractContext.network.rpcUrl
4829
+ });
4830
+ const read = await client.is_nulifier_hash_consumed({
4831
+ hash: hexToBuffer(input.nullifierHashHex)
4832
+ });
4833
+ return read.result;
4834
+ }
4835
+
4836
+ // src/transact/transfer-source/verify-private-records.ts
4837
+ async function resolveNullifierSpendScalarHex(input) {
4838
+ const stamped = input.spendScalarHex?.trim();
4839
+ if (stamped) {
4840
+ return stamped;
4841
+ }
4842
+ const privateAddress = input.record.privateAddress?.trim();
4843
+ if (!privateAddress) {
4844
+ throw executionError(
4845
+ "Private record is missing a private address; cannot derive the owner-bound spend scalar.",
4846
+ "validation",
4847
+ {
4848
+ reason: "private_record_missing_private_address",
4849
+ recordId: input.record.id
4850
+ }
4851
+ );
4852
+ }
4853
+ return ensureSenderPrivKeyScalarHex(
4854
+ input.environment,
4855
+ privateAddress,
4856
+ input.walletPublicKey
4857
+ );
4858
+ }
4859
+ async function readPrivateRecordNullifierSpendStatus(input) {
4860
+ const coin = requireCoinNoteFromRecord(input.record);
4861
+ const scalarHex = await resolveNullifierSpendScalarHex(input);
4862
+ const nullifierHashHex = await getPrivacyPoolService().calculateNullifierHash(
4863
+ coin.nullifier,
4864
+ privKeyScalarDecimalFromRecipientScalarHex(scalarHex)
4865
+ );
4866
+ const contractContext = requireContractContext(input.environment);
4867
+ const poolContractId = input.poolContractId?.trim() || contractContext.network.poolContract;
4868
+ const spent = await readNullifierConsumedOnChain({
4869
+ contractContext,
4870
+ poolContractId,
4871
+ walletPublicKey: input.walletPublicKey.trim(),
4872
+ nullifierHashHex
4873
+ });
4874
+ return { spent, nullifierHashHex };
4875
+ }
4876
+ async function verifyPrivateRecordsNullifiersBeforeExecute(input) {
4877
+ for (const record of input.records) {
4878
+ const status = await readPrivateRecordNullifierSpendStatus({
4879
+ record,
4880
+ environment: input.environment,
4881
+ walletPublicKey: input.walletPublicKey,
4882
+ ...input.poolContractId ? { poolContractId: input.poolContractId } : {},
4883
+ ...input.spendScalarHex ? { spendScalarHex: input.spendScalarHex } : {}
4884
+ });
4885
+ if (status.spent) {
4886
+ throw executionError(
4887
+ "Private input note nullifier was already spent on-chain.",
4888
+ "validation",
4889
+ {
4890
+ reason: "private_record_nullifier_spent",
4891
+ recordId: record.id,
4892
+ nullifierHashHex: status.nullifierHashHex
4893
+ }
4894
+ );
4895
+ }
4896
+ }
4897
+ }
4898
+
4899
+ // src/transact/engine/spend-proof-context.ts
4900
+ async function resolveSenderPrivKeyScalarHex2(input) {
4901
+ if (isEscrowSweepSpend(input.prepared.transactArtifacts)) {
4902
+ return requireEscrowSpendScalarHex(input.prepared.transactArtifacts);
4903
+ }
4904
+ if (input.prepared.kind !== "transfer" && input.prepared.kind !== "withdraw") {
4905
+ throw new Error("Spend execution requires a transfer or withdraw intent.");
4906
+ }
4907
+ return ensureSenderPrivKeyScalarHex(
4908
+ input.environment,
4909
+ readTransferFromPrivateAddress(input.prepared.intent.from),
4910
+ input.walletPublicKey
4911
+ );
4912
+ }
4913
+ async function buildSpendProofContextAtExecute(input) {
4914
+ const [primaryRecord] = input.prepared.consumedRecords;
4915
+ if (!primaryRecord) {
4916
+ throw new Error("Spend execution requires at least one private record.");
4917
+ }
4918
+ const walletPublicKey = primaryRecord.owner.trim();
4919
+ if (!walletPublicKey) {
4920
+ throw new Error("Spend execution record owner is missing.");
4921
+ }
4922
+ const senderPrivKeyScalarHex = await resolveSenderPrivKeyScalarHex2({
4923
+ prepared: input.prepared,
4924
+ environment: input.environment,
4925
+ walletPublicKey
4926
+ });
4927
+ const tokenAddress = await resolveTokenContractId2(
4928
+ input.environment,
4929
+ input.prepared.intent.asset
4930
+ );
4931
+ const coin = requireCoinNoteFromRecord(primaryRecord);
4932
+ const { commitments } = await loadMerkleState(input.environment, walletPublicKey);
4933
+ const leafIndex = findCommitmentLeafIndex(commitments, coin.commitment);
4934
+ if (leafIndex < 0) {
4935
+ throw new Error("Coin commitment not found in on-chain Merkle state.");
4936
+ }
4937
+ const ephemeral = await readLeafEphemeralHex({
4938
+ poolContractId: input.environment.network.poolContract,
4939
+ walletPublicKey,
4940
+ leafIndex,
4941
+ transactEnvironment: input.environment,
4942
+ ...input.environment.leafEphemeral ? { leafEphemeral: input.environment.leafEphemeral } : {}
4943
+ });
4944
+ return {
4945
+ walletPublicKey,
4946
+ tokenAddress,
4947
+ coin,
4948
+ commitments,
4949
+ ephemeral,
4950
+ senderPrivKeyScalarHex,
4951
+ recipientPrivateAddressStpl1: input.recipientPrivateAddressStpl1
4952
+ };
4953
+ }
4954
+ async function readCoinEphemeralForRecord(input) {
4955
+ const coin = requireCoinNoteFromRecord(input.record);
4956
+ const leafIndex = findCommitmentLeafIndex(input.commitments, coin.commitment);
4957
+ if (leafIndex < 0) {
4958
+ throw new Error("Coin commitment not found in on-chain Merkle state.");
4959
+ }
4960
+ const ephemeral = await readLeafEphemeralHex({
4961
+ poolContractId: input.environment.network.poolContract,
4962
+ walletPublicKey: input.walletPublicKey,
4963
+ leafIndex,
4964
+ transactEnvironment: input.environment,
4965
+ ...input.environment.leafEphemeral ? { leafEphemeral: input.environment.leafEphemeral } : {}
4966
+ });
4967
+ return { coin, ephemeral };
4968
+ }
4969
+
4970
+ // src/transact/engine/prepare/transfer-helpers.ts
4971
+ import { StrKey as StrKey8 } from "@stellar/stellar-sdk";
4972
+ function isStellarAccountRecipient(prepared) {
4973
+ return prepared.kind === "transfer" && StrKey8.isValidEd25519PublicKey(prepared.intent.to.trim());
4974
+ }
4975
+ async function resolveTransferRecipientForExecute(prepared, environment, walletPublicKey) {
4976
+ if (!isStellarAccountRecipient(prepared)) {
4977
+ return {
4978
+ recipientPrivateAddressStpl1: prepared.intent.to.trim()
4979
+ };
4980
+ }
4981
+ if (!environment.resolveTransferRecipientAtExecute) {
4982
+ throw new Error("Transfer recipient resolver is not configured.");
4983
+ }
4984
+ return environment.resolveTransferRecipientAtExecute({
4985
+ recipientStellarAddress: prepared.intent.to.trim(),
4986
+ walletPublicKey
4987
+ });
4988
+ }
4989
+
4990
+ // src/transact/engine/transfer-proof-at-execute.ts
4991
+ function readChangeRecipient(input, changeStroops) {
4992
+ if (changeStroops <= 0n || input.prepared.kind !== "transfer") {
4993
+ return void 0;
4994
+ }
4995
+ const from = input.prepared.intent.from;
4996
+ return readTransferFromPrivateAddress(from);
4997
+ }
4998
+ function proofEscrowFields(input) {
4999
+ return {
5000
+ ...input.escrowSend ? { escrowSend: input.escrowSend } : {},
5001
+ ...input.escrowClaimantLimbs ? { escrowClaimantLimbs: input.escrowClaimantLimbs } : {}
5002
+ };
5003
+ }
5004
+ async function buildSingleTransferProofAtExecute(input) {
5005
+ const context = await buildSpendProofContextAtExecute(input);
5006
+ const changeStroops = BigInt(context.coin.value) - input.prepared.intent.amount;
5007
+ const proof = await prepareConfidentialTransferProof({
5008
+ coin: context.coin,
5009
+ state: { commitments: context.commitments },
5010
+ senderPrivKeyScalarHex: context.senderPrivKeyScalarHex,
5011
+ depositorEphemeralKey: serializeEphemeralKeyString({
5012
+ xHex: context.ephemeral.xHex,
5013
+ yHex: context.ephemeral.yHex
5014
+ }),
5015
+ transferStroops: input.prepared.intent.amount,
5016
+ recipientPrivateAddressStpl1: context.recipientPrivateAddressStpl1,
5017
+ selfPrivateAddressStpl1ForChange: readChangeRecipient(input, changeStroops),
5018
+ tokenAddress: context.tokenAddress,
5019
+ ...proofEscrowFields(input)
5020
+ });
5021
+ return { context, proof };
5022
+ }
5023
+ async function buildDualTransferProofAtExecute(input) {
5024
+ const [primaryRecord, secondaryRecord] = input.prepared.consumedRecords;
5025
+ if (!primaryRecord || !secondaryRecord) {
5026
+ throw new Error("Dual transfer execution requires two private input records.");
5027
+ }
5028
+ const context = await buildSpendProofContextAtExecute(input);
5029
+ const secondary = await readCoinEphemeralForRecord({
5030
+ record: secondaryRecord,
5031
+ environment: input.environment,
5032
+ walletPublicKey: context.walletPublicKey,
5033
+ commitments: context.commitments
5034
+ });
5035
+ const totalNotes = BigInt(context.coin.value) + BigInt(secondary.coin.value);
5036
+ const changeStroops = totalNotes - input.prepared.intent.amount;
5037
+ const proof = await prepareConfidentialTransferProofDual({
5038
+ coinA: context.coin,
5039
+ coinB: secondary.coin,
5040
+ state: { commitments: context.commitments },
5041
+ senderPrivKeyScalarHex: context.senderPrivKeyScalarHex,
5042
+ ephemeralAKey: serializeEphemeralKeyString({
5043
+ xHex: context.ephemeral.xHex,
5044
+ yHex: context.ephemeral.yHex
5045
+ }),
5046
+ ephemeralBKey: serializeEphemeralKeyString({
5047
+ xHex: secondary.ephemeral.xHex,
5048
+ yHex: secondary.ephemeral.yHex
5049
+ }),
5050
+ transferStroops: input.prepared.intent.amount,
5051
+ recipientPrivateAddressStpl1: context.recipientPrivateAddressStpl1,
5052
+ selfPrivateAddressStpl1ForChange: readChangeRecipient(input, changeStroops),
5053
+ tokenAddress: context.tokenAddress,
5054
+ ...proofEscrowFields(input)
5055
+ });
5056
+ return { context, proof };
5057
+ }
5058
+ async function buildTransferProofAtExecute(input) {
5059
+ const recordCount = input.prepared.consumedRecords.length;
5060
+ if (recordCount === 1) {
5061
+ return buildSingleTransferProofAtExecute(input);
5062
+ }
5063
+ if (recordCount === 2) {
5064
+ return buildDualTransferProofAtExecute(input);
5065
+ }
5066
+ throw new Error("Confidential transfer execution supports at most two input notes.");
5067
+ }
5068
+
5069
+ // src/transact/engine/transfer-finalize.ts
5070
+ function stampEscrowOutputRecords(input) {
5071
+ if (input.escrowSendPrivateAddress) {
5072
+ const [recipientRecord, ...rest] = input.prepared.outputRecords;
5073
+ if (recipientRecord) {
5074
+ input.prepared.outputRecords = [
5075
+ {
5076
+ ...recipientRecord,
5077
+ privateAddress: input.escrowSendPrivateAddress
5078
+ },
5079
+ ...rest
5080
+ ];
5081
+ }
5082
+ }
5083
+ seedEscrowSweepOutputsFromProof({
5084
+ prepared: input.prepared,
5085
+ proof: input.proof,
5086
+ walletPublicKey: input.walletPublicKey
5087
+ });
5088
+ enrichTransferOutputRecords(input.prepared, input.proof);
5089
+ }
5090
+ function seedEscrowSweepOutputsFromProof(input) {
5091
+ if (input.prepared.transactArtifacts?.spendSource !== "escrow" || input.prepared.outputRecords.length > 0) {
5092
+ return;
5093
+ }
5094
+ input.prepared.outputRecords = [
5095
+ {
5096
+ id: input.proof.recipientCoin.commitment_hex,
5097
+ owner: input.walletPublicKey,
5098
+ privateAddress: input.prepared.intent.to,
5099
+ asset: input.prepared.intent.asset,
5100
+ amount: input.prepared.intent.amount,
5101
+ consumed: false
5102
+ }
5103
+ ];
5104
+ }
5105
+ function enrichTransferOutputRecords(prepared, proof) {
5106
+ if (prepared.outputRecords.length === 0) {
5107
+ return;
5108
+ }
5109
+ const generatedOutputCoins = [
5110
+ proof.recipientCoin,
5111
+ ...proof.changeCoin ? [proof.changeCoin] : []
5112
+ ];
5113
+ prepared.outputRecords = prepared.outputRecords.map((record, index) => {
5114
+ const generatedCoin = generatedOutputCoins.at(index);
5115
+ if (!generatedCoin) {
5116
+ return record;
5117
+ }
5118
+ return {
5119
+ ...record,
5120
+ id: generatedCoin.commitment_hex,
5121
+ commitmentHex: generatedCoin.commitment_hex,
5122
+ coinNote: generatedCoin.coin,
5123
+ depositScalarHex: generatedCoin.depositScalarHex,
5124
+ precommitementHex: generatedCoin.precommitementHex
5125
+ };
5126
+ });
5127
+ }
5128
+ function escrowSpendArtifacts(input) {
5129
+ if (input.escrowSend) {
5130
+ return {
5131
+ escrowSend: true,
5132
+ spendSource: "escrow",
5133
+ ...input.escrowRecipient ? { escrowRecipient: input.escrowRecipient } : {}
5134
+ };
5135
+ }
5136
+ if (input.preparedSpendSource === "escrow") {
5137
+ return {
5138
+ spendSource: "escrow",
5139
+ ...input.escrowRecipient ? { escrowRecipient: input.escrowRecipient } : {},
5140
+ ...input.escrowSpendScalarHex ? { escrowSpendScalarHex: input.escrowSpendScalarHex } : {},
5141
+ ...input.escrowClaimantLimbs ? { escrowClaimantLimbs: input.escrowClaimantLimbs } : {}
5142
+ };
5143
+ }
5144
+ return {};
5145
+ }
5146
+ function buildTransferFinalizeArtifacts(input) {
5147
+ return {
5148
+ proofHex: input.proof.proof_hex,
5149
+ publicHex: input.proof.public_hex,
5150
+ ...ciphertextArtifactsFromProof(input.proof),
5151
+ applicationIdsPlaintext: input.proof.applicationIdsPlaintext,
5152
+ tokenAddress: input.context.tokenAddress,
5153
+ walletPublicKey: input.context.walletPublicKey,
5154
+ executeFinalizeRequired: false,
5155
+ ...escrowSpendArtifacts(input)
5156
+ };
5157
+ }
5158
+ async function runTransferFinalizeSteps(input) {
5159
+ const recipient = await resolveTransferRecipientForExecute(
5160
+ input.prepared,
5161
+ input.environment,
5162
+ input.walletPublicKey
5163
+ );
5164
+ const spendScalarHex = nullifierCheckSpendScalarHex(input.prepared.transactArtifacts);
5165
+ await verifyPrivateRecordsNullifiersBeforeExecute({
5166
+ records: input.prepared.consumedRecords,
5167
+ environment: input.environment,
5168
+ walletPublicKey: input.walletPublicKey,
5169
+ ...spendScalarHex ? { spendScalarHex } : {}
5170
+ });
5171
+ const { context, proof } = await buildTransferProofAtExecute({
5172
+ prepared: input.prepared,
5173
+ environment: input.environment,
5174
+ recipientPrivateAddressStpl1: recipient.recipientPrivateAddressStpl1,
5175
+ ...recipient.escrowSend ? { escrowSend: recipient.escrowSend } : {},
5176
+ ...input.prepared.transactArtifacts?.escrowClaimantLimbs ? {
5177
+ escrowClaimantLimbs: input.prepared.transactArtifacts.escrowClaimantLimbs
5178
+ } : {}
5179
+ });
5180
+ stampEscrowOutputRecords({
5181
+ prepared: input.prepared,
5182
+ proof,
5183
+ walletPublicKey: input.walletPublicKey,
5184
+ ...recipient.escrowSend ? { escrowSendPrivateAddress: recipient.recipientPrivateAddressStpl1 } : {}
5185
+ });
5186
+ return buildTransferFinalizeArtifacts({
5187
+ proof,
5188
+ context,
5189
+ ...sweepFinalizeStamp(input.prepared, recipient)
5190
+ });
5191
+ }
5192
+ function sweepArtifactStamp(artifacts) {
5193
+ return {
5194
+ ...artifacts?.escrowSpendScalarHex ? { escrowSpendScalarHex: artifacts.escrowSpendScalarHex } : {},
5195
+ ...artifacts?.spendSource ? { preparedSpendSource: artifacts.spendSource } : {},
5196
+ ...artifacts?.escrowClaimantLimbs ? { escrowClaimantLimbs: artifacts.escrowClaimantLimbs } : {}
5197
+ };
5198
+ }
5199
+ function sweepFinalizeStamp(prepared, recipient) {
5200
+ const artifacts = prepared.transactArtifacts;
5201
+ const fromSend = recipient.escrowSend?.recipientStellarAddress?.trim();
5202
+ const escrowRecipient = fromSend || artifacts?.escrowRecipient?.trim();
5203
+ return {
5204
+ ...recipient.escrowSend ? { escrowSend: true } : {},
5205
+ ...escrowRecipient ? { escrowRecipient } : {},
5206
+ ...sweepArtifactStamp(artifacts)
5207
+ };
5208
+ }
5209
+ async function finalizeTransferAtExecute(prepared, environment) {
5210
+ const [primaryRecord] = prepared.consumedRecords;
5211
+ if (!primaryRecord?.owner.trim()) {
5212
+ throw new Error("Transfer execution record owner is missing.");
5213
+ }
5214
+ const walletPublicKey = primaryRecord.owner.trim();
5215
+ return runTransferFinalizeSteps({ prepared, environment, walletPublicKey });
5216
+ }
5217
+
5218
+ // src/transact/engine/execute.ts
5219
+ function enrichWithdrawOutputRecords(prepared, proof) {
5220
+ if (!proof.changeCoin || prepared.outputRecords.length === 0) {
5221
+ return;
5222
+ }
5223
+ const changeCoin = proof.changeCoin;
5224
+ prepared.outputRecords = prepared.outputRecords.map((record) => ({
5225
+ ...record,
5226
+ id: changeCoin.commitment_hex,
5227
+ commitmentHex: changeCoin.commitment_hex,
5228
+ coinNote: changeCoin.coin,
5229
+ depositScalarHex: changeCoin.depositScalarHex,
5230
+ precommitementHex: changeCoin.precommitementHex
5231
+ }));
5232
+ }
5233
+ function buildWithdrawFinalizeArtifacts(proof, context) {
5234
+ return {
5235
+ proofHex: proof.proof_hex,
5236
+ publicHex: proof.public_hex,
5237
+ ...ciphertextArtifactsFromProof(proof),
5238
+ applicationIdsPlaintext: proof.applicationIdsPlaintext,
5239
+ tokenAddress: context.tokenAddress,
5240
+ walletPublicKey: context.walletPublicKey,
5241
+ executeFinalizeRequired: false
5242
+ };
5243
+ }
5244
+ async function finalizeSingleWithdrawAtExecute(prepared, environment, poolService, withdrawFrom) {
5245
+ const context = await buildSpendProofContextAtExecute({
5246
+ prepared,
5247
+ environment,
5248
+ recipientPrivateAddressStpl1: withdrawFrom
5249
+ });
5250
+ const changeStroops = BigInt(context.coin.value) - prepared.intent.amount;
5251
+ const proof = await poolService.prepareWithdrawTransactProof({
5252
+ coin: context.coin,
5253
+ state: { commitments: context.commitments },
5254
+ destinationStellarAddress: prepared.intent.to,
5255
+ privKeyScalarHex: context.senderPrivKeyScalarHex,
5256
+ depositorEphemeralKey: serializeEphemeralKeyString({
5257
+ xHex: context.ephemeral.xHex,
5258
+ yHex: context.ephemeral.yHex
5259
+ }),
5260
+ withdrawAmountStroops: prepared.intent.amount,
5261
+ changePrivateAddressStpl1: changeStroops > 0n ? withdrawFrom : void 0,
5262
+ tokenAddress: context.tokenAddress
5263
+ });
5264
+ enrichWithdrawOutputRecords(prepared, proof);
5265
+ return buildWithdrawFinalizeArtifacts(proof, context);
5266
+ }
5267
+ async function finalizeDualWithdrawAtExecute(prepared, environment, poolService, withdrawFrom) {
5268
+ const [, secondaryRecord] = prepared.consumedRecords;
5269
+ if (!secondaryRecord) {
5270
+ throw new Error("Dual withdraw execution requires two private input records.");
5271
+ }
5272
+ const context = await buildSpendProofContextAtExecute({
5273
+ prepared,
5274
+ environment,
5275
+ recipientPrivateAddressStpl1: withdrawFrom
5276
+ });
5277
+ const secondary = await readCoinEphemeralForRecord({
5278
+ record: secondaryRecord,
5279
+ environment,
5280
+ walletPublicKey: context.walletPublicKey,
5281
+ commitments: context.commitments
5282
+ });
5283
+ const totalNotes = BigInt(context.coin.value) + BigInt(secondary.coin.value);
5284
+ const changeStroops = totalNotes - prepared.intent.amount;
5285
+ const proof = await poolService.prepareWithdrawTransactProofDual({
5286
+ coinA: context.coin,
5287
+ coinB: secondary.coin,
5288
+ state: { commitments: context.commitments },
5289
+ destinationStellarAddress: prepared.intent.to,
5290
+ privKeyScalarHex: context.senderPrivKeyScalarHex,
5291
+ depositorEphemeralAKey: serializeEphemeralKeyString({
5292
+ xHex: context.ephemeral.xHex,
5293
+ yHex: context.ephemeral.yHex
5294
+ }),
5295
+ depositorEphemeralBKey: serializeEphemeralKeyString({
5296
+ xHex: secondary.ephemeral.xHex,
5297
+ yHex: secondary.ephemeral.yHex
5298
+ }),
5299
+ withdrawAmountStroops: prepared.intent.amount,
5300
+ changePrivateAddressStpl1: changeStroops > 0n ? withdrawFrom : void 0,
5301
+ tokenAddress: context.tokenAddress
5302
+ });
5303
+ enrichWithdrawOutputRecords(prepared, proof);
5304
+ return buildWithdrawFinalizeArtifacts(proof, context);
5305
+ }
5306
+ async function finalizeWithdrawAtExecute(prepared, environment, poolService) {
5307
+ if (prepared.kind !== "withdraw") {
5308
+ throw new Error("Withdraw finalize requires a withdraw operation.");
5309
+ }
5310
+ const withdrawIntent = prepared.intent;
5311
+ const withdrawFrom = withdrawIntent.from;
5312
+ const recordCount = prepared.consumedRecords.length;
5313
+ if (recordCount === 1) {
5314
+ return finalizeSingleWithdrawAtExecute(
5315
+ prepared,
5316
+ environment,
5317
+ poolService,
5318
+ withdrawFrom
5319
+ );
5320
+ }
5321
+ if (recordCount === 2) {
5322
+ return finalizeDualWithdrawAtExecute(
5323
+ prepared,
5324
+ environment,
5325
+ poolService,
5326
+ withdrawFrom
5327
+ );
5328
+ }
5329
+ throw new Error("Confidential withdraw execution supports at most two input notes.");
5330
+ }
5331
+ async function finalizeSpendOperationAtExecute(prepared, environment, poolService) {
5332
+ if (prepared.kind !== "transfer" && prepared.kind !== "withdraw") {
5333
+ return prepared;
5334
+ }
5335
+ if (prepared.transactArtifacts?.proofHex) {
5336
+ return prepared;
5337
+ }
5338
+ const artifacts = prepared.kind === "transfer" ? await finalizeTransferAtExecute(prepared, environment) : await finalizeWithdrawAtExecute(prepared, environment, poolService);
5339
+ return {
5340
+ ...prepared,
5341
+ transactArtifacts: {
5342
+ ...prepared.transactArtifacts,
5343
+ ...artifacts
5344
+ }
5345
+ };
5346
+ }
5347
+
5348
+ // src/transact/relay/constants.ts
5349
+ var RELAY_TRANSACT_PACKAGE_VERSION_V1 = 1;
5350
+ var RELAY_TRANSACT_SUPPORTED_SIGNAL_COUNT = 93;
5351
+ var RELAY_TRANSACT_FIELD_BYTES = 32;
5352
+ var RELAY_TRANSACT_SIGNAL_PREFIX_BYTES = 4;
5353
+ var RELAY_SIGNAL_INDEX_NULLIFIER_0 = 0;
5354
+ var RELAY_SIGNAL_INDEX_NULLIFIER_1 = 1;
5355
+ var RELAY_SIGNAL_INDEX_STATE_ROOT = 82;
5356
+ var RELAY_SIGNAL_INDEX_WITHDRAW_ADDRESS_HI = 83;
5357
+ var RELAY_SIGNAL_INDEX_WITHDRAW_ADDRESS_LO = 84;
5358
+ var RELAY_SIGNAL_INDEX_ESCROW_RECIPIENT_HI = 85;
5359
+ var RELAY_SIGNAL_INDEX_ESCROW_RECIPIENT_LO = 86;
5360
+ var RELAY_SIGNAL_INDEX_PUBLIC_WITHDRAWAL_ASSET_HI = 87;
5361
+ var RELAY_SIGNAL_INDEX_PUBLIC_WITHDRAWAL_ASSET_LO = 88;
5362
+ var RELAY_SIGNAL_INDEX_PUBLIC_DEPOSIT_ASSET_HI = 89;
5363
+ var RELAY_SIGNAL_INDEX_PUBLIC_DEPOSIT_ASSET_LO = 90;
5364
+ var RELAY_SIGNAL_INDEX_PUBLIC_DEPOSIT = 91;
5365
+ var RELAY_SIGNAL_INDEX_PUBLIC_WITHDRAWAL = 92;
5366
+
5367
+ // src/transact/relay/signals.ts
5368
+ import { Buffer as Buffer15 } from "buffer";
5369
+
5370
+ // src/transact/relay/layout-profile.ts
5371
+ var FIELD_BYTES = 32;
5372
+ var PREFIX_BYTES = 4;
5373
+ var LEGACY_PUBLIC_INPUT_PREFIX_LEN = 5;
5374
+ var V2_PUBLIC_INPUT_PREFIX_LEN = 7;
5375
+ var EPHEMERAL_COORDINATE_COUNT = 2;
5376
+ var STANDARD_SHAPE = {
5377
+ nIns: 2,
5378
+ nOuts: 2,
5379
+ publicNInputs: 1,
5380
+ publicNOutputs: 1,
5381
+ nAuditSlots: 4,
5382
+ noteAuditLen: 12,
5383
+ noteOutputLen: 6
5384
+ };
5385
+ var SIX_BY_SIX_SHAPE = {
5386
+ nIns: 6,
5387
+ nOuts: 6,
5388
+ publicNInputs: 1,
5389
+ publicNOutputs: 1,
5390
+ nAuditSlots: 12,
5391
+ noteAuditLen: 12,
5392
+ noteOutputLen: 6
5393
+ };
5394
+ function profileFromShape(nonce, shape, publicInputPrefixLength, ciphertextsInPublicSignals) {
5395
+ const auditOffset = shape.nIns + shape.nOuts + shape.nOuts * EPHEMERAL_COORDINATE_COUNT;
5396
+ const outputNoteOffset = ciphertextsInPublicSignals ? auditOffset + shape.nAuditSlots * EPHEMERAL_COORDINATE_COUNT + shape.nAuditSlots * shape.noteAuditLen + shape.nAuditSlots : auditOffset + EPHEMERAL_COORDINATE_COUNT + shape.nAuditSlots;
5397
+ const publicOutputsLength = ciphertextsInPublicSignals ? outputNoteOffset + shape.nOuts * shape.noteOutputLen + shape.nOuts : outputNoteOffset + shape.nOuts;
5398
+ const signalCount = publicOutputsLength + publicInputPrefixLength + EPHEMERAL_COORDINATE_COUNT * shape.publicNInputs + EPHEMERAL_COORDINATE_COUNT * shape.publicNOutputs + shape.publicNInputs + shape.publicNOutputs;
5399
+ const stateRoot = publicOutputsLength;
5400
+ return {
5401
+ nonce,
5402
+ signalCount,
5403
+ fieldBytes: FIELD_BYTES,
5404
+ prefixBytes: PREFIX_BYTES,
5405
+ indices: {
5406
+ nullifier0: 0,
5407
+ nullifier1: 1,
5408
+ stateRoot,
5409
+ withdrawAddressHi: stateRoot + 1,
5410
+ withdrawAddressLo: stateRoot + 2,
5411
+ escrowRecipientHi: stateRoot + 3,
5412
+ escrowRecipientLo: stateRoot + 4,
5413
+ publicWithdrawalAssetHi: stateRoot + publicInputPrefixLength,
5414
+ publicWithdrawalAssetLo: stateRoot + publicInputPrefixLength + 1,
5415
+ publicDepositAssetHi: stateRoot + publicInputPrefixLength + 2,
5416
+ publicDepositAssetLo: stateRoot + publicInputPrefixLength + 3,
5417
+ publicDeposit: stateRoot + publicInputPrefixLength + 4,
5418
+ publicWithdrawal: stateRoot + publicInputPrefixLength + 5
5419
+ }
5420
+ };
5421
+ }
5422
+ function relayLayoutProfileForNonce(nonce) {
5423
+ if (nonce === STANDARD_ZK_CONFIG_NONCE) {
5424
+ return profileFromShape(
5425
+ nonce,
5426
+ STANDARD_SHAPE,
5427
+ LEGACY_PUBLIC_INPUT_PREFIX_LEN,
5428
+ true
5429
+ );
5430
+ }
5431
+ if (nonce === COMMITMENT_V2_ZK_NONCE) {
5432
+ return profileFromShape(nonce, STANDARD_SHAPE, V2_PUBLIC_INPUT_PREFIX_LEN, true);
5433
+ }
5434
+ if (nonce === BINDING_ZK_NONCE) {
5435
+ return profileFromShape(nonce, STANDARD_SHAPE, V2_PUBLIC_INPUT_PREFIX_LEN, false);
5436
+ }
5437
+ if (nonce === SIX_BY_SIX_ZK_NONCE) {
5438
+ return profileFromShape(nonce, SIX_BY_SIX_SHAPE, V2_PUBLIC_INPUT_PREFIX_LEN, true);
5439
+ }
5440
+ if (nonce === SIX_BY_SIX_BINDING_ZK_NONCE) {
5441
+ return profileFromShape(nonce, SIX_BY_SIX_SHAPE, V2_PUBLIC_INPUT_PREFIX_LEN, false);
5442
+ }
5443
+ throw new Error(`Unknown ZK config nonce ${nonce.toString()}`);
5444
+ }
5445
+
5446
+ // src/transact/relay/signals.ts
5447
+ function decodePublicSignalBytes(publicSignals) {
5448
+ return Buffer15.from(publicSignals.replace(/^0x/iu, ""), "hex");
5449
+ }
5450
+ function hasSupportedLengthPrefix(bytes, signalCount) {
5451
+ const expected = RELAY_TRANSACT_SIGNAL_PREFIX_BYTES + signalCount * RELAY_TRANSACT_FIELD_BYTES;
5452
+ if (bytes.length !== expected) {
5453
+ return false;
5454
+ }
5455
+ return bytes.readUInt32BE(0) === signalCount;
5456
+ }
5457
+ function assertSupportedPublicSignals(publicSignals, zkConfigNonce = DEFAULT_ZK_CONFIG_NONCE) {
5458
+ const profile = relayLayoutProfileForNonce(zkConfigNonce);
5459
+ const bytes = decodePublicSignalBytes(publicSignals);
5460
+ const supportedBytes = profile.signalCount * RELAY_TRANSACT_FIELD_BYTES;
5461
+ if (bytes.length === supportedBytes || hasSupportedLengthPrefix(bytes, profile.signalCount)) {
5462
+ return;
5463
+ }
5464
+ throw new Error(
5465
+ `Relay Transact Package V1 requires exactly ${String(profile.signalCount)} packed public signals.`
5466
+ );
5467
+ }
5468
+ function sliceSupportedPublicSignalFields(publicSignals, zkConfigNonce = DEFAULT_ZK_CONFIG_NONCE) {
5469
+ assertSupportedPublicSignals(publicSignals, zkConfigNonce);
5470
+ const profile = relayLayoutProfileForNonce(zkConfigNonce);
5471
+ const bytes = decodePublicSignalBytes(publicSignals);
5472
+ const body = hasSupportedLengthPrefix(bytes, profile.signalCount) ? bytes.subarray(RELAY_TRANSACT_SIGNAL_PREFIX_BYTES) : bytes;
5473
+ return Array.from(
5474
+ { length: profile.signalCount },
5475
+ (_unused, index) => Buffer15.from(
5476
+ body.subarray(
5477
+ index * RELAY_TRANSACT_FIELD_BYTES,
5478
+ (index + 1) * RELAY_TRANSACT_FIELD_BYTES
5479
+ )
5480
+ )
5481
+ );
5482
+ }
5483
+
5484
+ // src/transact/relay/prepare.ts
5485
+ function normalizeHex(value) {
5486
+ return value.replace(/^0x/iu, "").toLowerCase();
5487
+ }
5488
+ function prepareRelayTransactPackage(input) {
5489
+ const zkConfigNonce = input.zkConfigNonce ?? DEFAULT_ZK_CONFIG_NONCE;
5490
+ assertSupportedPublicSignals(input.publicSignals, zkConfigNonce);
5491
+ const prepared = {
5492
+ version: RELAY_TRANSACT_PACKAGE_VERSION_V1,
5493
+ poolSelector: input.poolSelector,
5494
+ zkConfigNonce,
5495
+ proofBytes: normalizeHex(input.proofBytes),
5496
+ publicSignals: normalizeHex(input.publicSignals),
5497
+ applicationIdHints: input.applicationIdHints
5498
+ };
5499
+ if (input.ciphertextBytes) {
5500
+ prepared.ciphertextBytes = normalizeHex(input.ciphertextBytes);
5501
+ }
5502
+ if (input.outputNoteEphemeralScalars) {
5503
+ prepared.outputNoteEphemeralScalars = [...input.outputNoteEphemeralScalars];
5504
+ }
5505
+ if (input.escrowAuthorization) {
5506
+ prepared.escrowAuthorization = input.escrowAuthorization;
5507
+ }
5508
+ if (input.keyVersionHints) {
5509
+ prepared.keyVersionHints = input.keyVersionHints;
5510
+ }
5511
+ return prepared;
5512
+ }
5513
+
5514
+ // src/transact/relay/from-prepared.ts
5515
+ function requirePreparedArtifacts(prepared) {
5516
+ const artifacts = prepared.transactArtifacts;
5517
+ if (!artifacts?.proofHex || !artifacts.publicHex || !artifacts.applicationIdsPlaintext) {
5518
+ throw new Error("Prepared operation is missing transact artifacts.");
5519
+ }
5520
+ return {
5521
+ proofBytes: artifacts.proofHex,
5522
+ publicSignals: artifacts.publicHex,
5523
+ applicationIdHints: artifacts.applicationIdsPlaintext,
5524
+ ...artifacts.ciphertextHex ? { ciphertextBytes: artifacts.ciphertextHex } : {},
5525
+ ...artifacts.outputNoteEphemeralScalars ? { outputNoteEphemeralScalars: artifacts.outputNoteEphemeralScalars } : {},
5526
+ ...artifacts.escrowAuthorization ? { escrowAuthorization: artifacts.escrowAuthorization } : {}
5527
+ };
5528
+ }
5529
+ function prepareRelayTransactPackageFromPrepared(input) {
5530
+ return prepareRelayTransactPackage({
5531
+ poolSelector: input.poolSelector,
5532
+ ...requirePreparedArtifacts(input.prepared),
5533
+ ...input.zkConfigNonce === void 0 ? {} : { zkConfigNonce: input.zkConfigNonce },
5534
+ ...input.keyVersionHints ? { keyVersionHints: input.keyVersionHints } : {}
5535
+ });
5536
+ }
5537
+
5538
+ // src/transact/relay/profile.ts
5539
+ function fieldAt(fields, index) {
5540
+ const field = fields.find((_unused, offset) => offset === index);
5541
+ if (!field) {
5542
+ throw new Error(`Missing packed public signal at index ${String(index)}.`);
5543
+ }
5544
+ return field;
5545
+ }
5546
+ function fieldHex2(fields, index) {
5547
+ return fieldAt(fields, index).toString("hex");
5548
+ }
5549
+ function fieldAmount(fields, index) {
5550
+ return BigInt(`0x${fieldAt(fields, index).toString("hex")}`).toString();
5551
+ }
5552
+ function readRelayTransactSupportedProfile(prepared) {
5553
+ const layout = relayLayoutProfileForNonce(prepared.zkConfigNonce);
5554
+ const fields = sliceSupportedPublicSignalFields(
5555
+ prepared.publicSignals,
5556
+ prepared.zkConfigNonce
5557
+ );
5558
+ const { indices } = layout;
5559
+ return {
5560
+ orderedNullifiers: [
5561
+ fieldHex2(fields, indices.nullifier0),
5562
+ fieldHex2(fields, indices.nullifier1)
5563
+ ],
5564
+ publicLegContext: {
5565
+ stateRoot: fieldHex2(fields, indices.stateRoot),
5566
+ withdrawAddressHi: fieldHex2(fields, indices.withdrawAddressHi),
5567
+ withdrawAddressLo: fieldHex2(fields, indices.withdrawAddressLo),
5568
+ escrowRecipientHi: fieldHex2(fields, indices.escrowRecipientHi),
5569
+ escrowRecipientLo: fieldHex2(fields, indices.escrowRecipientLo),
5570
+ publicWithdrawalAssetHi: fieldHex2(fields, indices.publicWithdrawalAssetHi),
5571
+ publicWithdrawalAssetLo: fieldHex2(fields, indices.publicWithdrawalAssetLo),
5572
+ publicDepositAssetHi: fieldHex2(fields, indices.publicDepositAssetHi),
5573
+ publicDepositAssetLo: fieldHex2(fields, indices.publicDepositAssetLo),
5574
+ publicDepositAmount: fieldAmount(fields, indices.publicDeposit),
5575
+ publicWithdrawalAmount: fieldAmount(fields, indices.publicWithdrawal)
5576
+ }
5577
+ };
5578
+ }
5579
+
5580
+ // src/transact/relay/required-submission-method.ts
5581
+ var ZERO_PUBLIC_DEPOSIT = 0n;
5582
+ var SUBMISSION_METHOD = {
5583
+ direct: "direct",
5584
+ relay: "relay"
5585
+ };
5586
+ var ESCROW_SUBMISSION_REFUSAL = {
5587
+ positivePublicDeposit: "escrow_positive_public_deposit"
5588
+ };
5589
+ var EscrowSubmissionRefusedError = class extends Error {
5590
+ reason;
5591
+ constructor(reason) {
5592
+ super(reason);
5593
+ this.name = "EscrowSubmissionRefusedError";
5594
+ this.reason = reason;
5595
+ }
5596
+ };
5597
+ function isEscrowPreparedOperation(prepared) {
5598
+ return prepared.transactArtifacts?.escrowSend === true || prepared.transactArtifacts?.spendSource === "escrow";
5599
+ }
5600
+ function publicDepositAmountFromPrepared(prepared, zkConfigNonce) {
5601
+ const publicHex = prepared.transactArtifacts?.publicHex;
5602
+ if (!publicHex) {
5603
+ return void 0;
5604
+ }
5605
+ const layout = relayLayoutProfileForNonce(zkConfigNonce);
5606
+ const fields = sliceSupportedPublicSignalFields(publicHex, zkConfigNonce);
5607
+ const field = fields.find(
5608
+ (_unused, offset) => offset === layout.indices.publicDeposit
5609
+ );
5610
+ if (!field) {
5611
+ throw new Error(
5612
+ `Missing packed public signal at index ${String(layout.indices.publicDeposit)}.`
5613
+ );
5614
+ }
5615
+ return BigInt(`0x${field.toString("hex")}`);
5616
+ }
5617
+ function evaluateRequiredSubmissionMethod(prepared, zkConfigNonce = DEFAULT_ZK_CONFIG_NONCE) {
5618
+ const publicDepositAmount = publicDepositAmountFromPrepared(prepared, zkConfigNonce);
5619
+ if (isEscrowPreparedOperation(prepared)) {
5620
+ if (publicDepositAmount !== void 0 && publicDepositAmount > ZERO_PUBLIC_DEPOSIT) {
5621
+ return { refused: ESCROW_SUBMISSION_REFUSAL.positivePublicDeposit };
5622
+ }
5623
+ if (prepared.transactArtifacts?.escrowSend === true) {
5624
+ return { method: SUBMISSION_METHOD.relay };
5625
+ }
5626
+ return { method: SUBMISSION_METHOD.direct };
5627
+ }
5628
+ if (publicDepositAmount === void 0) {
5629
+ throw new Error("Prepared operation is missing transact artifacts.");
5630
+ }
5631
+ return {
5632
+ method: publicDepositAmount > ZERO_PUBLIC_DEPOSIT ? SUBMISSION_METHOD.direct : SUBMISSION_METHOD.relay
5633
+ };
5634
+ }
5635
+ function requiredSubmissionMethod(prepared, zkConfigNonce = DEFAULT_ZK_CONFIG_NONCE) {
5636
+ const result = evaluateRequiredSubmissionMethod(prepared, zkConfigNonce);
5637
+ if ("refused" in result) {
5638
+ throw new EscrowSubmissionRefusedError(result.refused);
5639
+ }
5640
+ return result.method;
5641
+ }
4254
5642
  export {
5643
+ BundledZkCircuit2 as BundledZkCircuit,
5644
+ COMMITMENT_V2_ZK_NONCE,
4255
5645
  DEFAULT_STEALTH_SIGN_NONCE as DEFAULT_PRIVATE_ADDRESS_SIGN_NONCE,
5646
+ DEFAULT_STELLAR_ZK_CIRCUITS,
5647
+ DEFAULT_ZK_CONFIG_NONCE,
5648
+ ESCROW_SUBMISSION_REFUSAL,
5649
+ EscrowSubmissionRefusedError,
4256
5650
  KytInspectError,
4257
5651
  MIN_CONFIDENTIAL_TRANSFER_STROOPS,
5652
+ OWNER_BOUND_NOTE_SCHEMA_VERSION,
4258
5653
  PrivacyPoolService,
5654
+ RELAY_SIGNAL_INDEX_ESCROW_RECIPIENT_HI,
5655
+ RELAY_SIGNAL_INDEX_ESCROW_RECIPIENT_LO,
5656
+ RELAY_SIGNAL_INDEX_NULLIFIER_0,
5657
+ RELAY_SIGNAL_INDEX_NULLIFIER_1,
5658
+ RELAY_SIGNAL_INDEX_PUBLIC_DEPOSIT,
5659
+ RELAY_SIGNAL_INDEX_PUBLIC_DEPOSIT_ASSET_HI,
5660
+ RELAY_SIGNAL_INDEX_PUBLIC_DEPOSIT_ASSET_LO,
5661
+ RELAY_SIGNAL_INDEX_PUBLIC_WITHDRAWAL,
5662
+ RELAY_SIGNAL_INDEX_PUBLIC_WITHDRAWAL_ASSET_HI,
5663
+ RELAY_SIGNAL_INDEX_PUBLIC_WITHDRAWAL_ASSET_LO,
5664
+ RELAY_SIGNAL_INDEX_STATE_ROOT,
5665
+ RELAY_SIGNAL_INDEX_WITHDRAW_ADDRESS_HI,
5666
+ RELAY_SIGNAL_INDEX_WITHDRAW_ADDRESS_LO,
5667
+ RELAY_TRANSACT_FIELD_BYTES,
5668
+ RELAY_TRANSACT_PACKAGE_VERSION_V1,
5669
+ RELAY_TRANSACT_SIGNAL_PREFIX_BYTES,
5670
+ RELAY_TRANSACT_SUPPORTED_SIGNAL_COUNT,
5671
+ SIX_BY_SIX_ZK_NONCE,
5672
+ STANDARD_ZK_CONFIG_NONCE,
5673
+ SUBMISSION_METHOD,
4259
5674
  ZERO_STROOPS,
5675
+ assertEscrowSweepClaimant,
4260
5676
  assetLegToTokenAddress,
5677
+ attachEscrowAuthorization,
4261
5678
  attachPoolStatePorts,
4262
- buildOnboardingPayload,
5679
+ buildBlindedRecipientTagChallengeMessage,
4263
5680
  buildPoolTransactionAuditParameters,
4264
5681
  buildPrivateAddressSignMessage,
4265
- buildTransferOnboardingAtExecute,
4266
5682
  configurePrivacyPoolService,
4267
5683
  createPrivacyPoolService,
4268
5684
  decodePrivateAddress,
5685
+ deriveEscrowRecipientFromStellarAddress,
4269
5686
  encodePrivateAddress,
4270
5687
  encodePrivateAddressFromHexCoordinates,
5688
+ evaluateRequiredSubmissionMethod,
4271
5689
  fetchAndMergeMerkleState,
5690
+ fetchEscrowOutputNoteEvents,
5691
+ finalizeSpendOperationAtExecute,
4272
5692
  frDecimalToPaddedBytes32,
4273
5693
  generateRandomDepositScalarHex,
4274
5694
  generateTemporaryRecipientPrivateAddress,
4275
5695
  getPrivacyPoolService,
5696
+ isEscrowPreparedOperation,
4276
5697
  loadDefaultStellarBrowserAssets,
4277
5698
  loadStellarBrowserAssets,
5699
+ optionalZkArtifactBaseUrl,
4278
5700
  parseAuditPublicKeyFromEnvHex,
4279
5701
  parseKytReasonCode,
4280
5702
  prepareConfidentialTransferProof,
4281
5703
  prepareConfidentialTransferProofDual,
5704
+ prepareEscrowSweepOperation,
5705
+ prepareRelayTransactPackage,
5706
+ prepareRelayTransactPackageFromPrepared,
4282
5707
  privateAddressSdk,
4283
5708
  readLeafEphemeralHex,
5709
+ readRelayTransactSupportedProfile,
4284
5710
  recipientPublicKeysDecimalFromPrivateAddress,
5711
+ reconstructEscrowNote,
4285
5712
  requestKytPassageForPoolInteraction,
5713
+ requiredSubmissionMethod,
4286
5714
  resolvePoolApplicationId,
5715
+ resolveZkConfigNonce,
4287
5716
  runTtlPreflight,
5717
+ spendScalarHexFromStellarSignature,
4288
5718
  submitSorobanConfidentialTransfer,
4289
5719
  submitSorobanDeposit,
4290
- tokenAddressToAssetLeg
5720
+ tokenAddressToAssetLeg,
5721
+ unsignedEscrowAuthorizationForSweep
4291
5722
  };
4292
5723
  //# sourceMappingURL=index.js.map