@atumlabs/payment-gateway-client 2.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -89,7 +89,7 @@ var require_tron_address = __commonJS({
89
89
  hexAddress = base58ToHex2(address);
90
90
  }
91
91
  hexAddress = hexAddress.replace(/^0x/, "");
92
- if (hexAddress.startsWith(TVM_MAINNET_PREFIX)) {
92
+ if (hexAddress.length === 42 && hexAddress.startsWith(TVM_MAINNET_PREFIX)) {
93
93
  hexAddress = hexAddress.substring(2);
94
94
  }
95
95
  if (hexAddress.length !== 40) {
@@ -103,14 +103,62 @@ var require_tron_address = __commonJS({
103
103
  }
104
104
  });
105
105
 
106
+ // ../contracts/tvm/escrow-encoding/typescript/dist/witness-values.js
107
+ var require_witness_values = __commonJS({
108
+ "../contracts/tvm/escrow-encoding/typescript/dist/witness-values.js"(exports2) {
109
+ "use strict";
110
+ Object.defineProperty(exports2, "__esModule", { value: true });
111
+ exports2.normalizeBytes32 = normalizeBytes32;
112
+ exports2.normalizeUint256 = normalizeUint256;
113
+ exports2.maskedChainIdToHex = maskedChainIdToHex;
114
+ var ethers_1 = require("ethers");
115
+ var chain_id_1 = require_chain_id();
116
+ function normalizeBytes32(label, value) {
117
+ let bytes;
118
+ try {
119
+ bytes = (0, ethers_1.getBytes)(value);
120
+ } catch {
121
+ throw new Error(`${label} must be 0x-prefixed hex (32 bytes), got ${JSON.stringify(value)}`);
122
+ }
123
+ if (bytes.length !== 32) {
124
+ throw new Error(`${label} must be exactly 32 bytes, got ${bytes.length}`);
125
+ }
126
+ return (0, ethers_1.hexlify)(bytes);
127
+ }
128
+ function normalizeUint256(label, value) {
129
+ let n;
130
+ try {
131
+ n = BigInt(value);
132
+ } catch {
133
+ throw new Error(`${label} must be an integer (bigint or decimal string), got ${JSON.stringify(value)}`);
134
+ }
135
+ if (n < 0n) {
136
+ throw new Error(`${label} must be non-negative (uint256), got ${n.toString()}`);
137
+ }
138
+ return n.toString();
139
+ }
140
+ function maskedChainIdToHex(chainId) {
141
+ if (!Number.isSafeInteger(chainId) || chainId < 0) {
142
+ throw new Error(`chainId must be a non-negative safe integer, got ${chainId}`);
143
+ }
144
+ return `0x${(0, chain_id_1.maskChainId)(chainId).toString(16)}`;
145
+ }
146
+ }
147
+ });
148
+
106
149
  // ../contracts/tvm/escrow-encoding/typescript/dist/reserve-encoder.js
107
150
  var require_reserve_encoder = __commonJS({
108
151
  "../contracts/tvm/escrow-encoding/typescript/dist/reserve-encoder.js"(exports2) {
109
152
  "use strict";
110
153
  Object.defineProperty(exports2, "__esModule", { value: true });
154
+ exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE = void 0;
111
155
  exports2.computeReserveDigest = computeReserveDigest;
156
+ exports2.buildTvmReserveTypedDataWithQuoteSource = buildTvmReserveTypedDataWithQuoteSource;
157
+ exports2.computeTvmReserveDigestWithQuoteSource = computeTvmReserveDigestWithQuoteSource;
112
158
  var ethers_1 = require("ethers");
113
159
  var chain_id_1 = require_chain_id();
160
+ var tron_address_1 = require_tron_address();
161
+ var witness_values_1 = require_witness_values();
114
162
  var RESERVE_WITNESS_TYPES = {
115
163
  ReserveWitness: [
116
164
  { name: "paymentId", type: "bytes32" },
@@ -129,6 +177,36 @@ var require_reserve_encoder = __commonJS({
129
177
  settler: input.settler
130
178
  });
131
179
  }
180
+ exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE = {
181
+ ReserveWitness: [
182
+ { name: "depositId", type: "bytes32" },
183
+ { name: "quoteHash", type: "bytes32" },
184
+ { name: "settler", type: "address" },
185
+ { name: "sourceAmount", type: "uint256" }
186
+ ]
187
+ };
188
+ function buildTvmReserveTypedDataWithQuoteSource(input) {
189
+ return {
190
+ types: exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE,
191
+ primaryType: "ReserveWitness",
192
+ domain: {
193
+ name: "Escrow",
194
+ version: "3",
195
+ chainId: (0, witness_values_1.maskedChainIdToHex)(input.chainId),
196
+ verifyingContract: (0, tron_address_1.normalizeAddress)(input.escrowContract)
197
+ },
198
+ message: {
199
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", input.depositId),
200
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", input.quoteHash),
201
+ settler: (0, tron_address_1.normalizeAddress)(input.settler),
202
+ sourceAmount: (0, witness_values_1.normalizeUint256)("sourceAmount", input.sourceAmount)
203
+ }
204
+ };
205
+ }
206
+ function computeTvmReserveDigestWithQuoteSource(input) {
207
+ const prehash = buildTvmReserveTypedDataWithQuoteSource(input);
208
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
209
+ }
132
210
  }
133
211
  });
134
212
 
@@ -155,11 +233,14 @@ var require_deposit_encoder = __commonJS({
155
233
  "../contracts/tvm/escrow-encoding/typescript/dist/deposit-encoder.js"(exports2) {
156
234
  "use strict";
157
235
  Object.defineProperty(exports2, "__esModule", { value: true });
236
+ exports2.MAX_DESTINATION_BYTES = exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION = void 0;
158
237
  exports2.createTvmPermitWitnessTransferFromPrehash = createTvmPermitWitnessTransferFromPrehash2;
159
238
  exports2.hashTvmPermitWitnessTransferFrom = hashTvmPermitWitnessTransferFrom2;
239
+ exports2.createTvmPermitWitnessTransferFromPrehashWithDestination = createTvmPermitWitnessTransferFromPrehashWithDestination;
160
240
  var ethers_1 = require("ethers");
161
241
  var chain_id_1 = require_chain_id();
162
242
  var tron_address_1 = require_tron_address();
243
+ var witness_values_1 = require_witness_values();
163
244
  var PERMIT_WITNESS_TYPES_V2 = {
164
245
  PermitWitnessTransferFrom: [
165
246
  { name: "permitted", type: "TokenPermissions" },
@@ -205,6 +286,180 @@ var require_deposit_encoder = __commonJS({
205
286
  function hashTvmPermitWitnessTransferFrom2(prehash) {
206
287
  return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
207
288
  }
289
+ exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION = {
290
+ PermitWitnessTransferFrom: [
291
+ { name: "permitted", type: "TokenPermissions" },
292
+ { name: "spender", type: "address" },
293
+ { name: "nonce", type: "uint256" },
294
+ { name: "deadline", type: "uint256" },
295
+ { name: "witness", type: "DepositWitness" }
296
+ ],
297
+ TokenPermissions: [
298
+ { name: "token", type: "address" },
299
+ { name: "amount", type: "uint256" }
300
+ ],
301
+ DepositWitness: [
302
+ { name: "depositRequestHash", type: "bytes32" },
303
+ { name: "destination", type: "string" },
304
+ { name: "reserver", type: "address" },
305
+ { name: "releaser", type: "address" }
306
+ ]
307
+ };
308
+ exports2.MAX_DESTINATION_BYTES = 256;
309
+ function assertDestinationWithinBounds(destination) {
310
+ if (destination === "") {
311
+ throw new Error('destination is empty: the escrow reverts DestinationCannotBeEmpty, and because keccak256("") is a valid bytes32 this would otherwise sign a commitment to no destination at all');
312
+ }
313
+ const byteLength = (0, ethers_1.toUtf8Bytes)(destination).length;
314
+ if (byteLength > exports2.MAX_DESTINATION_BYTES) {
315
+ throw new Error(`destination is ${byteLength} bytes, over the escrow's MAX_DESTINATION_BYTES of ${exports2.MAX_DESTINATION_BYTES}: the contract reverts DestinationTooLong, so this digest could never be redeemed`);
316
+ }
317
+ }
318
+ function createTvmPermitWitnessTransferFromPrehashWithDestination(params) {
319
+ assertDestinationWithinBounds(params.destination);
320
+ return {
321
+ types: exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION,
322
+ primaryType: "PermitWitnessTransferFrom",
323
+ domain: {
324
+ name: "Permit2",
325
+ chainId: (0, witness_values_1.maskedChainIdToHex)(params.chainId),
326
+ verifyingContract: (0, tron_address_1.normalizeAddress)(params.permit2Address)
327
+ },
328
+ message: {
329
+ permitted: {
330
+ token: (0, tron_address_1.normalizeAddress)(params.tokenAddress),
331
+ amount: (0, witness_values_1.normalizeUint256)("amount", params.amount)
332
+ },
333
+ spender: (0, tron_address_1.normalizeAddress)(params.spenderAddress),
334
+ nonce: (0, witness_values_1.normalizeUint256)("nonce", params.nonce),
335
+ deadline: (0, witness_values_1.normalizeUint256)("deadline", params.deadline),
336
+ witness: {
337
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", params.depositRequestHash),
338
+ destination: params.destination,
339
+ reserver: (0, tron_address_1.normalizeAddress)(params.reserverAddress),
340
+ releaser: (0, tron_address_1.normalizeAddress)(params.releaserAddress)
341
+ }
342
+ }
343
+ };
344
+ }
345
+ }
346
+ });
347
+
348
+ // ../contracts/tvm/escrow-encoding/typescript/dist/release-encoder.js
349
+ var require_release_encoder = __commonJS({
350
+ "../contracts/tvm/escrow-encoding/typescript/dist/release-encoder.js"(exports2) {
351
+ "use strict";
352
+ Object.defineProperty(exports2, "__esModule", { value: true });
353
+ exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH = void 0;
354
+ exports2.buildTvmReleaseTypedDataWithQuoteHash = buildTvmReleaseTypedDataWithQuoteHash;
355
+ exports2.computeTvmReleaseDigestWithQuoteHash = computeTvmReleaseDigestWithQuoteHash;
356
+ var ethers_1 = require("ethers");
357
+ var tron_address_1 = require_tron_address();
358
+ var witness_values_1 = require_witness_values();
359
+ exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH = {
360
+ ReleaseWitness: [
361
+ { name: "depositId", type: "bytes32" },
362
+ { name: "quoteHash", type: "bytes32" },
363
+ { name: "depositRequestHash", type: "bytes32" },
364
+ { name: "destinationHash", type: "bytes32" },
365
+ { name: "depositor", type: "address" },
366
+ { name: "token", type: "address" },
367
+ { name: "amount", type: "uint256" },
368
+ { name: "feeAmount", type: "uint256" },
369
+ { name: "reserver", type: "address" },
370
+ { name: "releaser", type: "address" },
371
+ { name: "settler", type: "address" }
372
+ ]
373
+ };
374
+ function buildTvmReleaseTypedDataWithQuoteHash(input) {
375
+ const w = input.witness;
376
+ return {
377
+ types: exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH,
378
+ primaryType: "ReleaseWitness",
379
+ domain: {
380
+ name: "Escrow",
381
+ version: "3",
382
+ chainId: (0, witness_values_1.maskedChainIdToHex)(input.chainId),
383
+ verifyingContract: (0, tron_address_1.normalizeAddress)(input.escrowContract)
384
+ },
385
+ message: {
386
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", w.depositId),
387
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", w.quoteHash),
388
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", w.depositRequestHash),
389
+ destinationHash: (0, witness_values_1.normalizeBytes32)("destinationHash", w.destinationHash),
390
+ depositor: (0, tron_address_1.normalizeAddress)(w.depositor),
391
+ token: (0, tron_address_1.normalizeAddress)(w.token),
392
+ amount: (0, witness_values_1.normalizeUint256)("amount", w.amount),
393
+ feeAmount: (0, witness_values_1.normalizeUint256)("feeAmount", w.feeAmount),
394
+ reserver: (0, tron_address_1.normalizeAddress)(w.reserver),
395
+ releaser: (0, tron_address_1.normalizeAddress)(w.releaser),
396
+ settler: (0, tron_address_1.normalizeAddress)(w.settler)
397
+ }
398
+ };
399
+ }
400
+ function computeTvmReleaseDigestWithQuoteHash(input) {
401
+ const prehash = buildTvmReleaseTypedDataWithQuoteHash(input);
402
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
403
+ }
404
+ }
405
+ });
406
+
407
+ // ../contracts/tvm/escrow-encoding/typescript/dist/refund-encoder.js
408
+ var require_refund_encoder = __commonJS({
409
+ "../contracts/tvm/escrow-encoding/typescript/dist/refund-encoder.js"(exports2) {
410
+ "use strict";
411
+ Object.defineProperty(exports2, "__esModule", { value: true });
412
+ exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH = void 0;
413
+ exports2.buildTvmRefundTypedDataWithQuoteHash = buildTvmRefundTypedDataWithQuoteHash;
414
+ exports2.computeTvmRefundDigestWithQuoteHash = computeTvmRefundDigestWithQuoteHash;
415
+ var ethers_1 = require("ethers");
416
+ var tron_address_1 = require_tron_address();
417
+ var witness_values_1 = require_witness_values();
418
+ exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH = {
419
+ RefundWitness: [
420
+ { name: "depositId", type: "bytes32" },
421
+ { name: "quoteHash", type: "bytes32" },
422
+ { name: "depositRequestHash", type: "bytes32" },
423
+ { name: "destinationHash", type: "bytes32" },
424
+ { name: "depositor", type: "address" },
425
+ { name: "token", type: "address" },
426
+ { name: "amount", type: "uint256" },
427
+ { name: "feeAmount", type: "uint256" },
428
+ { name: "reserver", type: "address" },
429
+ { name: "releaser", type: "address" },
430
+ { name: "settler", type: "address" }
431
+ ]
432
+ };
433
+ function buildTvmRefundTypedDataWithQuoteHash(input) {
434
+ const w = input.witness;
435
+ return {
436
+ types: exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH,
437
+ primaryType: "RefundWitness",
438
+ domain: {
439
+ name: "Escrow",
440
+ version: "3",
441
+ chainId: (0, witness_values_1.maskedChainIdToHex)(input.chainId),
442
+ verifyingContract: (0, tron_address_1.normalizeAddress)(input.escrowContract)
443
+ },
444
+ message: {
445
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", w.depositId),
446
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", w.quoteHash),
447
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", w.depositRequestHash),
448
+ destinationHash: (0, witness_values_1.normalizeBytes32)("destinationHash", w.destinationHash),
449
+ depositor: (0, tron_address_1.normalizeAddress)(w.depositor),
450
+ token: (0, tron_address_1.normalizeAddress)(w.token),
451
+ amount: (0, witness_values_1.normalizeUint256)("amount", w.amount),
452
+ feeAmount: (0, witness_values_1.normalizeUint256)("feeAmount", w.feeAmount),
453
+ reserver: (0, tron_address_1.normalizeAddress)(w.reserver),
454
+ releaser: (0, tron_address_1.normalizeAddress)(w.releaser),
455
+ settler: (0, tron_address_1.normalizeAddress)(w.settler)
456
+ }
457
+ };
458
+ }
459
+ function computeTvmRefundDigestWithQuoteHash(input) {
460
+ const prehash = buildTvmRefundTypedDataWithQuoteHash(input);
461
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
462
+ }
208
463
  }
209
464
  });
210
465
 
@@ -213,7 +468,7 @@ var require_dist = __commonJS({
213
468
  "../contracts/tvm/escrow-encoding/typescript/dist/index.js"(exports2) {
214
469
  "use strict";
215
470
  Object.defineProperty(exports2, "__esModule", { value: true });
216
- exports2.hashTvmPermitWitnessTransferFrom = exports2.createTvmPermitWitnessTransferFromPrehash = exports2.computePaymentId = exports2.computeReserveDigest = exports2.normalizeAddress = exports2.base58ToHex = exports2.maskChainId = void 0;
471
+ exports2.MAX_DESTINATION_BYTES = exports2.createTvmPermitWitnessTransferFromPrehashWithDestination = exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION = exports2.computeTvmRefundDigestWithQuoteHash = exports2.buildTvmRefundTypedDataWithQuoteHash = exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH = exports2.computeTvmReleaseDigestWithQuoteHash = exports2.buildTvmReleaseTypedDataWithQuoteHash = exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH = exports2.computeTvmReserveDigestWithQuoteSource = exports2.buildTvmReserveTypedDataWithQuoteSource = exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE = exports2.hashTvmPermitWitnessTransferFrom = exports2.createTvmPermitWitnessTransferFromPrehash = exports2.computePaymentId = exports2.computeReserveDigest = exports2.normalizeAddress = exports2.base58ToHex = exports2.maskChainId = void 0;
217
472
  var chain_id_1 = require_chain_id();
218
473
  Object.defineProperty(exports2, "maskChainId", { enumerable: true, get: function() {
219
474
  return chain_id_1.maskChainId;
@@ -240,6 +495,222 @@ var require_dist = __commonJS({
240
495
  Object.defineProperty(exports2, "hashTvmPermitWitnessTransferFrom", { enumerable: true, get: function() {
241
496
  return deposit_encoder_1.hashTvmPermitWitnessTransferFrom;
242
497
  } });
498
+ var reserve_encoder_2 = require_reserve_encoder();
499
+ Object.defineProperty(exports2, "RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE", { enumerable: true, get: function() {
500
+ return reserve_encoder_2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE;
501
+ } });
502
+ Object.defineProperty(exports2, "buildTvmReserveTypedDataWithQuoteSource", { enumerable: true, get: function() {
503
+ return reserve_encoder_2.buildTvmReserveTypedDataWithQuoteSource;
504
+ } });
505
+ Object.defineProperty(exports2, "computeTvmReserveDigestWithQuoteSource", { enumerable: true, get: function() {
506
+ return reserve_encoder_2.computeTvmReserveDigestWithQuoteSource;
507
+ } });
508
+ var release_encoder_1 = require_release_encoder();
509
+ Object.defineProperty(exports2, "RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH", { enumerable: true, get: function() {
510
+ return release_encoder_1.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH;
511
+ } });
512
+ Object.defineProperty(exports2, "buildTvmReleaseTypedDataWithQuoteHash", { enumerable: true, get: function() {
513
+ return release_encoder_1.buildTvmReleaseTypedDataWithQuoteHash;
514
+ } });
515
+ Object.defineProperty(exports2, "computeTvmReleaseDigestWithQuoteHash", { enumerable: true, get: function() {
516
+ return release_encoder_1.computeTvmReleaseDigestWithQuoteHash;
517
+ } });
518
+ var refund_encoder_1 = require_refund_encoder();
519
+ Object.defineProperty(exports2, "REFUND_WITNESS_TYPES_WITH_QUOTE_HASH", { enumerable: true, get: function() {
520
+ return refund_encoder_1.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH;
521
+ } });
522
+ Object.defineProperty(exports2, "buildTvmRefundTypedDataWithQuoteHash", { enumerable: true, get: function() {
523
+ return refund_encoder_1.buildTvmRefundTypedDataWithQuoteHash;
524
+ } });
525
+ Object.defineProperty(exports2, "computeTvmRefundDigestWithQuoteHash", { enumerable: true, get: function() {
526
+ return refund_encoder_1.computeTvmRefundDigestWithQuoteHash;
527
+ } });
528
+ var deposit_encoder_2 = require_deposit_encoder();
529
+ Object.defineProperty(exports2, "PERMIT_WITNESS_TYPES_WITH_DESTINATION", { enumerable: true, get: function() {
530
+ return deposit_encoder_2.PERMIT_WITNESS_TYPES_WITH_DESTINATION;
531
+ } });
532
+ Object.defineProperty(exports2, "createTvmPermitWitnessTransferFromPrehashWithDestination", { enumerable: true, get: function() {
533
+ return deposit_encoder_2.createTvmPermitWitnessTransferFromPrehashWithDestination;
534
+ } });
535
+ Object.defineProperty(exports2, "MAX_DESTINATION_BYTES", { enumerable: true, get: function() {
536
+ return deposit_encoder_2.MAX_DESTINATION_BYTES;
537
+ } });
538
+ }
539
+ });
540
+
541
+ // ../schemas/declarations/common/chain-address/typescript/dist/index.js
542
+ var require_dist2 = __commonJS({
543
+ "../schemas/declarations/common/chain-address/typescript/dist/index.js"(exports2) {
544
+ "use strict";
545
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
546
+ return mod && mod.__esModule ? mod : { "default": mod };
547
+ };
548
+ Object.defineProperty(exports2, "__esModule", { value: true });
549
+ exports2.InvalidAccountError = exports2.REASONS = exports2.NAMESPACE_SOLANA = exports2.NAMESPACE_TRON = exports2.NAMESPACE_EIP155 = void 0;
550
+ exports2.supportedNamespaces = supportedNamespaces;
551
+ exports2.parse = parse;
552
+ exports2.validate = validate;
553
+ exports2.checkAccount = checkAccount;
554
+ var bs58_1 = __importDefault(require("bs58"));
555
+ var ethers_1 = require("ethers");
556
+ var tvm_escrow_encoding_1 = require_dist();
557
+ exports2.NAMESPACE_EIP155 = "eip155";
558
+ exports2.NAMESPACE_TRON = "tron";
559
+ exports2.NAMESPACE_SOLANA = "solana";
560
+ exports2.REASONS = [
561
+ "EMPTY",
562
+ "SURROUNDING_WHITESPACE",
563
+ "UNSUPPORTED_NAMESPACE",
564
+ "UNPARSEABLE",
565
+ "ZERO"
566
+ ];
567
+ var InvalidAccountError2 = class extends Error {
568
+ reason;
569
+ network;
570
+ account;
571
+ detail;
572
+ constructor(reason, network, account, detail = "") {
573
+ super(messageFor(reason, network, detail));
574
+ this.name = "InvalidAccountError";
575
+ this.reason = reason;
576
+ this.network = network;
577
+ this.account = account;
578
+ this.detail = detail;
579
+ }
580
+ };
581
+ exports2.InvalidAccountError = InvalidAccountError2;
582
+ function messageFor(reason, network, detail) {
583
+ switch (reason) {
584
+ case "EMPTY":
585
+ return "account is required and cannot be empty";
586
+ case "SURROUNDING_WHITESPACE":
587
+ return "account must not contain leading or trailing whitespace";
588
+ case "UNSUPPORTED_NAMESPACE":
589
+ return `no address rules are known for chain ${network}`;
590
+ case "ZERO":
591
+ return `account is the zero address on ${network}, which cannot receive a payout`;
592
+ default:
593
+ return `account is not a valid address for ${network}`;
594
+ }
595
+ }
596
+ function supportedNamespaces() {
597
+ return [exports2.NAMESPACE_EIP155, exports2.NAMESPACE_SOLANA, exports2.NAMESPACE_TRON];
598
+ }
599
+ function trimSurrounding(value) {
600
+ return value.replace(/^[\s\u0085]+|[\s\u0085]+$/gu, "");
601
+ }
602
+ function parse(network, account) {
603
+ if (trimSurrounding(account) === "") {
604
+ throw new InvalidAccountError2("EMPTY", network, account);
605
+ }
606
+ if (account !== trimSurrounding(account)) {
607
+ throw new InvalidAccountError2("SURROUNDING_WHITESPACE", network, account);
608
+ }
609
+ const separator = network.indexOf(":");
610
+ if (separator <= 0) {
611
+ throw new InvalidAccountError2("UNSUPPORTED_NAMESPACE", network, account);
612
+ }
613
+ const namespace = network.slice(0, separator);
614
+ let bytes;
615
+ try {
616
+ switch (namespace) {
617
+ case exports2.NAMESPACE_EIP155:
618
+ bytes = parseEvm(account);
619
+ break;
620
+ case exports2.NAMESPACE_TRON:
621
+ bytes = parseTron(account);
622
+ break;
623
+ case exports2.NAMESPACE_SOLANA:
624
+ bytes = parseSolana(account);
625
+ break;
626
+ default:
627
+ throw new InvalidAccountError2("UNSUPPORTED_NAMESPACE", network, account);
628
+ }
629
+ } catch (error) {
630
+ if (error instanceof InvalidAccountError2)
631
+ throw error;
632
+ throw new InvalidAccountError2("UNPARSEABLE", network, account, error.message);
633
+ }
634
+ return { namespace, bytes };
635
+ }
636
+ function validate(network, account) {
637
+ const parsed = parse(network, account);
638
+ if (isZero(parsed.bytes)) {
639
+ throw new InvalidAccountError2("ZERO", network, account);
640
+ }
641
+ return parsed;
642
+ }
643
+ function checkAccount(network, account) {
644
+ try {
645
+ validate(network, account);
646
+ return null;
647
+ } catch (error) {
648
+ if (error instanceof InvalidAccountError2)
649
+ return error;
650
+ throw error;
651
+ }
652
+ }
653
+ function isZero(bytes) {
654
+ return bytes.length > 0 && bytes.every((one) => one === 0);
655
+ }
656
+ var HEX_40 = /^(0[xX])?[0-9a-fA-F]{40}$/;
657
+ function parseEvm(account) {
658
+ if (!HEX_40.test(account)) {
659
+ throw new Error("expected 40 hex characters, optionally 0x-prefixed");
660
+ }
661
+ const body = account.replace(/^0[xX]/, "");
662
+ const lower = body.toLowerCase();
663
+ if (body !== lower && body !== body.toUpperCase()) {
664
+ if ((0, ethers_1.getAddress)(`0x${lower}`) !== account) {
665
+ throw new Error("mixed-case address fails its EIP-55 checksum");
666
+ }
667
+ }
668
+ return hexToBytes2(lower);
669
+ }
670
+ function parseTron(account) {
671
+ let hexBody;
672
+ if (account.startsWith("T") && account.length === 34) {
673
+ try {
674
+ hexBody = (0, tvm_escrow_encoding_1.base58ToHex)(account);
675
+ } catch (error) {
676
+ throw new Error(`base58 address failed its checksum: ${error.message}`);
677
+ }
678
+ } else if (account.toLowerCase().startsWith("0x41") && account.length === 44) {
679
+ hexBody = account.slice(2);
680
+ } else if (HEX_40.test(account)) {
681
+ return parseEvm(account);
682
+ } else {
683
+ throw new Error("expected a T-prefixed base58 address or 40 hex characters");
684
+ }
685
+ hexBody = hexBody.startsWith("41") ? hexBody.slice(2) : hexBody;
686
+ if (hexBody.length !== 40) {
687
+ throw new Error(`expected 40 hex characters after conversion, got ${hexBody.length}`);
688
+ }
689
+ return hexToBytes2(hexBody);
690
+ }
691
+ function parseSolana(account) {
692
+ let decoded;
693
+ try {
694
+ decoded = bs58_1.default.decode(account);
695
+ } catch {
696
+ throw new Error("expected a 32-byte base58 public key");
697
+ }
698
+ if (decoded.length !== 32) {
699
+ throw new Error(`expected a 32-byte base58 public key, got ${decoded.length} bytes`);
700
+ }
701
+ return decoded;
702
+ }
703
+ var HEX_BODY = /^[0-9a-fA-F]*$/;
704
+ function hexToBytes2(hex) {
705
+ if (hex.length % 2 !== 0 || !HEX_BODY.test(hex)) {
706
+ throw new Error("expected hex characters");
707
+ }
708
+ const out = new Uint8Array(hex.length / 2);
709
+ for (let i = 0; i < out.length; i += 1) {
710
+ out[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
711
+ }
712
+ return out;
713
+ }
243
714
  }
244
715
  });
245
716
 
@@ -251,12 +722,96 @@ var require_types = __commonJS({
251
722
  }
252
723
  });
253
724
 
725
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/destination.js
726
+ var require_destination = __commonJS({
727
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/destination.js"(exports2) {
728
+ "use strict";
729
+ Object.defineProperty(exports2, "__esModule", { value: true });
730
+ exports2.DESTINATION_COMMITMENT_WITNESS_VERSION = exports2.MAX_DESTINATION_BYTES = void 0;
731
+ exports2.usesDestinationCommitment = usesDestinationCommitment;
732
+ exports2.deriveDepositRequestHash = deriveDepositRequestHash;
733
+ exports2.buildEscrowDestination = buildEscrowDestination;
734
+ var ethers_1 = require("ethers");
735
+ exports2.MAX_DESTINATION_BYTES = 256;
736
+ var NAMESPACE_EIP155 = "eip155";
737
+ exports2.DESTINATION_COMMITMENT_WITNESS_VERSION = 4;
738
+ function usesDestinationCommitment(depositWitnessVersion) {
739
+ return depositWitnessVersion === void 0 || depositWitnessVersion >= exports2.DESTINATION_COMMITMENT_WITNESS_VERSION;
740
+ }
741
+ function deriveDepositRequestHash(requestId) {
742
+ if (requestId === "") {
743
+ throw new Error('sender_auth: cannot derive deposit_request_hash: request_id is empty, and keccak256("") is a perfectly valid non-zero bytes32, so this would silently commit every empty-id deposit to the same hash instead of failing');
744
+ }
745
+ return (0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)(requestId));
746
+ }
747
+ function buildEscrowDestination(assetIdentifier, account) {
748
+ if (assetIdentifier === "") {
749
+ throw new Error("sender_auth: destination asset_identifier is empty");
750
+ }
751
+ if (account === "") {
752
+ throw new Error("sender_auth: destination account is empty");
753
+ }
754
+ if (assetIdentifier.includes("@") || account.includes("@")) {
755
+ throw new Error(`sender_auth: destination asset_identifier (${JSON.stringify(assetIdentifier)}) and account (${JSON.stringify(account)}) must not contain '@': it is the separator between them in the committed destination grammar`);
756
+ }
757
+ const namespace = caip2Namespace(assetIdentifier);
758
+ let asset = assetIdentifier;
759
+ let acct = account;
760
+ if (namespace === NAMESPACE_EIP155) {
761
+ asset = asset.toLowerCase();
762
+ acct = acct.toLowerCase();
763
+ }
764
+ const destination = `${asset}@${acct}`;
765
+ const byteLength = (0, ethers_1.toUtf8Bytes)(destination).length;
766
+ if (byteLength > exports2.MAX_DESTINATION_BYTES) {
767
+ throw new Error(`sender_auth: composed destination is ${byteLength} bytes, over the escrow's MAX_DESTINATION_BYTES of ${exports2.MAX_DESTINATION_BYTES}: the contract reverts DestinationTooLong, so this deposit could never be redeemed`);
768
+ }
769
+ return destination;
770
+ }
771
+ function caip2Namespace(assetIdentifier) {
772
+ const slash = assetIdentifier.indexOf("/");
773
+ const chainPart = slash === -1 ? "" : assetIdentifier.slice(0, slash);
774
+ const assetPart = slash === -1 ? "" : assetIdentifier.slice(slash + 1);
775
+ if (slash === -1 || chainPart === "" || assetPart === "") {
776
+ const looksLegacy = !assetIdentifier.includes("/") && countChar(assetIdentifier, ":") === 2;
777
+ const hint = looksLegacy ? " (this looks like the deprecated `<chain>:<ref>:<asset>` form; migrate it to `<chain>:<ref>/<asset-namespace>:<asset-reference>`)" : "";
778
+ throw new Error(`sender_auth: destination asset_identifier ${JSON.stringify(assetIdentifier)} is not CAIP-19: expected <caip2-chain-id>/<asset-namespace>:<asset-reference>${hint}`);
779
+ }
780
+ const assetColon = assetPart.indexOf(":");
781
+ if (assetColon <= 0 || assetColon === assetPart.length - 1) {
782
+ throw new Error(`sender_auth: destination asset_identifier ${JSON.stringify(assetIdentifier)} has a malformed asset part ${JSON.stringify(assetPart)}: expected <asset-namespace>:<asset-reference>`);
783
+ }
784
+ const assetNamespace = assetPart.slice(0, assetColon);
785
+ if (assetNamespace !== assetNamespace.toLowerCase()) {
786
+ throw new Error(`sender_auth: destination asset_identifier ${JSON.stringify(assetIdentifier)} has a non-canonical asset namespace ${JSON.stringify(assetNamespace)}: the ratified grammar requires it lowercase (${JSON.stringify(assetNamespace.toLowerCase())}). It is rejected rather than normalised because the destination commitment is over these exact bytes`);
787
+ }
788
+ const chainColon = chainPart.indexOf(":");
789
+ if (chainColon <= 0 || chainColon === chainPart.length - 1) {
790
+ throw new Error(`sender_auth: destination asset_identifier ${JSON.stringify(assetIdentifier)} has a malformed chain part ${JSON.stringify(chainPart)}: expected <namespace>:<reference>`);
791
+ }
792
+ const namespace = chainPart.slice(0, chainColon);
793
+ if (namespace !== namespace.toLowerCase()) {
794
+ throw new Error(`sender_auth: destination asset_identifier ${JSON.stringify(assetIdentifier)} has a non-canonical chain namespace ${JSON.stringify(namespace)}: the ratified grammar requires it lowercase (${JSON.stringify(namespace.toLowerCase())}). It is rejected rather than normalised because the destination commitment is over these exact bytes`);
795
+ }
796
+ return namespace;
797
+ }
798
+ function countChar(s, c) {
799
+ let n = 0;
800
+ for (const ch of s) {
801
+ if (ch === c)
802
+ n++;
803
+ }
804
+ return n;
805
+ }
806
+ }
807
+ });
808
+
254
809
  // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/utils.js
255
810
  var require_utils = __commonJS({
256
811
  "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/utils.js"(exports2) {
257
812
  "use strict";
258
813
  Object.defineProperty(exports2, "__esModule", { value: true });
259
- exports2.REQUEST_ID_DOMAIN = exports2.SOLANA_REPLAY_SLOTS = exports2.PERMIT_NONCE_DOMAIN = exports2.REPLAY_HORIZON_SECS = void 0;
814
+ exports2.REQUEST_ID_DOMAIN = exports2.SOLANA_REPLAY_BUCKETS = exports2.SOLANA_REPLAY_SLOTS = exports2.PERMIT_NONCE_DOMAIN = exports2.REPLAY_HORIZON_SECS = void 0;
260
815
  exports2.resolvePermitDeadline = resolvePermitDeadline;
261
816
  exports2.generatePermitNonce = generatePermitNonce;
262
817
  exports2.resolvePermitNonce = resolvePermitNonce;
@@ -264,6 +819,7 @@ var require_utils = __commonJS({
264
819
  exports2.deterministicPermitNonce = deterministicPermitNonce2;
265
820
  exports2.deterministicSolanaNonce = deterministicSolanaNonce2;
266
821
  exports2.deterministicRequestId = deterministicRequestId;
822
+ exports2.parseSourceAsset = parseSourceAsset;
267
823
  exports2.sameAddress = sameAddress;
268
824
  exports2.assertKeyMatchesSender = assertKeyMatchesSender2;
269
825
  exports2.assertToken = assertToken;
@@ -272,8 +828,11 @@ var require_utils = __commonJS({
272
828
  exports2.assertSpender = assertSpender;
273
829
  exports2.assertWitnessRoles = assertWitnessRoles;
274
830
  exports2.assertRolePairComplete = assertRolePairComplete;
831
+ exports2.assertDestination = assertDestination;
832
+ exports2.assertDepositRequestHash = assertDepositRequestHash;
275
833
  exports2.nowSec = nowSec;
276
834
  var ethers_1 = require("ethers");
835
+ var destination_js_1 = require_destination();
277
836
  exports2.REPLAY_HORIZON_SECS = 128;
278
837
  function resolvePermitDeadline(deadline) {
279
838
  return BigInt(deadline);
@@ -288,7 +847,7 @@ var require_utils = __commonJS({
288
847
  }
289
848
  exports2.PERMIT_NONCE_DOMAIN = "atum-permit:v1:";
290
849
  exports2.SOLANA_REPLAY_SLOTS = 235n;
291
- var SOLANA_BUCKET_BITS = 17n;
850
+ exports2.SOLANA_REPLAY_BUCKETS = 256n;
292
851
  function canonicalDepositor(depositor) {
293
852
  const lower = depositor.toLowerCase();
294
853
  return lower.startsWith("0x") ? lower : depositor;
@@ -305,7 +864,7 @@ var require_utils = __commonJS({
305
864
  function deterministicSolanaNonce2(params) {
306
865
  const seed = permitNonceSeed(params.requestId, params.depositor);
307
866
  const slot = seed % exports2.SOLANA_REPLAY_SLOTS;
308
- const bucket = (seed >> 8n) % (1n << SOLANA_BUCKET_BITS);
867
+ const bucket = (seed >> 8n) % exports2.SOLANA_REPLAY_BUCKETS;
309
868
  return bucket << 32n | slot;
310
869
  }
311
870
  exports2.REQUEST_ID_DOMAIN = "atum-request:v1:";
@@ -322,6 +881,17 @@ var require_utils = __commonJS({
322
881
  const digest = (0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)(`${exports2.REQUEST_ID_DOMAIN}${params.anchor}:${canonicalDepositor(params.account)}`));
323
882
  return `${params.prefix}${digest.slice(2, 26)}`;
324
883
  }
884
+ function parseSourceAsset(assetIdentifier) {
885
+ const parts = typeof assetIdentifier === "string" ? assetIdentifier.split("/") : [];
886
+ const nsParts = parts[1]?.split(":");
887
+ if (parts.length === 3 && parts[0] && parts[1] && parts[2]) {
888
+ throw new Error(`sender_auth: source asset ${JSON.stringify(assetIdentifier)} names a token id, which a deposit cannot bind`);
889
+ }
890
+ if (parts.length !== 2 || !parts[0] || !nsParts || nsParts.length !== 2 || !nsParts[0] || !nsParts[1]) {
891
+ throw new Error(`sender_auth: invalid source asset ${JSON.stringify(assetIdentifier)}`);
892
+ }
893
+ return { network: parts[0], asset: nsParts[1] };
894
+ }
325
895
  function sameAddress(a, b) {
326
896
  if (a.startsWith("0x") && b.startsWith("0x")) {
327
897
  return a.toLowerCase() === b.toLowerCase();
@@ -363,6 +933,17 @@ var require_utils = __commonJS({
363
933
  throw new Error("sender_auth: reserver and releaser must be supplied together");
364
934
  }
365
935
  }
936
+ function assertDestination(signed, expected) {
937
+ if (signed !== expected) {
938
+ throw new Error(`sender_auth: signed deposit destination ${JSON.stringify(signed)} does not match the expected destination ${JSON.stringify(expected)} \u2014 the escrow stores only keccak256(bytes(destination)) and cannot tell a formatting disagreement from a wrong payee, so a deposit signed against this destination could be neither released nor refunded`);
939
+ }
940
+ }
941
+ function assertDepositRequestHash(signedHex, expectedRequestId) {
942
+ const expected = (0, destination_js_1.deriveDepositRequestHash)(expectedRequestId);
943
+ if (signedHex.toLowerCase() !== expected.toLowerCase()) {
944
+ throw new Error(`sender_auth: signed deposit_request_hash ${signedHex} is not keccak256(request_id) for request_id ${JSON.stringify(expectedRequestId)} (expected ${expected}): the deposit authorizes a different payment request`);
945
+ }
946
+ }
366
947
  function nowSec() {
367
948
  return Math.floor(Date.now() / 1e3);
368
949
  }
@@ -374,7 +955,7 @@ var require_chain_id2 = __commonJS({
374
955
  "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/chain-id.js"(exports2) {
375
956
  "use strict";
376
957
  Object.defineProperty(exports2, "__esModule", { value: true });
377
- exports2.TRON_PERMIT2_FALLBACKS = exports2.TRON_CHAIN_IDS = void 0;
958
+ exports2.TRON_PERMIT2_FALLBACKS = exports2.TRON_CHAIN_IDS = exports2.MAX_EVM_CHAIN_ID = void 0;
378
959
  exports2.namespaceOf = namespaceOf;
379
960
  exports2.evmChainId = evmChainId;
380
961
  exports2.tronNumericChainId = tronNumericChainId;
@@ -383,21 +964,30 @@ var require_chain_id2 = __commonJS({
383
964
  function namespaceOf(network) {
384
965
  return network.split(":")[0];
385
966
  }
967
+ exports2.MAX_EVM_CHAIN_ID = Number.MAX_SAFE_INTEGER;
386
968
  function evmChainId(network) {
387
969
  const match = /^eip155:([0-9]+)$/.exec(network);
388
970
  if (!match) {
389
971
  throw new Error(`sender_auth: expected an eip155 network, got ${network}`);
390
972
  }
391
- return Number(match[1]);
973
+ const chainId = Number(match[1]);
974
+ if (chainId > exports2.MAX_EVM_CHAIN_ID) {
975
+ throw new Error(`sender_auth: eip155 chain id ${match[1]} exceeds the EIP-2294 maximum (${exports2.MAX_EVM_CHAIN_ID})`);
976
+ }
977
+ return chainId;
392
978
  }
393
979
  exports2.TRON_CHAIN_IDS = {
394
980
  mainnet: 728126428,
395
981
  shasta: 2494104990
396
982
  };
397
983
  function tronNumericChainId(network) {
398
- const cluster = network.split(":")[1];
399
- const id = exports2.TRON_CHAIN_IDS[cluster ?? ""];
400
- if (id === void 0) {
984
+ if (namespaceOf(network) !== "tron") {
985
+ throw new Error(`sender_auth: expected a tron network, got ${network}`);
986
+ }
987
+ const segments = network.split(":");
988
+ const cluster = segments.length === 2 ? segments[1] : void 0;
989
+ const id = cluster !== void 0 && Object.hasOwn(exports2.TRON_CHAIN_IDS, cluster) ? exports2.TRON_CHAIN_IDS[cluster] : void 0;
990
+ if (typeof id !== "number") {
401
991
  throw new Error(`sender_auth: unsupported Tron network '${network}'`);
402
992
  }
403
993
  return id;
@@ -407,8 +997,8 @@ var require_chain_id2 = __commonJS({
407
997
  "tron:shasta": "TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp"
408
998
  };
409
999
  function resolveTronPermit2(network) {
410
- const resolved = exports2.TRON_PERMIT2_FALLBACKS[network];
411
- if (!resolved) {
1000
+ const resolved = Object.hasOwn(exports2.TRON_PERMIT2_FALLBACKS, network) ? exports2.TRON_PERMIT2_FALLBACKS[network] : void 0;
1001
+ if (typeof resolved !== "string" || resolved === "") {
412
1002
  throw new Error(`sender_auth: no Permit2 address known for Tron network '${network}'`);
413
1003
  }
414
1004
  return resolved;
@@ -464,7 +1054,7 @@ var require_permit_types = __commonJS({
464
1054
  "../contracts/evm/escrow-encoding/typescript/dist/permit-types.js"(exports2) {
465
1055
  "use strict";
466
1056
  Object.defineProperty(exports2, "__esModule", { value: true });
467
- exports2.REFUND_WITNESS_TYPES = exports2.RELEASE_WITNESS_TYPES = exports2.RESERVE_WITNESS_TYPES = exports2.PERMIT_WITNESS_TYPES_V2 = exports2.PERMIT_WITNESS_TYPES = void 0;
1057
+ exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH = exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH = exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE = exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION = exports2.REFUND_WITNESS_TYPES = exports2.RELEASE_WITNESS_TYPES = exports2.RESERVE_WITNESS_TYPES = exports2.PERMIT_WITNESS_TYPES_V2 = exports2.PERMIT_WITNESS_TYPES = void 0;
468
1058
  exports2.createPermit2Domain = createPermit2Domain;
469
1059
  exports2.createEscrowDomain = createEscrowDomain;
470
1060
  exports2.PERMIT_WITNESS_TYPES = {
@@ -547,6 +1137,63 @@ var require_permit_types = __commonJS({
547
1137
  { name: "settler", type: "address" }
548
1138
  ]
549
1139
  };
1140
+ exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION = {
1141
+ PermitWitnessTransferFrom: [
1142
+ { name: "permitted", type: "TokenPermissions" },
1143
+ { name: "spender", type: "address" },
1144
+ { name: "nonce", type: "uint256" },
1145
+ { name: "deadline", type: "uint256" },
1146
+ { name: "witness", type: "DepositWitness" }
1147
+ ],
1148
+ TokenPermissions: [
1149
+ { name: "token", type: "address" },
1150
+ { name: "amount", type: "uint256" }
1151
+ ],
1152
+ DepositWitness: [
1153
+ { name: "depositRequestHash", type: "bytes32" },
1154
+ { name: "destination", type: "string" },
1155
+ { name: "reserver", type: "address" },
1156
+ { name: "releaser", type: "address" }
1157
+ ]
1158
+ };
1159
+ exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE = {
1160
+ ReserveWitness: [
1161
+ { name: "depositId", type: "bytes32" },
1162
+ { name: "quoteHash", type: "bytes32" },
1163
+ { name: "settler", type: "address" },
1164
+ { name: "sourceAmount", type: "uint256" }
1165
+ ]
1166
+ };
1167
+ exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH = {
1168
+ ReleaseWitness: [
1169
+ { name: "depositId", type: "bytes32" },
1170
+ { name: "quoteHash", type: "bytes32" },
1171
+ { name: "depositRequestHash", type: "bytes32" },
1172
+ { name: "destinationHash", type: "bytes32" },
1173
+ { name: "depositor", type: "address" },
1174
+ { name: "token", type: "address" },
1175
+ { name: "amount", type: "uint256" },
1176
+ { name: "feeAmount", type: "uint256" },
1177
+ { name: "reserver", type: "address" },
1178
+ { name: "releaser", type: "address" },
1179
+ { name: "settler", type: "address" }
1180
+ ]
1181
+ };
1182
+ exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH = {
1183
+ RefundWitness: [
1184
+ { name: "depositId", type: "bytes32" },
1185
+ { name: "quoteHash", type: "bytes32" },
1186
+ { name: "depositRequestHash", type: "bytes32" },
1187
+ { name: "destinationHash", type: "bytes32" },
1188
+ { name: "depositor", type: "address" },
1189
+ { name: "token", type: "address" },
1190
+ { name: "amount", type: "uint256" },
1191
+ { name: "feeAmount", type: "uint256" },
1192
+ { name: "reserver", type: "address" },
1193
+ { name: "releaser", type: "address" },
1194
+ { name: "settler", type: "address" }
1195
+ ]
1196
+ };
550
1197
  }
551
1198
  });
552
1199
 
@@ -673,6 +1320,8 @@ var require_escrow_abi = __commonJS({
673
1320
  name: "depositWitness",
674
1321
  type: "tuple",
675
1322
  components: [
1323
+ { name: "depositRequestHash", type: "bytes32" },
1324
+ { name: "destination", type: "string" },
676
1325
  { name: "reserver", type: "address" },
677
1326
  { name: "releaser", type: "address" }
678
1327
  ]
@@ -682,15 +1331,17 @@ var require_escrow_abi = __commonJS({
682
1331
  name: "reserveWitness",
683
1332
  type: "tuple",
684
1333
  components: [
685
- { name: "paymentId", type: "bytes32" },
686
- { name: "settler", type: "address" }
1334
+ { name: "depositId", type: "bytes32" },
1335
+ { name: "quoteHash", type: "bytes32" },
1336
+ { name: "settler", type: "address" },
1337
+ { name: "sourceAmount", type: "uint256" }
687
1338
  ]
688
1339
  },
689
1340
  { name: "reserveSignature", type: "bytes" }
690
1341
  ]
691
1342
  }
692
1343
  ],
693
- outputs: [{ name: "paymentId", type: "bytes32" }],
1344
+ outputs: [{ name: "depositId", type: "bytes32" }],
694
1345
  stateMutability: "nonpayable"
695
1346
  },
696
1347
  {
@@ -705,7 +1356,10 @@ var require_escrow_abi = __commonJS({
705
1356
  name: "refundWitness",
706
1357
  type: "tuple",
707
1358
  components: [
708
- { name: "paymentId", type: "bytes32" },
1359
+ { name: "depositId", type: "bytes32" },
1360
+ { name: "quoteHash", type: "bytes32" },
1361
+ { name: "depositRequestHash", type: "bytes32" },
1362
+ { name: "destinationHash", type: "bytes32" },
709
1363
  { name: "depositor", type: "address" },
710
1364
  { name: "token", type: "address" },
711
1365
  { name: "amount", type: "uint256" },
@@ -725,7 +1379,7 @@ var require_escrow_abi = __commonJS({
725
1379
  {
726
1380
  type: "function",
727
1381
  name: "getDepositHash",
728
- inputs: [{ name: "paymentId", type: "bytes32" }],
1382
+ inputs: [{ name: "depositId", type: "bytes32" }],
729
1383
  outputs: [{ name: "", type: "bytes32" }],
730
1384
  stateMutability: "view"
731
1385
  },
@@ -741,14 +1395,67 @@ var require_escrow_abi = __commonJS({
741
1395
  }
742
1396
  });
743
1397
 
1398
+ // ../contracts/evm/escrow-encoding/typescript/dist/witness-values.js
1399
+ var require_witness_values2 = __commonJS({
1400
+ "../contracts/evm/escrow-encoding/typescript/dist/witness-values.js"(exports2) {
1401
+ "use strict";
1402
+ Object.defineProperty(exports2, "__esModule", { value: true });
1403
+ exports2.normalizeBytes32 = normalizeBytes32;
1404
+ exports2.normalizeAddressField = normalizeAddressField;
1405
+ exports2.normalizeUint256 = normalizeUint256;
1406
+ exports2.chainIdToHex = chainIdToHex;
1407
+ var ethers_1 = require("ethers");
1408
+ function normalizeBytes32(label, value) {
1409
+ let bytes;
1410
+ try {
1411
+ bytes = (0, ethers_1.getBytes)(value);
1412
+ } catch {
1413
+ throw new Error(`${label} must be 0x-prefixed hex (32 bytes), got ${JSON.stringify(value)}`);
1414
+ }
1415
+ if (bytes.length !== 32) {
1416
+ throw new Error(`${label} must be exactly 32 bytes, got ${bytes.length}`);
1417
+ }
1418
+ return (0, ethers_1.hexlify)(bytes);
1419
+ }
1420
+ function normalizeAddressField(label, value) {
1421
+ try {
1422
+ return (0, ethers_1.getAddress)(value);
1423
+ } catch {
1424
+ throw new Error(`${label} must be a 20-byte hex address, got ${JSON.stringify(value)}`);
1425
+ }
1426
+ }
1427
+ function normalizeUint256(label, value) {
1428
+ let n;
1429
+ try {
1430
+ n = BigInt(value);
1431
+ } catch {
1432
+ throw new Error(`${label} must be an integer (bigint or decimal string), got ${JSON.stringify(value)}`);
1433
+ }
1434
+ if (n < 0n) {
1435
+ throw new Error(`${label} must be non-negative (uint256), got ${n.toString()}`);
1436
+ }
1437
+ return n.toString();
1438
+ }
1439
+ function chainIdToHex(chainId) {
1440
+ if (!Number.isSafeInteger(chainId) || chainId < 0) {
1441
+ throw new Error(`chainId must be a non-negative safe integer, got ${chainId}`);
1442
+ }
1443
+ return `0x${chainId.toString(16)}`;
1444
+ }
1445
+ }
1446
+ });
1447
+
744
1448
  // ../contracts/evm/escrow-encoding/typescript/dist/reserve-encoder.js
745
1449
  var require_reserve_encoder2 = __commonJS({
746
1450
  "../contracts/evm/escrow-encoding/typescript/dist/reserve-encoder.js"(exports2) {
747
1451
  "use strict";
748
1452
  Object.defineProperty(exports2, "__esModule", { value: true });
749
1453
  exports2.computeReserveDigest = computeReserveDigest;
1454
+ exports2.buildReserveTypedDataWithQuoteSource = buildReserveTypedDataWithQuoteSource;
1455
+ exports2.computeReserveDigestWithQuoteSource = computeReserveDigestWithQuoteSource;
750
1456
  var ethers_1 = require("ethers");
751
1457
  var permit_types_1 = require_permit_types();
1458
+ var witness_values_1 = require_witness_values2();
752
1459
  function computeReserveDigest(input) {
753
1460
  const domain = (0, permit_types_1.createEscrowDomain)(input.chainId, input.escrowContract);
754
1461
  return ethers_1.TypedDataEncoder.hash(domain, permit_types_1.RESERVE_WITNESS_TYPES, {
@@ -756,6 +1463,114 @@ var require_reserve_encoder2 = __commonJS({
756
1463
  settler: input.settler
757
1464
  });
758
1465
  }
1466
+ function buildReserveTypedDataWithQuoteSource(input) {
1467
+ return {
1468
+ types: permit_types_1.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE,
1469
+ primaryType: "ReserveWitness",
1470
+ domain: {
1471
+ name: "Escrow",
1472
+ version: "3",
1473
+ chainId: (0, witness_values_1.chainIdToHex)(input.chainId),
1474
+ verifyingContract: (0, witness_values_1.normalizeAddressField)("escrowContract", input.escrowContract)
1475
+ },
1476
+ message: {
1477
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", input.depositId),
1478
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", input.quoteHash),
1479
+ settler: (0, witness_values_1.normalizeAddressField)("settler", input.settler),
1480
+ sourceAmount: (0, witness_values_1.normalizeUint256)("sourceAmount", input.sourceAmount)
1481
+ }
1482
+ };
1483
+ }
1484
+ function computeReserveDigestWithQuoteSource(input) {
1485
+ const prehash = buildReserveTypedDataWithQuoteSource(input);
1486
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
1487
+ }
1488
+ }
1489
+ });
1490
+
1491
+ // ../contracts/evm/escrow-encoding/typescript/dist/release-encoder.js
1492
+ var require_release_encoder2 = __commonJS({
1493
+ "../contracts/evm/escrow-encoding/typescript/dist/release-encoder.js"(exports2) {
1494
+ "use strict";
1495
+ Object.defineProperty(exports2, "__esModule", { value: true });
1496
+ exports2.buildReleaseTypedDataWithQuoteHash = buildReleaseTypedDataWithQuoteHash;
1497
+ exports2.computeReleaseDigestWithQuoteHash = computeReleaseDigestWithQuoteHash;
1498
+ var ethers_1 = require("ethers");
1499
+ var permit_types_1 = require_permit_types();
1500
+ var witness_values_1 = require_witness_values2();
1501
+ function buildReleaseTypedDataWithQuoteHash(input) {
1502
+ const w = input.witness;
1503
+ return {
1504
+ types: permit_types_1.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH,
1505
+ primaryType: "ReleaseWitness",
1506
+ domain: {
1507
+ name: "Escrow",
1508
+ version: "3",
1509
+ chainId: (0, witness_values_1.chainIdToHex)(input.chainId),
1510
+ verifyingContract: (0, witness_values_1.normalizeAddressField)("escrowContract", input.escrowContract)
1511
+ },
1512
+ message: {
1513
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", w.depositId),
1514
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", w.quoteHash),
1515
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", w.depositRequestHash),
1516
+ destinationHash: (0, witness_values_1.normalizeBytes32)("destinationHash", w.destinationHash),
1517
+ depositor: (0, witness_values_1.normalizeAddressField)("depositor", w.depositor),
1518
+ token: (0, witness_values_1.normalizeAddressField)("token", w.token),
1519
+ amount: (0, witness_values_1.normalizeUint256)("amount", w.amount),
1520
+ feeAmount: (0, witness_values_1.normalizeUint256)("feeAmount", w.feeAmount),
1521
+ reserver: (0, witness_values_1.normalizeAddressField)("reserver", w.reserver),
1522
+ releaser: (0, witness_values_1.normalizeAddressField)("releaser", w.releaser),
1523
+ settler: (0, witness_values_1.normalizeAddressField)("settler", w.settler)
1524
+ }
1525
+ };
1526
+ }
1527
+ function computeReleaseDigestWithQuoteHash(input) {
1528
+ const prehash = buildReleaseTypedDataWithQuoteHash(input);
1529
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
1530
+ }
1531
+ }
1532
+ });
1533
+
1534
+ // ../contracts/evm/escrow-encoding/typescript/dist/refund-encoder.js
1535
+ var require_refund_encoder2 = __commonJS({
1536
+ "../contracts/evm/escrow-encoding/typescript/dist/refund-encoder.js"(exports2) {
1537
+ "use strict";
1538
+ Object.defineProperty(exports2, "__esModule", { value: true });
1539
+ exports2.buildRefundTypedDataWithQuoteHash = buildRefundTypedDataWithQuoteHash;
1540
+ exports2.computeRefundDigestWithQuoteHash = computeRefundDigestWithQuoteHash;
1541
+ var ethers_1 = require("ethers");
1542
+ var permit_types_1 = require_permit_types();
1543
+ var witness_values_1 = require_witness_values2();
1544
+ function buildRefundTypedDataWithQuoteHash(input) {
1545
+ const w = input.witness;
1546
+ return {
1547
+ types: permit_types_1.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH,
1548
+ primaryType: "RefundWitness",
1549
+ domain: {
1550
+ name: "Escrow",
1551
+ version: "3",
1552
+ chainId: (0, witness_values_1.chainIdToHex)(input.chainId),
1553
+ verifyingContract: (0, witness_values_1.normalizeAddressField)("escrowContract", input.escrowContract)
1554
+ },
1555
+ message: {
1556
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", w.depositId),
1557
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", w.quoteHash),
1558
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", w.depositRequestHash),
1559
+ destinationHash: (0, witness_values_1.normalizeBytes32)("destinationHash", w.destinationHash),
1560
+ depositor: (0, witness_values_1.normalizeAddressField)("depositor", w.depositor),
1561
+ token: (0, witness_values_1.normalizeAddressField)("token", w.token),
1562
+ amount: (0, witness_values_1.normalizeUint256)("amount", w.amount),
1563
+ feeAmount: (0, witness_values_1.normalizeUint256)("feeAmount", w.feeAmount),
1564
+ reserver: (0, witness_values_1.normalizeAddressField)("reserver", w.reserver),
1565
+ releaser: (0, witness_values_1.normalizeAddressField)("releaser", w.releaser),
1566
+ settler: (0, witness_values_1.normalizeAddressField)("settler", w.settler)
1567
+ }
1568
+ };
1569
+ }
1570
+ function computeRefundDigestWithQuoteHash(input) {
1571
+ const prehash = buildRefundTypedDataWithQuoteHash(input);
1572
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
1573
+ }
759
1574
  }
760
1575
  });
761
1576
 
@@ -764,11 +1579,13 @@ var require_deposit_encoder2 = __commonJS({
764
1579
  "../contracts/evm/escrow-encoding/typescript/dist/deposit-encoder.js"(exports2) {
765
1580
  "use strict";
766
1581
  Object.defineProperty(exports2, "__esModule", { value: true });
767
- exports2.PERMIT2_CONTRACT_ADDRESS = void 0;
1582
+ exports2.MAX_DESTINATION_BYTES = exports2.PERMIT2_CONTRACT_ADDRESS = void 0;
768
1583
  exports2.createPermitWitnessTransferFromPrehash = createPermitWitnessTransferFromPrehash2;
769
1584
  exports2.hashPermitWitnessTransferFrom = hashPermitWitnessTransferFrom2;
1585
+ exports2.createPermitWitnessTransferFromPrehashWithDestination = createPermitWitnessTransferFromPrehashWithDestination;
770
1586
  var ethers_1 = require("ethers");
771
1587
  var permit_types_1 = require_permit_types();
1588
+ var witness_values_1 = require_witness_values2();
772
1589
  exports2.PERMIT2_CONTRACT_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
773
1590
  function createPermitWitnessTransferFromPrehash2(params) {
774
1591
  return {
@@ -797,15 +1614,52 @@ var require_deposit_encoder2 = __commonJS({
797
1614
  function hashPermitWitnessTransferFrom2(prehash) {
798
1615
  return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
799
1616
  }
1617
+ exports2.MAX_DESTINATION_BYTES = 256;
1618
+ function assertDestinationWithinBounds(destination) {
1619
+ if (destination === "") {
1620
+ throw new Error('destination is empty: the escrow reverts DestinationCannotBeEmpty, and because keccak256("") is a valid bytes32 this would otherwise sign a commitment to no destination at all');
1621
+ }
1622
+ const byteLength = (0, ethers_1.toUtf8Bytes)(destination).length;
1623
+ if (byteLength > exports2.MAX_DESTINATION_BYTES) {
1624
+ throw new Error(`destination is ${byteLength} bytes, over the escrow's MAX_DESTINATION_BYTES of ${exports2.MAX_DESTINATION_BYTES}: the contract reverts DestinationTooLong, so this digest could never be redeemed`);
1625
+ }
1626
+ }
1627
+ function createPermitWitnessTransferFromPrehashWithDestination(params) {
1628
+ assertDestinationWithinBounds(params.destination);
1629
+ return {
1630
+ types: permit_types_1.PERMIT_WITNESS_TYPES_WITH_DESTINATION,
1631
+ primaryType: "PermitWitnessTransferFrom",
1632
+ domain: {
1633
+ name: "Permit2",
1634
+ chainId: (0, witness_values_1.chainIdToHex)(params.chainId),
1635
+ verifyingContract: (0, witness_values_1.normalizeAddressField)("verifyingContract", params.verifyingContract)
1636
+ },
1637
+ message: {
1638
+ permitted: {
1639
+ token: (0, witness_values_1.normalizeAddressField)("token", params.token),
1640
+ amount: (0, witness_values_1.normalizeUint256)("amount", params.amount)
1641
+ },
1642
+ spender: (0, witness_values_1.normalizeAddressField)("spender", params.spender),
1643
+ nonce: (0, witness_values_1.normalizeUint256)("nonce", params.nonce),
1644
+ deadline: (0, witness_values_1.normalizeUint256)("deadline", params.deadline),
1645
+ witness: {
1646
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", params.depositRequestHash),
1647
+ destination: params.destination,
1648
+ reserver: (0, witness_values_1.normalizeAddressField)("reserver", params.reserver),
1649
+ releaser: (0, witness_values_1.normalizeAddressField)("releaser", params.releaser)
1650
+ }
1651
+ }
1652
+ };
1653
+ }
800
1654
  }
801
1655
  });
802
1656
 
803
1657
  // ../contracts/evm/escrow-encoding/typescript/dist/index.js
804
- var require_dist2 = __commonJS({
1658
+ var require_dist3 = __commonJS({
805
1659
  "../contracts/evm/escrow-encoding/typescript/dist/index.js"(exports2) {
806
1660
  "use strict";
807
1661
  Object.defineProperty(exports2, "__esModule", { value: true });
808
- exports2.PERMIT2_CONTRACT_ADDRESS = exports2.hashPermitWitnessTransferFrom = exports2.createPermitWitnessTransferFromPrehash = exports2.computeReserveDigest = exports2.ESCROW_V3_ABI_JSON = exports2.ESCROW_V2_ABI_JSON = exports2.ESCROW_ABI_JSON = exports2.ESCROW_ABI = exports2.REFUND_WITNESS_TYPES = exports2.RELEASE_WITNESS_TYPES = exports2.RESERVE_WITNESS_TYPES = exports2.createEscrowDomain = exports2.createPermit2Domain = exports2.PERMIT_WITNESS_TYPES_V2 = exports2.PERMIT_WITNESS_TYPES = exports2.generateNonce = exports2.computePaymentIdV2 = exports2.computePaymentId = void 0;
1662
+ exports2.MAX_DESTINATION_BYTES = exports2.createPermitWitnessTransferFromPrehashWithDestination = exports2.PERMIT2_CONTRACT_ADDRESS = exports2.hashPermitWitnessTransferFrom = exports2.createPermitWitnessTransferFromPrehash = exports2.computeRefundDigestWithQuoteHash = exports2.buildRefundTypedDataWithQuoteHash = exports2.computeReleaseDigestWithQuoteHash = exports2.buildReleaseTypedDataWithQuoteHash = exports2.computeReserveDigestWithQuoteSource = exports2.buildReserveTypedDataWithQuoteSource = exports2.computeReserveDigest = exports2.ESCROW_V3_ABI_JSON = exports2.ESCROW_V2_ABI_JSON = exports2.ESCROW_ABI_JSON = exports2.ESCROW_ABI = exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH = exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH = exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE = exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION = exports2.REFUND_WITNESS_TYPES = exports2.RELEASE_WITNESS_TYPES = exports2.RESERVE_WITNESS_TYPES = exports2.createEscrowDomain = exports2.createPermit2Domain = exports2.PERMIT_WITNESS_TYPES_V2 = exports2.PERMIT_WITNESS_TYPES = exports2.generateNonce = exports2.computePaymentIdV2 = exports2.computePaymentId = void 0;
809
1663
  var payment_id_1 = require_payment_id2();
810
1664
  Object.defineProperty(exports2, "computePaymentId", { enumerable: true, get: function() {
811
1665
  return payment_id_1.computePaymentId;
@@ -839,6 +1693,19 @@ var require_dist2 = __commonJS({
839
1693
  Object.defineProperty(exports2, "REFUND_WITNESS_TYPES", { enumerable: true, get: function() {
840
1694
  return permit_types_1.REFUND_WITNESS_TYPES;
841
1695
  } });
1696
+ var permit_types_2 = require_permit_types();
1697
+ Object.defineProperty(exports2, "PERMIT_WITNESS_TYPES_WITH_DESTINATION", { enumerable: true, get: function() {
1698
+ return permit_types_2.PERMIT_WITNESS_TYPES_WITH_DESTINATION;
1699
+ } });
1700
+ Object.defineProperty(exports2, "RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE", { enumerable: true, get: function() {
1701
+ return permit_types_2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE;
1702
+ } });
1703
+ Object.defineProperty(exports2, "RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH", { enumerable: true, get: function() {
1704
+ return permit_types_2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH;
1705
+ } });
1706
+ Object.defineProperty(exports2, "REFUND_WITNESS_TYPES_WITH_QUOTE_HASH", { enumerable: true, get: function() {
1707
+ return permit_types_2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH;
1708
+ } });
842
1709
  var escrow_abi_1 = require_escrow_abi();
843
1710
  Object.defineProperty(exports2, "ESCROW_ABI", { enumerable: true, get: function() {
844
1711
  return escrow_abi_1.ESCROW_ABI;
@@ -856,6 +1723,27 @@ var require_dist2 = __commonJS({
856
1723
  Object.defineProperty(exports2, "computeReserveDigest", { enumerable: true, get: function() {
857
1724
  return reserve_encoder_1.computeReserveDigest;
858
1725
  } });
1726
+ var reserve_encoder_2 = require_reserve_encoder2();
1727
+ Object.defineProperty(exports2, "buildReserveTypedDataWithQuoteSource", { enumerable: true, get: function() {
1728
+ return reserve_encoder_2.buildReserveTypedDataWithQuoteSource;
1729
+ } });
1730
+ Object.defineProperty(exports2, "computeReserveDigestWithQuoteSource", { enumerable: true, get: function() {
1731
+ return reserve_encoder_2.computeReserveDigestWithQuoteSource;
1732
+ } });
1733
+ var release_encoder_1 = require_release_encoder2();
1734
+ Object.defineProperty(exports2, "buildReleaseTypedDataWithQuoteHash", { enumerable: true, get: function() {
1735
+ return release_encoder_1.buildReleaseTypedDataWithQuoteHash;
1736
+ } });
1737
+ Object.defineProperty(exports2, "computeReleaseDigestWithQuoteHash", { enumerable: true, get: function() {
1738
+ return release_encoder_1.computeReleaseDigestWithQuoteHash;
1739
+ } });
1740
+ var refund_encoder_1 = require_refund_encoder2();
1741
+ Object.defineProperty(exports2, "buildRefundTypedDataWithQuoteHash", { enumerable: true, get: function() {
1742
+ return refund_encoder_1.buildRefundTypedDataWithQuoteHash;
1743
+ } });
1744
+ Object.defineProperty(exports2, "computeRefundDigestWithQuoteHash", { enumerable: true, get: function() {
1745
+ return refund_encoder_1.computeRefundDigestWithQuoteHash;
1746
+ } });
859
1747
  var deposit_encoder_1 = require_deposit_encoder2();
860
1748
  Object.defineProperty(exports2, "createPermitWitnessTransferFromPrehash", { enumerable: true, get: function() {
861
1749
  return deposit_encoder_1.createPermitWitnessTransferFromPrehash;
@@ -866,6 +1754,13 @@ var require_dist2 = __commonJS({
866
1754
  Object.defineProperty(exports2, "PERMIT2_CONTRACT_ADDRESS", { enumerable: true, get: function() {
867
1755
  return deposit_encoder_1.PERMIT2_CONTRACT_ADDRESS;
868
1756
  } });
1757
+ var deposit_encoder_2 = require_deposit_encoder2();
1758
+ Object.defineProperty(exports2, "createPermitWitnessTransferFromPrehashWithDestination", { enumerable: true, get: function() {
1759
+ return deposit_encoder_2.createPermitWitnessTransferFromPrehashWithDestination;
1760
+ } });
1761
+ Object.defineProperty(exports2, "MAX_DESTINATION_BYTES", { enumerable: true, get: function() {
1762
+ return deposit_encoder_2.MAX_DESTINATION_BYTES;
1763
+ } });
869
1764
  }
870
1765
  });
871
1766
 
@@ -906,24 +1801,25 @@ var require_evm = __commonJS({
906
1801
  Object.defineProperty(exports2, "__esModule", { value: true });
907
1802
  exports2.evmAdapter = void 0;
908
1803
  var ethers_1 = require("ethers");
909
- var evm_escrow_encoding_1 = require_dist2();
1804
+ var evm_escrow_encoding_1 = require_dist3();
910
1805
  var utils_js_1 = require_utils();
1806
+ var destination_js_1 = require_destination();
911
1807
  var errors_js_1 = require_errors();
912
1808
  var chain_id_js_1 = require_chain_id2();
913
1809
  exports2.evmAdapter = {
914
- async buildAuthMessage({ sourceAsset, maxSourceAmount, sourceDefaults, deadline, nonce }) {
1810
+ async buildAuthMessage({ sourceAsset, maxSourceAmount, requestId, sourceDefaults, destinationAsset, destinationAccount, deadline, nonce }) {
915
1811
  if (nonce === void 0) {
916
1812
  throw new Error("sender_auth: buildAuthMessage requires an explicit nonce \u2014 derive it deterministically from a stable request id (e.g. an order id) so retries reproduce the same permit; pass generatePermitNonce() only for genuinely one-shot builds");
917
1813
  }
918
1814
  if (deadline === void 0) {
919
1815
  throw new Error("sender_auth: buildAuthMessage requires an explicit permit deadline (absolute Unix seconds) \u2014 the low-level builder does not default it; derive it from the payment's fulfillment/settlement deadline in the calling layer (pgc/mppx)");
920
1816
  }
921
- const sourceChainId = sourceAsset.split("/")[0];
922
- const chainIdNum = parseInt(sourceChainId.split(":")[1]);
923
- const tokenAddress = sourceAsset.split("/")[1].split(":")[1];
924
- const permitParams = {
1817
+ const { network: sourceChainId, asset: tokenAddress } = (0, utils_js_1.parseSourceAsset)(sourceAsset);
1818
+ const chainIdNum = (0, chain_id_js_1.evmChainId)(sourceChainId);
1819
+ const permit2Contract = sourceDefaults.permit2Contract ?? evm_escrow_encoding_1.PERMIT2_CONTRACT_ADDRESS;
1820
+ const basePermit = {
925
1821
  chainId: chainIdNum,
926
- verifyingContract: evm_escrow_encoding_1.PERMIT2_CONTRACT_ADDRESS,
1822
+ verifyingContract: permit2Contract,
927
1823
  token: tokenAddress,
928
1824
  amount: maxSourceAmount,
929
1825
  spender: sourceDefaults.escrowContract,
@@ -932,7 +1828,21 @@ var require_evm = __commonJS({
932
1828
  reserver: sourceDefaults.quoteSelector,
933
1829
  releaser: sourceDefaults.fulfillmentVerifierAccount
934
1830
  };
935
- const messagePrehash = (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehash)(permitParams);
1831
+ if ((0, destination_js_1.usesDestinationCommitment)(sourceDefaults.depositWitnessVersion)) {
1832
+ const permitParams = {
1833
+ ...basePermit,
1834
+ // The two escrow commitments. Composed here through the shared helpers rather than
1835
+ // accepted pre-built, so this producer and the release signer cannot disagree about
1836
+ // formatting — a disagreement the escrow cannot detect, because it stores only
1837
+ // keccak256(bytes(destination)).
1838
+ depositRequestHash: (0, destination_js_1.deriveDepositRequestHash)(requestId),
1839
+ destination: (0, destination_js_1.buildEscrowDestination)(destinationAsset, destinationAccount)
1840
+ };
1841
+ const messagePrehash2 = (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehashWithDestination)(permitParams);
1842
+ const messageHash2 = (0, evm_escrow_encoding_1.hashPermitWitnessTransferFrom)(messagePrehash2);
1843
+ return { messageScheme: "EVM_PERMIT2", messageHash: messageHash2, messagePrehash: JSON.stringify(messagePrehash2) };
1844
+ }
1845
+ const messagePrehash = (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehash)(basePermit);
936
1846
  const messageHash = (0, evm_escrow_encoding_1.hashPermitWitnessTransferFrom)(messagePrehash);
937
1847
  return { messageScheme: "EVM_PERMIT2", messageHash, messagePrehash: JSON.stringify(messagePrehash) };
938
1848
  },
@@ -965,17 +1875,31 @@ var require_evm = __commonJS({
965
1875
  let msg;
966
1876
  try {
967
1877
  msg = JSON.parse(signed.message_prehash).message;
968
- canonical = (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehash)({
1878
+ const base = {
969
1879
  chainId: (0, chain_id_js_1.evmChainId)(source.network),
970
- verifyingContract: evm_escrow_encoding_1.PERMIT2_CONTRACT_ADDRESS,
1880
+ // The same Permit2 buildAuthMessage signed against. Taken from the VERIFIER's
1881
+ // expectations, never from msg — the prehash is client-supplied, so reading the domain
1882
+ // out of it would let a caller nominate its own verifying contract and have the
1883
+ // signature check itself. Absent means canonical, matching the build side's default.
1884
+ verifyingContract: expected.permit2Contract ?? evm_escrow_encoding_1.PERMIT2_CONTRACT_ADDRESS,
971
1885
  token: msg.permitted.token,
972
1886
  amount: msg.permitted.amount,
973
1887
  spender: msg.spender,
974
1888
  nonce: BigInt(msg.nonce),
975
1889
  deadline: BigInt(msg.deadline),
976
- reserver: msg.witness.reserver,
977
- releaser: msg.witness.releaser
978
- });
1890
+ reserver: msg.witness?.reserver,
1891
+ releaser: msg.witness?.releaser
1892
+ };
1893
+ const hasHash = typeof msg.witness?.depositRequestHash === "string";
1894
+ const hasDestination = typeof msg.witness?.destination === "string";
1895
+ if (hasHash !== hasDestination) {
1896
+ throw new Error("half-populated deposit witness");
1897
+ }
1898
+ canonical = hasHash ? (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehashWithDestination)({
1899
+ ...base,
1900
+ depositRequestHash: msg.witness.depositRequestHash,
1901
+ destination: msg.witness.destination
1902
+ }) : (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehash)(base);
979
1903
  } catch {
980
1904
  throw new errors_js_1.MalformedPrehashError();
981
1905
  }
@@ -999,6 +1923,12 @@ var require_evm = __commonJS({
999
1923
  if (expected.reserver !== void 0 && expected.releaser !== void 0) {
1000
1924
  (0, utils_js_1.assertWitnessRoles)(msg.witness.reserver, msg.witness.releaser, expected.reserver, expected.releaser, (a) => a);
1001
1925
  }
1926
+ if (expected.destination !== void 0) {
1927
+ (0, utils_js_1.assertDestination)(msg.witness.destination, expected.destination);
1928
+ }
1929
+ if (expected.requestId !== void 0) {
1930
+ (0, utils_js_1.assertDepositRequestHash)(msg.witness.depositRequestHash, expected.requestId);
1931
+ }
1002
1932
  return {
1003
1933
  amount: msg.permitted.amount,
1004
1934
  deadlineSec,
@@ -1009,7 +1939,11 @@ var require_evm = __commonJS({
1009
1939
  deadlineSec,
1010
1940
  reserver: msg.witness.reserver,
1011
1941
  releaser: msg.witness.releaser,
1012
- spender: msg.spender
1942
+ spender: msg.spender,
1943
+ // Surfaced whether or not the opt-in checks above ran, so a consumer binding these
1944
+ // downstream does not have to re-parse message_prehash and risk drifting from this parse.
1945
+ destination: msg.witness.destination,
1946
+ depositRequestHash: msg.witness.depositRequestHash
1013
1947
  }
1014
1948
  };
1015
1949
  }
@@ -1028,18 +1962,18 @@ var require_tron = __commonJS({
1028
1962
  var utils_js_1 = require_utils();
1029
1963
  var errors_js_1 = require_errors();
1030
1964
  var chain_id_js_1 = require_chain_id2();
1965
+ var destination_js_1 = require_destination();
1031
1966
  exports2.tronAdapter = {
1032
- async buildAuthMessage({ sourceAsset, maxSourceAmount, sourceDefaults, deadline, nonce }) {
1967
+ async buildAuthMessage({ sourceAsset, maxSourceAmount, requestId, sourceDefaults, destinationAsset, destinationAccount, deadline, nonce }) {
1033
1968
  if (nonce === void 0) {
1034
1969
  throw new Error("sender_auth: buildAuthMessage requires an explicit nonce \u2014 derive it deterministically from a stable request id (e.g. an order id) so retries reproduce the same permit; pass generatePermitNonce() only for genuinely one-shot builds");
1035
1970
  }
1036
1971
  if (deadline === void 0) {
1037
1972
  throw new Error("sender_auth: buildAuthMessage requires an explicit permit deadline (absolute Unix seconds) \u2014 the low-level builder does not default it; derive it from the payment's fulfillment/settlement deadline in the calling layer (pgc/mppx)");
1038
1973
  }
1039
- const sourceChainId = sourceAsset.split("/")[0];
1040
- const tokenAddress = sourceAsset.split("/")[1].split(":")[1];
1974
+ const { network: sourceChainId, asset: tokenAddress } = (0, utils_js_1.parseSourceAsset)(sourceAsset);
1041
1975
  const permit2Address = sourceDefaults.permit2Contract ?? (0, chain_id_js_1.resolveTronPermit2)(sourceChainId);
1042
- const tvmParams = {
1976
+ const baseParams = {
1043
1977
  chainId: (0, chain_id_js_1.tronNumericChainId)(sourceChainId),
1044
1978
  permit2Address,
1045
1979
  tokenAddress,
@@ -1050,7 +1984,21 @@ var require_tron = __commonJS({
1050
1984
  reserverAddress: sourceDefaults.quoteSelector,
1051
1985
  releaserAddress: sourceDefaults.fulfillmentVerifierAccount
1052
1986
  };
1053
- const messagePrehash = (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehash)(tvmParams);
1987
+ if ((0, destination_js_1.usesDestinationCommitment)(sourceDefaults.depositWitnessVersion)) {
1988
+ const tvmParams = {
1989
+ ...baseParams,
1990
+ // The two commitments, composed through the shared helpers rather than accepted
1991
+ // pre-built, so this producer and the Go release signer cannot disagree about
1992
+ // formatting — a disagreement the escrow cannot detect, because it stores only
1993
+ // keccak256(bytes(destination)).
1994
+ depositRequestHash: (0, destination_js_1.deriveDepositRequestHash)(requestId),
1995
+ destination: (0, destination_js_1.buildEscrowDestination)(destinationAsset, destinationAccount)
1996
+ };
1997
+ const messagePrehash2 = (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehashWithDestination)(tvmParams);
1998
+ const messageHash2 = (0, tvm_escrow_encoding_1.hashTvmPermitWitnessTransferFrom)(messagePrehash2);
1999
+ return { messageScheme: "EVM_PERMIT2", messageHash: messageHash2, messagePrehash: JSON.stringify(messagePrehash2) };
2000
+ }
2001
+ const messagePrehash = (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehash)(baseParams);
1054
2002
  const messageHash = (0, tvm_escrow_encoding_1.hashTvmPermitWitnessTransferFrom)(messagePrehash);
1055
2003
  return { messageScheme: "EVM_PERMIT2", messageHash, messagePrehash: JSON.stringify(messagePrehash) };
1056
2004
  },
@@ -1085,17 +2033,31 @@ var require_tron = __commonJS({
1085
2033
  let digest;
1086
2034
  try {
1087
2035
  msg = JSON.parse(signed.message_prehash).message;
1088
- const canonical = (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehash)({
2036
+ const base = {
1089
2037
  chainId: (0, chain_id_js_1.tronNumericChainId)(source.network),
1090
- permit2Address: (0, chain_id_js_1.resolveTronPermit2)(source.network),
2038
+ // The same Permit2 buildAuthMessage signed against, taken from the VERIFIER's
2039
+ // expectations rather than from msg — the prehash is payer-supplied, so reading the
2040
+ // domain out of it would let a caller nominate its own verifying contract. Absent means
2041
+ // the pinned per-chain address, matching the build side's default.
2042
+ permit2Address: expected.permit2Contract ?? (0, chain_id_js_1.resolveTronPermit2)(source.network),
1091
2043
  tokenAddress: msg.permitted.token,
1092
2044
  amount: msg.permitted.amount,
1093
2045
  spenderAddress: msg.spender,
1094
2046
  nonce: BigInt(msg.nonce),
1095
2047
  deadline: BigInt(msg.deadline),
1096
- reserverAddress: msg.witness.reserver,
1097
- releaserAddress: msg.witness.releaser
1098
- });
2048
+ reserverAddress: msg.witness?.reserver,
2049
+ releaserAddress: msg.witness?.releaser
2050
+ };
2051
+ const hasHash = typeof msg.witness?.depositRequestHash === "string";
2052
+ const hasDestination = typeof msg.witness?.destination === "string";
2053
+ if (hasHash !== hasDestination) {
2054
+ throw new Error("half-populated witness");
2055
+ }
2056
+ const canonical = hasHash ? (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehashWithDestination)({
2057
+ ...base,
2058
+ depositRequestHash: msg.witness.depositRequestHash,
2059
+ destination: msg.witness.destination
2060
+ }) : (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehash)(base);
1099
2061
  digest = (0, tvm_escrow_encoding_1.hashTvmPermitWitnessTransferFrom)(canonical);
1100
2062
  } catch {
1101
2063
  throw new errors_js_1.MalformedPrehashError();
@@ -1143,7 +2105,7 @@ var require_errors2 = __commonJS({
1143
2105
  "../contracts/svm/escrow-encoding/typescript/dist/errors.js"(exports2) {
1144
2106
  "use strict";
1145
2107
  Object.defineProperty(exports2, "__esModule", { value: true });
1146
- exports2.InvalidHexError = exports2.InvalidBase58Error = exports2.InvalidPubkeyLengthError = exports2.ZeroDepositHashError = exports2.ZeroRecipientError = exports2.ZeroReleaserError = exports2.ZeroReserverError = exports2.ZeroAmountError = exports2.ZeroMintError = exports2.ZeroDepositorError = exports2.ZeroPaymentIdError = exports2.EncodingError = void 0;
2108
+ exports2.DestinationTooLongError = exports2.EmptyDestinationError = exports2.ZeroSourceAmountError = exports2.ZeroQuoteHashError = exports2.InvalidHexError = exports2.InvalidBase58Error = exports2.InvalidPubkeyLengthError = exports2.ZeroDepositHashError = exports2.ZeroRecipientError = exports2.ZeroReleaserError = exports2.ZeroReserverError = exports2.ZeroAmountError = exports2.ZeroMintError = exports2.ZeroDepositorError = exports2.ZeroDepositRequestHashError = exports2.EncodingError = void 0;
1147
2109
  var EncodingError = class extends Error {
1148
2110
  constructor(message) {
1149
2111
  super(message);
@@ -1151,13 +2113,13 @@ var require_errors2 = __commonJS({
1151
2113
  }
1152
2114
  };
1153
2115
  exports2.EncodingError = EncodingError;
1154
- var ZeroPaymentIdError = class extends EncodingError {
2116
+ var ZeroDepositRequestHashError = class extends EncodingError {
1155
2117
  constructor() {
1156
- super("payment ID cannot be zero");
1157
- this.name = "ZeroPaymentIdError";
2118
+ super("deposit request hash cannot be zero");
2119
+ this.name = "ZeroDepositRequestHashError";
1158
2120
  }
1159
2121
  };
1160
- exports2.ZeroPaymentIdError = ZeroPaymentIdError;
2122
+ exports2.ZeroDepositRequestHashError = ZeroDepositRequestHashError;
1161
2123
  var ZeroDepositorError = class extends EncodingError {
1162
2124
  constructor() {
1163
2125
  super("depositor cannot be zero");
@@ -1213,21 +2175,49 @@ var require_errors2 = __commonJS({
1213
2175
  this.name = "InvalidPubkeyLengthError";
1214
2176
  }
1215
2177
  };
1216
- exports2.InvalidPubkeyLengthError = InvalidPubkeyLengthError;
1217
- var InvalidBase58Error = class extends EncodingError {
2178
+ exports2.InvalidPubkeyLengthError = InvalidPubkeyLengthError;
2179
+ var InvalidBase58Error = class extends EncodingError {
2180
+ constructor() {
2181
+ super("invalid base58 encoding");
2182
+ this.name = "InvalidBase58Error";
2183
+ }
2184
+ };
2185
+ exports2.InvalidBase58Error = InvalidBase58Error;
2186
+ var InvalidHexError = class extends EncodingError {
2187
+ constructor() {
2188
+ super("invalid hex encoding");
2189
+ this.name = "InvalidHexError";
2190
+ }
2191
+ };
2192
+ exports2.InvalidHexError = InvalidHexError;
2193
+ var ZeroQuoteHashError = class extends EncodingError {
2194
+ constructor() {
2195
+ super("quote hash cannot be zero");
2196
+ this.name = "ZeroQuoteHashError";
2197
+ }
2198
+ };
2199
+ exports2.ZeroQuoteHashError = ZeroQuoteHashError;
2200
+ var ZeroSourceAmountError = class extends EncodingError {
2201
+ constructor() {
2202
+ super("source amount cannot be zero");
2203
+ this.name = "ZeroSourceAmountError";
2204
+ }
2205
+ };
2206
+ exports2.ZeroSourceAmountError = ZeroSourceAmountError;
2207
+ var EmptyDestinationError = class extends EncodingError {
1218
2208
  constructor() {
1219
- super("invalid base58 encoding");
1220
- this.name = "InvalidBase58Error";
2209
+ super("destination cannot be empty");
2210
+ this.name = "EmptyDestinationError";
1221
2211
  }
1222
2212
  };
1223
- exports2.InvalidBase58Error = InvalidBase58Error;
1224
- var InvalidHexError = class extends EncodingError {
2213
+ exports2.EmptyDestinationError = EmptyDestinationError;
2214
+ var DestinationTooLongError = class extends EncodingError {
1225
2215
  constructor() {
1226
- super("invalid hex encoding");
1227
- this.name = "InvalidHexError";
2216
+ super("destination exceeds the maximum length");
2217
+ this.name = "DestinationTooLongError";
1228
2218
  }
1229
2219
  };
1230
- exports2.InvalidHexError = InvalidHexError;
2220
+ exports2.DestinationTooLongError = DestinationTooLongError;
1231
2221
  }
1232
2222
  });
1233
2223
 
@@ -1242,7 +2232,7 @@ var require_pubkey = __commonJS({
1242
2232
  exports2.Pubkey = void 0;
1243
2233
  var bs58_1 = __importDefault(require("bs58"));
1244
2234
  var errors_1 = require_errors2();
1245
- var Pubkey2 = class _Pubkey {
2235
+ var Pubkey = class _Pubkey {
1246
2236
  constructor(data) {
1247
2237
  if (data.length !== 32) {
1248
2238
  throw new errors_1.InvalidPubkeyLengthError();
@@ -1335,7 +2325,7 @@ var require_pubkey = __commonJS({
1335
2325
  return this.data.every((b, i) => b === other.data[i]);
1336
2326
  }
1337
2327
  };
1338
- exports2.Pubkey = Pubkey2;
2328
+ exports2.Pubkey = Pubkey;
1339
2329
  }
1340
2330
  });
1341
2331
 
@@ -1958,13 +2948,36 @@ var require_deposit_encoder3 = __commonJS({
1958
2948
  "../contracts/svm/escrow-encoding/typescript/dist/deposit-encoder.js"(exports2) {
1959
2949
  "use strict";
1960
2950
  Object.defineProperty(exports2, "__esModule", { value: true });
1961
- exports2.computeDepositHash = computeDepositHash2;
2951
+ exports2.MAX_DESTINATION_LEN = void 0;
2952
+ exports2.computeDepositHash = computeDepositHash;
2953
+ exports2.computeDestinationHash = computeDestinationHash;
2954
+ exports2.computeDepositHashV2 = computeDepositHashV2;
1962
2955
  var encoding_utils_1 = require_encoding_utils();
1963
2956
  var escrow_domain_1 = require_escrow_domain();
1964
2957
  var errors_1 = require_errors2();
1965
- function computeDepositHash2(params, domain) {
1966
- if (params.paymentId.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.paymentId)) {
1967
- throw new errors_1.ZeroPaymentIdError();
2958
+ function computeDepositHash(params, domain) {
2959
+ if (params.depositRequestHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositRequestHash)) {
2960
+ throw new errors_1.ZeroDepositRequestHashError();
2961
+ }
2962
+ if (params.depositor.isZero())
2963
+ throw new errors_1.ZeroDepositorError();
2964
+ if (params.mint.isZero())
2965
+ throw new errors_1.ZeroMintError();
2966
+ if (params.amount === 0n)
2967
+ throw new errors_1.ZeroAmountError();
2968
+ if (params.reserver.isZero())
2969
+ throw new errors_1.ZeroReserverError();
2970
+ if (params.releaser.isZero())
2971
+ throw new errors_1.ZeroReleaserError();
2972
+ return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("deposit"), params.depositRequestHash, params.depositor.toBytes(), params.mint.toBytes(), (0, encoding_utils_1.encodeU64LE)(params.amount), params.reserver.toBytes(), params.releaser.toBytes(), (0, encoding_utils_1.encodeU64LE)(params.nonce), (0, encoding_utils_1.encodeU64LE)(params.issuedAt), (0, encoding_utils_1.encodeU64LE)(params.deadline));
2973
+ }
2974
+ exports2.MAX_DESTINATION_LEN = 256;
2975
+ function computeDestinationHash(destination) {
2976
+ return (0, encoding_utils_1.keccak256)((0, encoding_utils_1.stringToBytes)(destination));
2977
+ }
2978
+ function computeDepositHashV2(params, destination, domain) {
2979
+ if (params.depositRequestHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositRequestHash)) {
2980
+ throw new errors_1.ZeroDepositRequestHashError();
1968
2981
  }
1969
2982
  if (params.depositor.isZero())
1970
2983
  throw new errors_1.ZeroDepositorError();
@@ -1976,7 +2989,28 @@ var require_deposit_encoder3 = __commonJS({
1976
2989
  throw new errors_1.ZeroReserverError();
1977
2990
  if (params.releaser.isZero())
1978
2991
  throw new errors_1.ZeroReleaserError();
1979
- return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("deposit"), params.paymentId, params.depositor.toBytes(), params.mint.toBytes(), (0, encoding_utils_1.encodeU64LE)(params.amount), params.reserver.toBytes(), params.releaser.toBytes(), (0, encoding_utils_1.encodeU64LE)(params.nonce), (0, encoding_utils_1.encodeU64LE)(params.issuedAt), (0, encoding_utils_1.encodeU64LE)(params.deadline));
2992
+ if (destination.length === 0)
2993
+ throw new errors_1.EmptyDestinationError();
2994
+ if ((0, encoding_utils_1.stringToBytes)(destination).length > exports2.MAX_DESTINATION_LEN) {
2995
+ throw new errors_1.DestinationTooLongError();
2996
+ }
2997
+ return (0, encoding_utils_1.keccak256)(
2998
+ ...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain),
2999
+ (0, encoding_utils_1.stringToBytes)("deposit"),
3000
+ params.depositRequestHash,
3001
+ // Hash first: keccak256 concatenates without length prefixes, so injectivity depends on every
3002
+ // hashed field being fixed-width. Feeding the raw string would make it conditional on the
3003
+ // surrounding widths and diverge from the on-chain program, which hashes it too.
3004
+ computeDestinationHash(destination),
3005
+ params.depositor.toBytes(),
3006
+ params.mint.toBytes(),
3007
+ (0, encoding_utils_1.encodeU64LE)(params.amount),
3008
+ params.reserver.toBytes(),
3009
+ params.releaser.toBytes(),
3010
+ (0, encoding_utils_1.encodeU64LE)(params.nonce),
3011
+ (0, encoding_utils_1.encodeU64LE)(params.issuedAt),
3012
+ (0, encoding_utils_1.encodeU64LE)(params.deadline)
3013
+ );
1980
3014
  }
1981
3015
  }
1982
3016
  });
@@ -1987,6 +3021,8 @@ var require_reserve_encoder3 = __commonJS({
1987
3021
  "use strict";
1988
3022
  Object.defineProperty(exports2, "__esModule", { value: true });
1989
3023
  exports2.computeReserveHash = computeReserveHash;
3024
+ exports2.computeReserveHashV2 = computeReserveHashV2;
3025
+ exports2.computeReserveHashV3 = computeReserveHashV3;
1990
3026
  var encoding_utils_1 = require_encoding_utils();
1991
3027
  var escrow_domain_1 = require_escrow_domain();
1992
3028
  var errors_1 = require_errors2();
@@ -1998,15 +3034,38 @@ var require_reserve_encoder3 = __commonJS({
1998
3034
  throw new errors_1.ZeroRecipientError();
1999
3035
  return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("reserve"), params.recipient.toBytes(), params.depositHash);
2000
3036
  }
3037
+ function computeReserveHashV2(params, quoteHash, domain) {
3038
+ if (params.depositHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositHash)) {
3039
+ throw new errors_1.ZeroDepositHashError();
3040
+ }
3041
+ if (params.recipient.isZero())
3042
+ throw new errors_1.ZeroRecipientError();
3043
+ if (quoteHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(quoteHash))
3044
+ throw new errors_1.ZeroQuoteHashError();
3045
+ return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("reserve"), params.recipient.toBytes(), params.depositHash, quoteHash);
3046
+ }
3047
+ function computeReserveHashV3(params, quoteHash, sourceAmount, domain) {
3048
+ if (params.depositHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositHash)) {
3049
+ throw new errors_1.ZeroDepositHashError();
3050
+ }
3051
+ if (params.recipient.isZero())
3052
+ throw new errors_1.ZeroRecipientError();
3053
+ if (quoteHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(quoteHash))
3054
+ throw new errors_1.ZeroQuoteHashError();
3055
+ if (sourceAmount === 0n)
3056
+ throw new errors_1.ZeroSourceAmountError();
3057
+ return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("reserve"), params.recipient.toBytes(), params.depositHash, quoteHash, (0, encoding_utils_1.encodeU64LE)(sourceAmount));
3058
+ }
2001
3059
  }
2002
3060
  });
2003
3061
 
2004
3062
  // ../contracts/svm/escrow-encoding/typescript/dist/release-encoder.js
2005
- var require_release_encoder = __commonJS({
3063
+ var require_release_encoder3 = __commonJS({
2006
3064
  "../contracts/svm/escrow-encoding/typescript/dist/release-encoder.js"(exports2) {
2007
3065
  "use strict";
2008
3066
  Object.defineProperty(exports2, "__esModule", { value: true });
2009
3067
  exports2.computeReleaseHash = computeReleaseHash;
3068
+ exports2.computeReleaseHashV2 = computeReleaseHashV2;
2010
3069
  var encoding_utils_1 = require_encoding_utils();
2011
3070
  var escrow_domain_1 = require_escrow_domain();
2012
3071
  var errors_1 = require_errors2();
@@ -2016,15 +3075,22 @@ var require_release_encoder = __commonJS({
2016
3075
  }
2017
3076
  return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("release"), params.depositHash);
2018
3077
  }
3078
+ function computeReleaseHashV2(params, quoteHash, domain) {
3079
+ if (params.depositHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositHash)) {
3080
+ throw new errors_1.ZeroDepositHashError();
3081
+ }
3082
+ return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("release"), params.depositHash, quoteHash);
3083
+ }
2019
3084
  }
2020
3085
  });
2021
3086
 
2022
3087
  // ../contracts/svm/escrow-encoding/typescript/dist/refund-encoder.js
2023
- var require_refund_encoder = __commonJS({
3088
+ var require_refund_encoder3 = __commonJS({
2024
3089
  "../contracts/svm/escrow-encoding/typescript/dist/refund-encoder.js"(exports2) {
2025
3090
  "use strict";
2026
3091
  Object.defineProperty(exports2, "__esModule", { value: true });
2027
3092
  exports2.computeRefundHash = computeRefundHash;
3093
+ exports2.computeRefundHashV2 = computeRefundHashV2;
2028
3094
  var encoding_utils_1 = require_encoding_utils();
2029
3095
  var escrow_domain_1 = require_escrow_domain();
2030
3096
  var errors_1 = require_errors2();
@@ -2034,6 +3100,12 @@ var require_refund_encoder = __commonJS({
2034
3100
  }
2035
3101
  return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("refund"), params.depositHash);
2036
3102
  }
3103
+ function computeRefundHashV2(params, quoteHash, domain) {
3104
+ if (params.depositHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositHash)) {
3105
+ throw new errors_1.ZeroDepositHashError();
3106
+ }
3107
+ return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("refund"), params.depositHash, quoteHash);
3108
+ }
2037
3109
  }
2038
3110
  });
2039
3111
 
@@ -2042,16 +3114,16 @@ var require_nonce_generator2 = __commonJS({
2042
3114
  "../contracts/svm/escrow-encoding/typescript/dist/nonce-generator.js"(exports2) {
2043
3115
  "use strict";
2044
3116
  Object.defineProperty(exports2, "__esModule", { value: true });
2045
- exports2.MAX_VALID_SLOT = exports2.REPLAY_SLOTS = void 0;
3117
+ exports2.REPLAY_BUCKETS = exports2.MAX_VALID_SLOT = exports2.REPLAY_SLOTS = exports2.DEPOSIT_COMPUTE_UNIT_LIMIT = void 0;
2046
3118
  exports2.generateNonce = generateNonce2;
2047
3119
  var crypto_1 = require("crypto");
3120
+ exports2.DEPOSIT_COMPUTE_UNIT_LIMIT = 4e5;
2048
3121
  exports2.REPLAY_SLOTS = 235;
2049
3122
  exports2.MAX_VALID_SLOT = exports2.REPLAY_SLOTS - 1;
2050
- var NONCE_BUCKET_MASK = 131071;
3123
+ exports2.REPLAY_BUCKETS = 256;
2051
3124
  var NONCE_BUCKET_SHIFT = 32n;
2052
3125
  function generateNonce2() {
2053
- const bucketBytes = (0, crypto_1.randomBytes)(4);
2054
- const bucketID = bucketBytes.readUInt32LE(0) & NONCE_BUCKET_MASK;
3126
+ const bucketID = (0, crypto_1.randomBytes)(4).readUInt32LE(0) % exports2.REPLAY_BUCKETS;
2055
3127
  let slot;
2056
3128
  do {
2057
3129
  slot = (0, crypto_1.randomBytes)(1)[0];
@@ -2062,11 +3134,11 @@ var require_nonce_generator2 = __commonJS({
2062
3134
  });
2063
3135
 
2064
3136
  // ../contracts/svm/escrow-encoding/typescript/dist/index.js
2065
- var require_dist3 = __commonJS({
3137
+ var require_dist4 = __commonJS({
2066
3138
  "../contracts/svm/escrow-encoding/typescript/dist/index.js"(exports2) {
2067
3139
  "use strict";
2068
3140
  Object.defineProperty(exports2, "__esModule", { value: true });
2069
- exports2.MAX_VALID_SLOT = exports2.REPLAY_SLOTS = exports2.generateNonce = exports2.computeRefundHash = exports2.computeReleaseHash = exports2.computeReserveHash = exports2.computeDepositHash = exports2.InvalidHexError = exports2.InvalidBase58Error = exports2.InvalidPubkeyLengthError = exports2.ZeroDepositHashError = exports2.ZeroRecipientError = exports2.ZeroReleaserError = exports2.ZeroReserverError = exports2.ZeroAmountError = exports2.ZeroMintError = exports2.ZeroDepositorError = exports2.ZeroPaymentIdError = exports2.EncodingError = exports2.escrowDomainPrefixBytes = exports2.isZeroBytes32 = exports2.stringToBytes = exports2.keccak256 = exports2.encodeU64LE = exports2.Pubkey = void 0;
3141
+ exports2.DEPOSIT_COMPUTE_UNIT_LIMIT = exports2.REPLAY_BUCKETS = exports2.MAX_VALID_SLOT = exports2.REPLAY_SLOTS = exports2.generateNonce = exports2.computeRefundHashV2 = exports2.computeRefundHash = exports2.computeReleaseHashV2 = exports2.computeReleaseHash = exports2.computeReserveHashV3 = exports2.computeReserveHashV2 = exports2.computeReserveHash = exports2.MAX_DESTINATION_LEN = exports2.computeDestinationHash = exports2.computeDepositHashV2 = exports2.computeDepositHash = exports2.InvalidHexError = exports2.InvalidBase58Error = exports2.InvalidPubkeyLengthError = exports2.ZeroDepositHashError = exports2.ZeroRecipientError = exports2.ZeroReleaserError = exports2.ZeroReserverError = exports2.ZeroAmountError = exports2.ZeroMintError = exports2.ZeroDepositorError = exports2.DestinationTooLongError = exports2.EmptyDestinationError = exports2.ZeroQuoteHashError = exports2.ZeroDepositRequestHashError = exports2.EncodingError = exports2.escrowDomainPrefixBytes = exports2.isZeroBytes32 = exports2.stringToBytes = exports2.keccak256 = exports2.encodeU64LE = exports2.Pubkey = void 0;
2070
3142
  var pubkey_1 = require_pubkey();
2071
3143
  Object.defineProperty(exports2, "Pubkey", { enumerable: true, get: function() {
2072
3144
  return pubkey_1.Pubkey;
@@ -2092,8 +3164,17 @@ var require_dist3 = __commonJS({
2092
3164
  Object.defineProperty(exports2, "EncodingError", { enumerable: true, get: function() {
2093
3165
  return errors_1.EncodingError;
2094
3166
  } });
2095
- Object.defineProperty(exports2, "ZeroPaymentIdError", { enumerable: true, get: function() {
2096
- return errors_1.ZeroPaymentIdError;
3167
+ Object.defineProperty(exports2, "ZeroDepositRequestHashError", { enumerable: true, get: function() {
3168
+ return errors_1.ZeroDepositRequestHashError;
3169
+ } });
3170
+ Object.defineProperty(exports2, "ZeroQuoteHashError", { enumerable: true, get: function() {
3171
+ return errors_1.ZeroQuoteHashError;
3172
+ } });
3173
+ Object.defineProperty(exports2, "EmptyDestinationError", { enumerable: true, get: function() {
3174
+ return errors_1.EmptyDestinationError;
3175
+ } });
3176
+ Object.defineProperty(exports2, "DestinationTooLongError", { enumerable: true, get: function() {
3177
+ return errors_1.DestinationTooLongError;
2097
3178
  } });
2098
3179
  Object.defineProperty(exports2, "ZeroDepositorError", { enumerable: true, get: function() {
2099
3180
  return errors_1.ZeroDepositorError;
@@ -2129,18 +3210,39 @@ var require_dist3 = __commonJS({
2129
3210
  Object.defineProperty(exports2, "computeDepositHash", { enumerable: true, get: function() {
2130
3211
  return deposit_encoder_1.computeDepositHash;
2131
3212
  } });
3213
+ Object.defineProperty(exports2, "computeDepositHashV2", { enumerable: true, get: function() {
3214
+ return deposit_encoder_1.computeDepositHashV2;
3215
+ } });
3216
+ Object.defineProperty(exports2, "computeDestinationHash", { enumerable: true, get: function() {
3217
+ return deposit_encoder_1.computeDestinationHash;
3218
+ } });
3219
+ Object.defineProperty(exports2, "MAX_DESTINATION_LEN", { enumerable: true, get: function() {
3220
+ return deposit_encoder_1.MAX_DESTINATION_LEN;
3221
+ } });
2132
3222
  var reserve_encoder_1 = require_reserve_encoder3();
2133
3223
  Object.defineProperty(exports2, "computeReserveHash", { enumerable: true, get: function() {
2134
3224
  return reserve_encoder_1.computeReserveHash;
2135
3225
  } });
2136
- var release_encoder_1 = require_release_encoder();
3226
+ Object.defineProperty(exports2, "computeReserveHashV2", { enumerable: true, get: function() {
3227
+ return reserve_encoder_1.computeReserveHashV2;
3228
+ } });
3229
+ Object.defineProperty(exports2, "computeReserveHashV3", { enumerable: true, get: function() {
3230
+ return reserve_encoder_1.computeReserveHashV3;
3231
+ } });
3232
+ var release_encoder_1 = require_release_encoder3();
2137
3233
  Object.defineProperty(exports2, "computeReleaseHash", { enumerable: true, get: function() {
2138
3234
  return release_encoder_1.computeReleaseHash;
2139
3235
  } });
2140
- var refund_encoder_1 = require_refund_encoder();
3236
+ Object.defineProperty(exports2, "computeReleaseHashV2", { enumerable: true, get: function() {
3237
+ return release_encoder_1.computeReleaseHashV2;
3238
+ } });
3239
+ var refund_encoder_1 = require_refund_encoder3();
2141
3240
  Object.defineProperty(exports2, "computeRefundHash", { enumerable: true, get: function() {
2142
3241
  return refund_encoder_1.computeRefundHash;
2143
3242
  } });
3243
+ Object.defineProperty(exports2, "computeRefundHashV2", { enumerable: true, get: function() {
3244
+ return refund_encoder_1.computeRefundHashV2;
3245
+ } });
2144
3246
  var nonce_generator_1 = require_nonce_generator2();
2145
3247
  Object.defineProperty(exports2, "generateNonce", { enumerable: true, get: function() {
2146
3248
  return nonce_generator_1.generateNonce;
@@ -2151,6 +3253,12 @@ var require_dist3 = __commonJS({
2151
3253
  Object.defineProperty(exports2, "MAX_VALID_SLOT", { enumerable: true, get: function() {
2152
3254
  return nonce_generator_1.MAX_VALID_SLOT;
2153
3255
  } });
3256
+ Object.defineProperty(exports2, "REPLAY_BUCKETS", { enumerable: true, get: function() {
3257
+ return nonce_generator_1.REPLAY_BUCKETS;
3258
+ } });
3259
+ Object.defineProperty(exports2, "DEPOSIT_COMPUTE_UNIT_LIMIT", { enumerable: true, get: function() {
3260
+ return nonce_generator_1.DEPOSIT_COMPUTE_UNIT_LIMIT;
3261
+ } });
2154
3262
  }
2155
3263
  });
2156
3264
 
@@ -2166,7 +3274,8 @@ var require_solana = __commonJS({
2166
3274
  var ethers_1 = require("ethers");
2167
3275
  var tweetnacl_1 = __importDefault(require("tweetnacl"));
2168
3276
  var bs58_1 = __importDefault(require("bs58"));
2169
- var solana_escrow_encoding_1 = require_dist3();
3277
+ var solana_escrow_encoding_1 = require_dist4();
3278
+ var destination_js_1 = require_destination();
2170
3279
  var utils_js_1 = require_utils();
2171
3280
  var errors_js_1 = require_errors();
2172
3281
  var chain_id_js_1 = require_chain_id2();
@@ -2176,7 +3285,8 @@ var require_solana = __commonJS({
2176
3285
  }
2177
3286
  function hashDeposit(prehash, domain) {
2178
3287
  return (0, ethers_1.hexlify)((0, solana_escrow_encoding_1.computeDepositHash)({
2179
- paymentId: (0, ethers_1.getBytes)(prehash.payment_id),
3288
+ // The encoder field was renamed for cross-VM parity; the prehash WIRE key stays payment_id.
3289
+ depositRequestHash: (0, ethers_1.getBytes)(prehash.payment_id),
2180
3290
  depositor: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.depositor),
2181
3291
  mint: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.mint),
2182
3292
  amount: BigInt(prehash.amount),
@@ -2187,6 +3297,26 @@ var require_solana = __commonJS({
2187
3297
  deadline: BigInt(prehash.deadline)
2188
3298
  }, domain));
2189
3299
  }
3300
+ var SVM_DESTINATION_COMMITMENT_VERSION = 4;
3301
+ function hashDepositV2(prehash, domain) {
3302
+ return (0, ethers_1.hexlify)((0, solana_escrow_encoding_1.computeDepositHashV2)(
3303
+ {
3304
+ depositRequestHash: (0, ethers_1.getBytes)(prehash.deposit_request_hash),
3305
+ depositor: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.depositor),
3306
+ mint: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.mint),
3307
+ amount: BigInt(prehash.amount),
3308
+ reserver: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.reserver),
3309
+ releaser: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.releaser),
3310
+ nonce: BigInt(prehash.nonce),
3311
+ issuedAt: BigInt(prehash.issued_at),
3312
+ deadline: BigInt(prehash.deadline)
3313
+ },
3314
+ // Plaintext, NOT pre-hashed: the encoder hashes it, and hashing an already-hashed
3315
+ // destination yields a well-formed commitment no on-chain state can satisfy.
3316
+ prehash.destination,
3317
+ domain
3318
+ ));
3319
+ }
2190
3320
  function domainFrom(defaults) {
2191
3321
  if (!defaults.escrowContract) {
2192
3322
  throw new Error("sender_auth: Solana source requires escrowContract (escrow program id) for the deposit-hash domain");
@@ -2201,12 +3331,11 @@ var require_solana = __commonJS({
2201
3331
  };
2202
3332
  }
2203
3333
  exports2.solanaAdapter = {
2204
- async buildAuthMessage({ sourceAsset, depositor, maxSourceAmount, requestId, sourceDefaults, nonce, solanaClockReader }) {
3334
+ async buildAuthMessage({ sourceAsset, depositor, maxSourceAmount, requestId, sourceDefaults, destinationAsset, destinationAccount, nonce, solanaClockReader }) {
2205
3335
  if (!requestId) {
2206
3336
  throw new Error("sender_auth: request_id is required");
2207
3337
  }
2208
- const sourceChainId = sourceAsset.split("/")[0];
2209
- const tokenMint = sourceAsset.split("/")[1].split(":")[1];
3338
+ const { network: sourceChainId, asset: tokenMint } = (0, utils_js_1.parseSourceAsset)(sourceAsset);
2210
3339
  const depositNonce = nonce !== void 0 ? BigInt(nonce) : (0, solana_escrow_encoding_1.generateNonce)();
2211
3340
  if (nonce !== void 0) {
2212
3341
  if (depositNonce < 0n || depositNonce >= 1n << 64n) {
@@ -2219,8 +3348,8 @@ var require_solana = __commonJS({
2219
3348
  const issuedAt = solanaClockReader ? await solanaClockReader(sourceChainId) : BigInt(Math.floor(Date.now() / 1e3));
2220
3349
  const deadline = issuedAt + BigInt(utils_js_1.REPLAY_HORIZON_SECS - 8);
2221
3350
  const paymentId = generateSolanaPaymentIdV3(requestId);
2222
- const prehash = {
2223
- payment_id: paymentId,
3351
+ const domain = domainFrom(sourceDefaults);
3352
+ const common = {
2224
3353
  depositor,
2225
3354
  mint: tokenMint,
2226
3355
  amount: BigInt(maxSourceAmount).toString(),
@@ -2230,7 +3359,20 @@ var require_solana = __commonJS({
2230
3359
  issued_at: issuedAt.toString(),
2231
3360
  deadline: deadline.toString()
2232
3361
  };
2233
- const depositHash = hashDeposit(prehash, domainFrom(sourceDefaults));
3362
+ if (domain.signatureDomainVersion >= SVM_DESTINATION_COMMITMENT_VERSION) {
3363
+ const prehashV2 = {
3364
+ deposit_request_hash: paymentId,
3365
+ destination: (0, destination_js_1.buildEscrowDestination)(destinationAsset, destinationAccount),
3366
+ ...common
3367
+ };
3368
+ return {
3369
+ messageScheme: "SOLANA",
3370
+ messageHash: hashDepositV2(prehashV2, domain),
3371
+ messagePrehash: JSON.stringify(prehashV2)
3372
+ };
3373
+ }
3374
+ const prehash = { payment_id: paymentId, ...common };
3375
+ const depositHash = hashDeposit(prehash, domain);
2234
3376
  return { messageScheme: "SOLANA", messageHash: depositHash, messagePrehash: JSON.stringify(prehash) };
2235
3377
  },
2236
3378
  async sign(signedMessage, privateKey) {
@@ -2276,8 +3418,18 @@ var require_solana = __commonJS({
2276
3418
  let prehash;
2277
3419
  let canonicalHash;
2278
3420
  try {
2279
- prehash = JSON.parse(signed.message_prehash);
2280
- canonicalHash = hashDeposit(prehash, domainFrom(expected));
3421
+ const domain = domainFrom(expected);
3422
+ if (domain.signatureDomainVersion >= SVM_DESTINATION_COMMITMENT_VERSION) {
3423
+ const v2 = JSON.parse(signed.message_prehash);
3424
+ if (typeof v2.deposit_request_hash !== "string" || typeof v2.destination !== "string") {
3425
+ throw new Error("pre-widening V1 prehash on a destination-committing domain");
3426
+ }
3427
+ canonicalHash = hashDepositV2(v2, domain);
3428
+ prehash = { payment_id: v2.deposit_request_hash, ...v2 };
3429
+ } else {
3430
+ prehash = JSON.parse(signed.message_prehash);
3431
+ canonicalHash = hashDeposit(prehash, domain);
3432
+ }
2281
3433
  } catch {
2282
3434
  throw new errors_js_1.MalformedPrehashError();
2283
3435
  }
@@ -2369,14 +3521,7 @@ var require_verify = __commonJS({
2369
3521
  Object.defineProperty(exports2, "__esModule", { value: true });
2370
3522
  exports2.verifyPaymentRequest = verifyPaymentRequest;
2371
3523
  var index_js_1 = require_adapters();
2372
- function parseSourceAsset(assetIdentifier) {
2373
- const parts = assetIdentifier.split("/");
2374
- const nsParts = parts[1]?.split(":");
2375
- if (parts.length < 2 || !nsParts || nsParts.length < 2 || !nsParts[1]) {
2376
- throw new Error(`sender_auth: invalid source asset "${assetIdentifier}"`);
2377
- }
2378
- return { network: parts[0], asset: nsParts[1] };
2379
- }
3524
+ var utils_js_1 = require_utils();
2380
3525
  function verifyPaymentRequest(request2, expected = {}) {
2381
3526
  const senderAuth = request2.sender_auth;
2382
3527
  if (!senderAuth?.signed_messages?.length) {
@@ -2385,87 +3530,482 @@ var require_verify = __commonJS({
2385
3530
  if (!request2.source) {
2386
3531
  throw new Error("sender_auth: request has no source");
2387
3532
  }
2388
- const requestSource = parseSourceAsset(request2.source.asset_identifier);
2389
- const { sourceAsset, network: networkOverride, maxSourceAmount: amountOverride, ...scheme } = expected;
2390
- const network = networkOverride ?? requestSource.network;
2391
- const asset = sourceAsset ?? requestSource.asset;
2392
- const maxSourceAmount = amountOverride ?? request2.max_source_amount ?? "0";
2393
- const source = { network, asset, account: request2.source.account };
2394
- const perMessage = { ...scheme, maxSourceAmount };
2395
- const adapter = (0, index_js_1.getChainAdapter)(network);
2396
- const results = senderAuth.signed_messages.map((m) => adapter.recoverAndVerify(m, source, perMessage));
2397
- return { results, recoveredAccount: source.account };
3533
+ const requestSource = (0, utils_js_1.parseSourceAsset)(request2.source.asset_identifier);
3534
+ const { sourceAsset, network: networkOverride, maxSourceAmount: amountOverride, ...scheme } = expected;
3535
+ const network = networkOverride ?? requestSource.network;
3536
+ const asset = sourceAsset ?? requestSource.asset;
3537
+ const maxSourceAmount = amountOverride ?? request2.max_source_amount ?? "0";
3538
+ const source = { network, asset, account: request2.source.account };
3539
+ const perMessage = { ...scheme, maxSourceAmount };
3540
+ const adapter = (0, index_js_1.getChainAdapter)(network);
3541
+ const results = senderAuth.signed_messages.map((m) => adapter.recoverAndVerify(m, source, perMessage));
3542
+ return { results, recoveredAccount: source.account };
3543
+ }
3544
+ }
3545
+ });
3546
+
3547
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/signer.js
3548
+ var require_signer = __commonJS({
3549
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/signer.js"(exports2) {
3550
+ "use strict";
3551
+ Object.defineProperty(exports2, "__esModule", { value: true });
3552
+ exports2.localKeySigner = localKeySigner2;
3553
+ var index_js_1 = require_adapters();
3554
+ function localKeySigner2(network, privateKey) {
3555
+ const adapter = (0, index_js_1.getChainAdapter)(network);
3556
+ return {
3557
+ async sign(signedMessage) {
3558
+ const signature = await adapter.sign(signedMessage, privateKey);
3559
+ const delegateSigner = adapter.deriveDelegateSigner?.(privateKey);
3560
+ return delegateSigner !== void 0 ? { signature, delegateSigner } : { signature };
3561
+ }
3562
+ };
3563
+ }
3564
+ }
3565
+ });
3566
+
3567
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/index.js
3568
+ var require_dist5 = __commonJS({
3569
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/index.js"(exports2) {
3570
+ "use strict";
3571
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
3572
+ if (k2 === void 0) k2 = k;
3573
+ var desc = Object.getOwnPropertyDescriptor(m, k);
3574
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
3575
+ desc = { enumerable: true, get: function() {
3576
+ return m[k];
3577
+ } };
3578
+ }
3579
+ Object.defineProperty(o, k2, desc);
3580
+ }) : (function(o, m, k, k2) {
3581
+ if (k2 === void 0) k2 = k;
3582
+ o[k2] = m[k];
3583
+ }));
3584
+ var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
3585
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
3586
+ };
3587
+ Object.defineProperty(exports2, "__esModule", { value: true });
3588
+ exports2.localKeySigner = exports2.SignerMismatchError = exports2.RecoveryFailedError = exports2.MalformedPrehashError = exports2.verifyPaymentRequest = exports2.DESTINATION_COMMITMENT_WITNESS_VERSION = exports2.usesDestinationCommitment = exports2.MAX_DESTINATION_BYTES = exports2.deriveDepositRequestHash = exports2.buildEscrowDestination = exports2.getChainAdapter = void 0;
3589
+ __exportStar(require_types(), exports2);
3590
+ __exportStar(require_utils(), exports2);
3591
+ __exportStar(require_chain_id2(), exports2);
3592
+ var index_js_1 = require_adapters();
3593
+ Object.defineProperty(exports2, "getChainAdapter", { enumerable: true, get: function() {
3594
+ return index_js_1.getChainAdapter;
3595
+ } });
3596
+ var destination_js_1 = require_destination();
3597
+ Object.defineProperty(exports2, "buildEscrowDestination", { enumerable: true, get: function() {
3598
+ return destination_js_1.buildEscrowDestination;
3599
+ } });
3600
+ Object.defineProperty(exports2, "deriveDepositRequestHash", { enumerable: true, get: function() {
3601
+ return destination_js_1.deriveDepositRequestHash;
3602
+ } });
3603
+ Object.defineProperty(exports2, "MAX_DESTINATION_BYTES", { enumerable: true, get: function() {
3604
+ return destination_js_1.MAX_DESTINATION_BYTES;
3605
+ } });
3606
+ Object.defineProperty(exports2, "usesDestinationCommitment", { enumerable: true, get: function() {
3607
+ return destination_js_1.usesDestinationCommitment;
3608
+ } });
3609
+ Object.defineProperty(exports2, "DESTINATION_COMMITMENT_WITNESS_VERSION", { enumerable: true, get: function() {
3610
+ return destination_js_1.DESTINATION_COMMITMENT_WITNESS_VERSION;
3611
+ } });
3612
+ var verify_js_1 = require_verify();
3613
+ Object.defineProperty(exports2, "verifyPaymentRequest", { enumerable: true, get: function() {
3614
+ return verify_js_1.verifyPaymentRequest;
3615
+ } });
3616
+ var errors_js_1 = require_errors();
3617
+ Object.defineProperty(exports2, "MalformedPrehashError", { enumerable: true, get: function() {
3618
+ return errors_js_1.MalformedPrehashError;
3619
+ } });
3620
+ Object.defineProperty(exports2, "RecoveryFailedError", { enumerable: true, get: function() {
3621
+ return errors_js_1.RecoveryFailedError;
3622
+ } });
3623
+ Object.defineProperty(exports2, "SignerMismatchError", { enumerable: true, get: function() {
3624
+ return errors_js_1.SignerMismatchError;
3625
+ } });
3626
+ var signer_js_1 = require_signer();
3627
+ Object.defineProperty(exports2, "localKeySigner", { enumerable: true, get: function() {
3628
+ return signer_js_1.localKeySigner;
3629
+ } });
3630
+ }
3631
+ });
3632
+
3633
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/allowance.js
3634
+ var require_allowance = __commonJS({
3635
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/allowance.js"(exports2) {
3636
+ "use strict";
3637
+ Object.defineProperty(exports2, "__esModule", { value: true });
3638
+ exports2.UNLIMITED_APPROVAL_FLOOR = exports2.UNLIMITED_APPROVAL = void 0;
3639
+ exports2.isAllowanceSufficient = isAllowanceSufficient;
3640
+ exports2.effectiveRequirement = effectiveRequirement;
3641
+ exports2.resolveApprovalAmount = resolveApprovalAmount;
3642
+ var ethers_1 = require("ethers");
3643
+ exports2.UNLIMITED_APPROVAL = ethers_1.MaxUint256;
3644
+ exports2.UNLIMITED_APPROVAL_FLOOR = ethers_1.MaxUint256 / 2n;
3645
+ function isAllowanceSufficient(current, requiredAllowance) {
3646
+ return requiredAllowance !== void 0 ? current >= requiredAllowance : current >= exports2.UNLIMITED_APPROVAL_FLOOR;
3647
+ }
3648
+ function effectiveRequirement(requiredAllowance, approvalAmount) {
3649
+ return requiredAllowance ?? approvalAmount;
3650
+ }
3651
+ function resolveApprovalAmount(approvalAmount, requiredAllowance) {
3652
+ if (approvalAmount === void 0)
3653
+ return exports2.UNLIMITED_APPROVAL;
3654
+ if (approvalAmount <= 0n) {
3655
+ throw new Error(`token_approval: approvalAmount must be positive, got ${approvalAmount}`);
3656
+ }
3657
+ if (requiredAllowance !== void 0 && approvalAmount < requiredAllowance) {
3658
+ throw new Error(`token_approval: approvalAmount ${approvalAmount} is below requiredAllowance ${requiredAllowance}, so the approval would still fall short and every call would send another one`);
3659
+ }
3660
+ return approvalAmount;
3661
+ }
3662
+ }
3663
+ });
3664
+
3665
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/unconfirmed.js
3666
+ var require_unconfirmed = __commonJS({
3667
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/unconfirmed.js"(exports2) {
3668
+ "use strict";
3669
+ Object.defineProperty(exports2, "__esModule", { value: true });
3670
+ exports2.unconfirmed = unconfirmed;
3671
+ exports2.isUnconfirmed = isUnconfirmed2;
3672
+ function unconfirmed(message) {
3673
+ return Object.assign(new Error(message), { unconfirmed: true });
3674
+ }
3675
+ function isUnconfirmed2(error) {
3676
+ return error?.unconfirmed === true;
3677
+ }
3678
+ }
3679
+ });
3680
+
3681
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/evm.js
3682
+ var require_evm2 = __commonJS({
3683
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/evm.js"(exports2) {
3684
+ "use strict";
3685
+ Object.defineProperty(exports2, "__esModule", { value: true });
3686
+ exports2.evmAdapter = exports2.ERC20_ALLOWANCE_ABI = void 0;
3687
+ var ethers_1 = require("ethers");
3688
+ var evm_escrow_encoding_1 = require_dist3();
3689
+ var unconfirmed_js_1 = require_unconfirmed();
3690
+ exports2.ERC20_ALLOWANCE_ABI = [
3691
+ "function allowance(address owner, address spender) view returns (uint256)",
3692
+ "function approve(address spender, uint256 amount) returns (bool)"
3693
+ ];
3694
+ var DEFAULT_CONFIRMATION_TIMEOUT_MS = 6e4;
3695
+ function requireSigner(params) {
3696
+ if (!params.signer) {
3697
+ throw new Error(`token_approval: approving on ${params.network} needs an ethers signer connected to that chain (params.signer)`);
3698
+ }
3699
+ return params.signer;
3700
+ }
3701
+ function erc20(params) {
3702
+ return new ethers_1.Contract(params.token, exports2.ERC20_ALLOWANCE_ABI, requireSigner(params));
3703
+ }
3704
+ async function send(params, call, purpose) {
3705
+ const tx = await call;
3706
+ params.onSubmitted?.(tx.hash, purpose);
3707
+ const timeoutMs = params.confirmation?.timeoutMs ?? DEFAULT_CONFIRMATION_TIMEOUT_MS;
3708
+ try {
3709
+ await tx.wait(1, timeoutMs);
3710
+ } catch (error) {
3711
+ if (isTimeout(error)) {
3712
+ throw (0, unconfirmed_js_1.unconfirmed)(`token_approval: the ${purpose === "reset" ? "allowance reset" : "approval"} ${tx.hash} was not confirmed within ${timeoutMs}ms. It may still confirm \u2014 check the transaction before approving again.`);
3713
+ }
3714
+ throw error;
3715
+ }
3716
+ return tx.hash;
3717
+ }
3718
+ function isTimeout(error) {
3719
+ return error?.code === "TIMEOUT";
3720
+ }
3721
+ exports2.evmAdapter = {
3722
+ applicable: true,
3723
+ resolveSpender(params) {
3724
+ return params.spender ?? evm_escrow_encoding_1.PERMIT2_CONTRACT_ADDRESS;
3725
+ },
3726
+ async senderAddress(params) {
3727
+ return await requireSigner(params).getAddress();
3728
+ },
3729
+ async readAllowance(params, spender) {
3730
+ return await erc20(params).allowance(params.owner, spender);
3731
+ },
3732
+ async approve(params, spender, amount, current) {
3733
+ const token = erc20(params);
3734
+ if (current !== 0n && await refusesOverwrite(params, token, spender, amount)) {
3735
+ const nonce = await requireSigner(params).getNonce("pending");
3736
+ const resetTxHash = await send(params, token.approve(spender, 0n, { nonce }), "reset");
3737
+ try {
3738
+ return {
3739
+ txHash: await send(params, token.approve(spender, amount, { nonce: nonce + 1 }), "approval"),
3740
+ resetTxHash
3741
+ };
3742
+ } catch (error) {
3743
+ const detail = error instanceof Error ? error.message : String(error);
3744
+ if ((0, unconfirmed_js_1.isUnconfirmed)(error)) {
3745
+ throw (0, unconfirmed_js_1.unconfirmed)(`token_approval: the allowance was reset to 0 in ${resetTxHash} and the new approval was broadcast but not confirmed (${detail}). If it lands the allowance is ${amount}; if it does not, it stays 0. Check that transaction before approving again.`);
3746
+ }
3747
+ throw new Error(`token_approval: the allowance was reset to 0 in ${resetTxHash}, but the new approval did not go through (${detail}). The allowance is currently 0 \u2014 re-run to finish.`);
3748
+ }
3749
+ }
3750
+ return { txHash: await send(params, token.approve(spender, amount), "approval") };
3751
+ }
3752
+ };
3753
+ async function refusesOverwrite(params, token, spender, amount) {
3754
+ const data = token.interface.encodeFunctionData("approve", [spender, amount]);
3755
+ try {
3756
+ await requireSigner(params).call({ to: params.token, data });
3757
+ return false;
3758
+ } catch (error) {
3759
+ if (isRevert(error))
3760
+ return true;
3761
+ throw error;
3762
+ }
3763
+ }
3764
+ function isRevert(error) {
3765
+ return error?.code === "CALL_EXCEPTION";
3766
+ }
3767
+ }
3768
+ });
3769
+
3770
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/tron.js
3771
+ var require_tron2 = __commonJS({
3772
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/tron.js"(exports2) {
3773
+ "use strict";
3774
+ Object.defineProperty(exports2, "__esModule", { value: true });
3775
+ exports2.tronAdapter = exports2.TRC20_ALLOWANCE_ABI = void 0;
3776
+ var payment_request_sender_auth_1 = require_dist5();
3777
+ var unconfirmed_js_1 = require_unconfirmed();
3778
+ exports2.TRC20_ALLOWANCE_ABI = [
3779
+ {
3780
+ name: "allowance",
3781
+ type: "function",
3782
+ stateMutability: "View",
3783
+ inputs: [
3784
+ { name: "owner", type: "address" },
3785
+ { name: "spender", type: "address" }
3786
+ ],
3787
+ outputs: [{ type: "uint256" }]
3788
+ },
3789
+ {
3790
+ name: "approve",
3791
+ type: "function",
3792
+ stateMutability: "Nonpayable",
3793
+ inputs: [
3794
+ { name: "spender", type: "address" },
3795
+ { name: "amount", type: "uint256" }
3796
+ ],
3797
+ outputs: [{ type: "bool" }]
3798
+ }
3799
+ ];
3800
+ var DEFAULT_FEE_LIMIT = 1e8;
3801
+ var DEFAULT_CONFIRMATION_TIMEOUT_MS = 6e4;
3802
+ var DEFAULT_POLL_INTERVAL_MS2 = 1500;
3803
+ function requireTronWeb(params) {
3804
+ if (!params.tronWeb) {
3805
+ throw new Error(`token_approval: approving on ${params.network} needs a TronWeb instance configured for that chain (params.tronWeb)`);
3806
+ }
3807
+ return params.tronWeb;
3808
+ }
3809
+ function token(params) {
3810
+ return requireTronWeb(params).contract(exports2.TRC20_ALLOWANCE_ABI, params.token);
3811
+ }
3812
+ var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
3813
+ async function waitForConfirmation(tronWeb, txId, options) {
3814
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_CONFIRMATION_TIMEOUT_MS;
3815
+ const pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
3816
+ const deadline = Date.now() + timeoutMs;
3817
+ for (; ; ) {
3818
+ let result;
3819
+ try {
3820
+ result = (await tronWeb.trx.getTransactionInfo(txId))?.receipt?.result;
3821
+ } catch {
3822
+ }
3823
+ if (result === "SUCCESS")
3824
+ return;
3825
+ if (result !== void 0) {
3826
+ throw new Error(`token_approval: Tron approval ${txId} failed on-chain (${result})`);
3827
+ }
3828
+ if (Date.now() >= deadline) {
3829
+ throw (0, unconfirmed_js_1.unconfirmed)(`token_approval: Tron approval ${txId} was not confirmed within ${timeoutMs}ms. It may still confirm \u2014 check the transaction before approving again.`);
3830
+ }
3831
+ await sleep(pollIntervalMs);
3832
+ }
3833
+ }
3834
+ async function send(params, contract, spender, amount, purpose) {
3835
+ const txId = await contract.approve(spender, amount.toString()).send({ feeLimit: params.confirmation?.feeLimit ?? DEFAULT_FEE_LIMIT });
3836
+ params.onSubmitted?.(txId, purpose);
3837
+ await waitForConfirmation(requireTronWeb(params), txId, params.confirmation);
3838
+ return txId;
3839
+ }
3840
+ exports2.tronAdapter = {
3841
+ applicable: true,
3842
+ resolveSpender(params) {
3843
+ return params.spender ?? (0, payment_request_sender_auth_1.resolveTronPermit2)(params.network);
3844
+ },
3845
+ async senderAddress(params) {
3846
+ return requireTronWeb(params).defaultAddress?.base58 || void 0;
3847
+ },
3848
+ async readAllowance(params, spender) {
3849
+ const raw = await token(params).allowance(params.owner, spender).call();
3850
+ return BigInt(String(raw));
3851
+ },
3852
+ async approve(params, spender, amount, current) {
3853
+ const contract = token(params);
3854
+ try {
3855
+ return { txHash: await send(params, contract, spender, amount, "approval") };
3856
+ } catch (error) {
3857
+ if (current === 0n || (0, unconfirmed_js_1.isUnconfirmed)(error))
3858
+ throw error;
3859
+ throw new Error(`token_approval: the approval on ${params.network} failed while an allowance of ${current} was already set (${error instanceof Error ? error.message : String(error)}). Some tokens refuse to replace a non-zero allowance in place: approve 0 first, then retry.`);
3860
+ }
3861
+ }
3862
+ };
3863
+ }
3864
+ });
3865
+
3866
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/solana.js
3867
+ var require_solana2 = __commonJS({
3868
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/solana.js"(exports2) {
3869
+ "use strict";
3870
+ Object.defineProperty(exports2, "__esModule", { value: true });
3871
+ exports2.solanaAdapter = void 0;
3872
+ exports2.solanaAdapter = {
3873
+ applicable: false,
3874
+ resolveSpender() {
3875
+ throw new Error("token_approval: Solana does not use a Permit2-style allowance");
3876
+ },
3877
+ async senderAddress() {
3878
+ throw new Error("token_approval: Solana does not use a Permit2-style allowance");
3879
+ },
3880
+ async readAllowance() {
3881
+ throw new Error("token_approval: Solana does not use a Permit2-style allowance");
3882
+ },
3883
+ async approve() {
3884
+ throw new Error("token_approval: Solana does not use a Permit2-style allowance");
3885
+ }
3886
+ };
3887
+ }
3888
+ });
3889
+
3890
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/index.js
3891
+ var require_adapters2 = __commonJS({
3892
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/index.js"(exports2) {
3893
+ "use strict";
3894
+ Object.defineProperty(exports2, "__esModule", { value: true });
3895
+ exports2.approvalAdapterFor = approvalAdapterFor;
3896
+ var payment_request_sender_auth_1 = require_dist5();
3897
+ var evm_js_1 = require_evm2();
3898
+ var tron_js_1 = require_tron2();
3899
+ var solana_js_1 = require_solana2();
3900
+ var ADAPTERS = {
3901
+ eip155: evm_js_1.evmAdapter,
3902
+ tron: tron_js_1.tronAdapter,
3903
+ solana: solana_js_1.solanaAdapter
3904
+ };
3905
+ function approvalAdapterFor(network) {
3906
+ const namespace = (0, payment_request_sender_auth_1.namespaceOf)(network);
3907
+ const adapter = Object.hasOwn(ADAPTERS, namespace) ? ADAPTERS[namespace] : void 0;
3908
+ if (!adapter) {
3909
+ throw new Error(`token_approval: no approval adapter for network '${network}'`);
3910
+ }
3911
+ return adapter;
2398
3912
  }
2399
3913
  }
2400
3914
  });
2401
3915
 
2402
- // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/signer.js
2403
- var require_signer = __commonJS({
2404
- "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/signer.js"(exports2) {
3916
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/sender.js
3917
+ var require_sender = __commonJS({
3918
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/sender.js"(exports2) {
2405
3919
  "use strict";
2406
3920
  Object.defineProperty(exports2, "__esModule", { value: true });
2407
- exports2.localKeySigner = localKeySigner2;
2408
- var index_js_1 = require_adapters();
2409
- function localKeySigner2(network, privateKey) {
2410
- const adapter = (0, index_js_1.getChainAdapter)(network);
2411
- return {
2412
- async sign(signedMessage) {
2413
- const signature = await adapter.sign(signedMessage, privateKey);
2414
- const delegateSigner = adapter.deriveDelegateSigner?.(privateKey);
2415
- return delegateSigner !== void 0 ? { signature, delegateSigner } : { signature };
2416
- }
2417
- };
3921
+ exports2.assertSenderIsOwner = assertSenderIsOwner;
3922
+ function assertSenderIsOwner(owner, sender) {
3923
+ if (sender === void 0 || sender.toLowerCase() === owner.toLowerCase())
3924
+ return;
3925
+ throw new Error(`token_approval: the approval would be sent by ${sender}, but the allowance is being granted for ${owner}. An approval only ever applies to the account that sends it, so this would approve ${sender} and leave ${owner} unable to pay. Pass a signer for ${owner}, or read the allowance for ${sender}.`);
2418
3926
  }
2419
3927
  }
2420
3928
  });
2421
3929
 
2422
- // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/index.js
2423
- var require_dist4 = __commonJS({
2424
- "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/index.js"(exports2) {
3930
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/index.js
3931
+ var require_dist6 = __commonJS({
3932
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/index.js"(exports2) {
2425
3933
  "use strict";
2426
- var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
2427
- if (k2 === void 0) k2 = k;
2428
- var desc = Object.getOwnPropertyDescriptor(m, k);
2429
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
2430
- desc = { enumerable: true, get: function() {
2431
- return m[k];
2432
- } };
2433
- }
2434
- Object.defineProperty(o, k2, desc);
2435
- }) : (function(o, m, k, k2) {
2436
- if (k2 === void 0) k2 = k;
2437
- o[k2] = m[k];
2438
- }));
2439
- var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
2440
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
2441
- };
2442
3934
  Object.defineProperty(exports2, "__esModule", { value: true });
2443
- exports2.localKeySigner = exports2.SignerMismatchError = exports2.RecoveryFailedError = exports2.MalformedPrehashError = exports2.verifyPaymentRequest = exports2.getChainAdapter = void 0;
2444
- __exportStar(require_types(), exports2);
2445
- __exportStar(require_utils(), exports2);
2446
- __exportStar(require_chain_id2(), exports2);
2447
- var index_js_1 = require_adapters();
2448
- Object.defineProperty(exports2, "getChainAdapter", { enumerable: true, get: function() {
2449
- return index_js_1.getChainAdapter;
3935
+ exports2.approvalAdapterFor = exports2.isUnconfirmed = exports2.assertSenderIsOwner = exports2.resolveApprovalAmount = exports2.isAllowanceSufficient = exports2.effectiveRequirement = exports2.UNLIMITED_APPROVAL_FLOOR = exports2.UNLIMITED_APPROVAL = void 0;
3936
+ exports2.needsSourceApproval = needsSourceApproval2;
3937
+ exports2.ensureSourceApproval = ensureSourceApproval2;
3938
+ var allowance_js_1 = require_allowance();
3939
+ var index_js_1 = require_adapters2();
3940
+ var sender_js_1 = require_sender();
3941
+ var allowance_js_2 = require_allowance();
3942
+ Object.defineProperty(exports2, "UNLIMITED_APPROVAL", { enumerable: true, get: function() {
3943
+ return allowance_js_2.UNLIMITED_APPROVAL;
2450
3944
  } });
2451
- var verify_js_1 = require_verify();
2452
- Object.defineProperty(exports2, "verifyPaymentRequest", { enumerable: true, get: function() {
2453
- return verify_js_1.verifyPaymentRequest;
3945
+ Object.defineProperty(exports2, "UNLIMITED_APPROVAL_FLOOR", { enumerable: true, get: function() {
3946
+ return allowance_js_2.UNLIMITED_APPROVAL_FLOOR;
2454
3947
  } });
2455
- var errors_js_1 = require_errors();
2456
- Object.defineProperty(exports2, "MalformedPrehashError", { enumerable: true, get: function() {
2457
- return errors_js_1.MalformedPrehashError;
3948
+ Object.defineProperty(exports2, "effectiveRequirement", { enumerable: true, get: function() {
3949
+ return allowance_js_2.effectiveRequirement;
2458
3950
  } });
2459
- Object.defineProperty(exports2, "RecoveryFailedError", { enumerable: true, get: function() {
2460
- return errors_js_1.RecoveryFailedError;
3951
+ Object.defineProperty(exports2, "isAllowanceSufficient", { enumerable: true, get: function() {
3952
+ return allowance_js_2.isAllowanceSufficient;
2461
3953
  } });
2462
- Object.defineProperty(exports2, "SignerMismatchError", { enumerable: true, get: function() {
2463
- return errors_js_1.SignerMismatchError;
3954
+ Object.defineProperty(exports2, "resolveApprovalAmount", { enumerable: true, get: function() {
3955
+ return allowance_js_2.resolveApprovalAmount;
2464
3956
  } });
2465
- var signer_js_1 = require_signer();
2466
- Object.defineProperty(exports2, "localKeySigner", { enumerable: true, get: function() {
2467
- return signer_js_1.localKeySigner;
3957
+ var sender_js_2 = require_sender();
3958
+ Object.defineProperty(exports2, "assertSenderIsOwner", { enumerable: true, get: function() {
3959
+ return sender_js_2.assertSenderIsOwner;
2468
3960
  } });
3961
+ var unconfirmed_js_1 = require_unconfirmed();
3962
+ Object.defineProperty(exports2, "isUnconfirmed", { enumerable: true, get: function() {
3963
+ return unconfirmed_js_1.isUnconfirmed;
3964
+ } });
3965
+ var index_js_2 = require_adapters2();
3966
+ Object.defineProperty(exports2, "approvalAdapterFor", { enumerable: true, get: function() {
3967
+ return index_js_2.approvalAdapterFor;
3968
+ } });
3969
+ async function needsSourceApproval2(params) {
3970
+ const adapter = (0, index_js_1.approvalAdapterFor)(params.network);
3971
+ if (!adapter.applicable)
3972
+ return false;
3973
+ const required = (0, allowance_js_1.effectiveRequirement)(params.requiredAllowance, params.approvalAmount);
3974
+ (0, allowance_js_1.resolveApprovalAmount)(params.approvalAmount, required);
3975
+ const spender = adapter.resolveSpender(params);
3976
+ const current = await adapter.readAllowance(params, spender);
3977
+ return !(0, allowance_js_1.isAllowanceSufficient)(current, required);
3978
+ }
3979
+ async function ensureSourceApproval2(params) {
3980
+ const adapter = (0, index_js_1.approvalAdapterFor)(params.network);
3981
+ if (!adapter.applicable)
3982
+ return { alreadySufficient: true };
3983
+ const required = (0, allowance_js_1.effectiveRequirement)(params.requiredAllowance, params.approvalAmount);
3984
+ const amount = (0, allowance_js_1.resolveApprovalAmount)(params.approvalAmount, required);
3985
+ const spender = adapter.resolveSpender(params);
3986
+ const current = await adapter.readAllowance(params, spender);
3987
+ if ((0, allowance_js_1.isAllowanceSufficient)(current, required)) {
3988
+ return { alreadySufficient: true };
3989
+ }
3990
+ (0, sender_js_1.assertSenderIsOwner)(params.owner, await adapter.senderAddress(params));
3991
+ return { alreadySufficient: false, ...await adapter.approve(params, spender, amount, current) };
3992
+ }
3993
+ }
3994
+ });
3995
+
3996
+ // src/signers/pinned-address.ts
3997
+ function requirePinnedSender(pinnedAddress) {
3998
+ if (pinnedAddress === null || pinnedAddress === void 0) return void 0;
3999
+ if (typeof pinnedAddress !== "string" || pinnedAddress.trim() === "") {
4000
+ throw new Error(
4001
+ "The sender address (pinnedAddress) must be a non-empty address. Pass the sender to check it against the signing wallet or key. SDK callers may omit pinnedAddress to skip that check."
4002
+ );
4003
+ }
4004
+ return pinnedAddress;
4005
+ }
4006
+ var init_pinned_address = __esm({
4007
+ "src/signers/pinned-address.ts"() {
4008
+ "use strict";
2469
4009
  }
2470
4010
  });
2471
4011
 
@@ -2566,7 +4106,7 @@ var require_policy = __commonJS({
2566
4106
  });
2567
4107
 
2568
4108
  // ../key-management/common/typescript/dist/index.js
2569
- var require_dist5 = __commonJS({
4109
+ var require_dist7 = __commonJS({
2570
4110
  "../key-management/common/typescript/dist/index.js"(exports2) {
2571
4111
  "use strict";
2572
4112
  var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
@@ -2708,7 +4248,7 @@ var require_client = __commonJS({
2708
4248
  Object.defineProperty(exports2, "__esModule", { value: true });
2709
4249
  exports2.TurnkeyClient = void 0;
2710
4250
  var promises_1 = require("timers/promises");
2711
- var km_core_1 = require_dist5();
4251
+ var km_core_1 = require_dist7();
2712
4252
  var constants_1 = require_constants();
2713
4253
  var logger_1 = require_logger();
2714
4254
  var meter_1 = require_meter();
@@ -2860,7 +4400,8 @@ var require_client = __commonJS({
2860
4400
  }
2861
4401
  if (activity?.status !== "ACTIVITY_STATUS_COMPLETED") {
2862
4402
  const failure = activity?.failure ?? {};
2863
- throw (0, km_core_1.signerTerminal)(km_core_1.SignerErrorCode.TURNKEY_ACTIVITY_FAILED, `Turnkey ${ctx} activityId=${activity?.id ?? "?"} status=${activity?.status ?? "unknown"}; ${JSON.stringify(failure)}`);
4403
+ const fp = activity?.fingerprint ? ` fingerprint=${activity.fingerprint}` : "";
4404
+ throw (0, km_core_1.signerTerminal)(km_core_1.SignerErrorCode.TURNKEY_ACTIVITY_FAILED, `Turnkey ${ctx} activityId=${activity?.id ?? "?"} status=${activity?.status ?? "unknown"}${fp}; ${JSON.stringify(failure)}`);
2864
4405
  }
2865
4406
  if (activity.result == null) {
2866
4407
  throw (0, km_core_1.signerTerminal)(km_core_1.SignerErrorCode.TURNKEY_BAD_RESPONSE, `Turnkey ${ctx} activityId=${activity.id} COMPLETED but result was missing`);
@@ -3087,7 +4628,7 @@ var require_signer_base = __commonJS({
3087
4628
  Object.defineProperty(exports2, "__esModule", { value: true });
3088
4629
  exports2.resolveTurnkeyAccountAddress = resolveTurnkeyAccountAddress;
3089
4630
  var promises_1 = require("timers/promises");
3090
- var km_core_1 = require_dist5();
4631
+ var km_core_1 = require_dist7();
3091
4632
  var constants_1 = require_constants();
3092
4633
  var DISCOVERY_BACKOFF_MS = constants_1.TURNKEY_RETRY_BACKOFF_MS;
3093
4634
  async function resolveTurnkeyAccountAddress(deps, addressFormat) {
@@ -3146,7 +4687,7 @@ var require_secp256k1_helpers = __commonJS({
3146
4687
  exports2.signSecp256k1TypedDataAndVerify = signSecp256k1TypedDataAndVerify;
3147
4688
  exports2.bytesFromHexOrBytes = bytesFromHexOrBytes;
3148
4689
  var ethers_1 = require("ethers");
3149
- var km_core_1 = require_dist5();
4690
+ var km_core_1 = require_dist7();
3150
4691
  var EIP712_HASH_FUNCTION = "HASH_FUNCTION_NOT_APPLICABLE";
3151
4692
  async function signSecp256k1PreimageAndVerify(client, signWith, preimage, expectedEvmAddrLower) {
3152
4693
  const preimageHex = (0, ethers_1.hexlify)(preimage).slice(2);
@@ -3193,13 +4734,13 @@ var require_secp256k1_helpers = __commonJS({
3193
4734
  });
3194
4735
 
3195
4736
  // ../key-management/providers/turnkey/typescript/dist/chains/evm.js
3196
- var require_evm2 = __commonJS({
4737
+ var require_evm3 = __commonJS({
3197
4738
  "../key-management/providers/turnkey/typescript/dist/chains/evm.js"(exports2) {
3198
4739
  "use strict";
3199
4740
  Object.defineProperty(exports2, "__esModule", { value: true });
3200
4741
  exports2.TurnkeyEvmSigner = void 0;
3201
4742
  var ethers_1 = require("ethers");
3202
- var km_core_1 = require_dist5();
4743
+ var km_core_1 = require_dist7();
3203
4744
  var signer_base_1 = require_signer_base();
3204
4745
  var secp256k1_helpers_1 = require_secp256k1_helpers();
3205
4746
  var ADDRESS_FORMAT = "ADDRESS_FORMAT_ETHEREUM";
@@ -3315,7 +4856,7 @@ ${msgBytes.length}`);
3315
4856
  });
3316
4857
 
3317
4858
  // ../key-management/providers/turnkey/typescript/dist/chains/solana.js
3318
- var require_solana2 = __commonJS({
4859
+ var require_solana3 = __commonJS({
3319
4860
  "../key-management/providers/turnkey/typescript/dist/chains/solana.js"(exports2) {
3320
4861
  "use strict";
3321
4862
  var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
@@ -3363,7 +4904,7 @@ var require_solana2 = __commonJS({
3363
4904
  exports2.encodePayload = encodePayload;
3364
4905
  var web3_js_1 = require("@solana/web3.js");
3365
4906
  var bs58_1 = __importDefault(require("bs58"));
3366
- var km_core_1 = require_dist5();
4907
+ var km_core_1 = require_dist7();
3367
4908
  var signer_base_1 = require_signer_base();
3368
4909
  var ADDRESS_FORMAT = "ADDRESS_FORMAT_SOLANA";
3369
4910
  var TurnkeySolanaSigner2 = class {
@@ -3456,7 +4997,7 @@ var require_solana2 = __commonJS({
3456
4997
  });
3457
4998
 
3458
4999
  // ../key-management/providers/turnkey/typescript/dist/chains/tron.js
3459
- var require_tron2 = __commonJS({
5000
+ var require_tron3 = __commonJS({
3460
5001
  "../key-management/providers/turnkey/typescript/dist/chains/tron.js"(exports2) {
3461
5002
  "use strict";
3462
5003
  var __importDefault = exports2 && exports2.__importDefault || function(mod) {
@@ -3468,7 +5009,7 @@ var require_tron2 = __commonJS({
3468
5009
  var bs58_1 = __importDefault(require("bs58"));
3469
5010
  var ethers_1 = require("ethers");
3470
5011
  var node_crypto_1 = require("crypto");
3471
- var km_core_1 = require_dist5();
5012
+ var km_core_1 = require_dist7();
3472
5013
  var signer_base_1 = require_signer_base();
3473
5014
  var secp256k1_helpers_1 = require_secp256k1_helpers();
3474
5015
  var ADDRESS_FORMAT = "ADDRESS_FORMAT_TRON";
@@ -3690,6 +5231,200 @@ var require_users = __commonJS({
3690
5231
  }
3691
5232
  });
3692
5233
 
5234
+ // ../key-management/providers/turnkey/typescript/dist/admin/activities.js
5235
+ var require_activities = __commonJS({
5236
+ "../key-management/providers/turnkey/typescript/dist/admin/activities.js"(exports2) {
5237
+ "use strict";
5238
+ Object.defineProperty(exports2, "__esModule", { value: true });
5239
+ exports2.getRootQuorum = getRootQuorum;
5240
+ exports2.getActivity = getActivity;
5241
+ exports2.listPendingActivities = listPendingActivities;
5242
+ exports2.approvedVoterIds = approvedVoterIds;
5243
+ exports2.approveActivity = approveActivity;
5244
+ async function getRootQuorum(client, organizationId) {
5245
+ const r = await client.query("/public/v1/query/get_organization", { organizationId });
5246
+ const q = r.organizationData?.rootQuorum;
5247
+ if (typeof q?.threshold !== "number") {
5248
+ throw new Error(`get_organization on ${organizationId} returned no rootQuorum.threshold: ${JSON.stringify(r).slice(0, 200)}`);
5249
+ }
5250
+ return { threshold: q.threshold, userIds: q.userIds ?? [] };
5251
+ }
5252
+ async function getActivity(client, organizationId, activityId) {
5253
+ const r = await client.query("/public/v1/query/get_activity", {
5254
+ organizationId,
5255
+ activityId
5256
+ });
5257
+ if (!r.activity?.id) {
5258
+ throw new Error(`get_activity returned no activity for ${activityId} in ${organizationId}`);
5259
+ }
5260
+ return r.activity;
5261
+ }
5262
+ async function listPendingActivities(client, organizationId) {
5263
+ const r = await client.query("/public/v1/query/list_activities", { organizationId, filterByStatus: ["ACTIVITY_STATUS_CONSENSUS_NEEDED"] });
5264
+ return r.activities ?? [];
5265
+ }
5266
+ function approvedVoterIds(activity) {
5267
+ const ids = (activity.votes ?? []).filter((v) => v.selection === "VOTE_SELECTION_APPROVED").map((v) => v.userId).filter((id) => Boolean(id));
5268
+ return new Set(ids);
5269
+ }
5270
+ async function approveActivity(client, organizationId, fingerprint) {
5271
+ const r = await client.query("/public/v1/submit/approve_activity", {
5272
+ type: "ACTIVITY_TYPE_APPROVE_ACTIVITY",
5273
+ timestampMs: String(Date.now()),
5274
+ organizationId,
5275
+ parameters: { fingerprint }
5276
+ });
5277
+ if (!r.activity) {
5278
+ throw new Error(`approve_activity returned no activity for ${fingerprint}`);
5279
+ }
5280
+ return r.activity;
5281
+ }
5282
+ }
5283
+ });
5284
+
5285
+ // ../key-management/providers/turnkey/typescript/dist/admin/api-keys.js
5286
+ var require_api_keys = __commonJS({
5287
+ "../key-management/providers/turnkey/typescript/dist/admin/api-keys.js"(exports2) {
5288
+ "use strict";
5289
+ Object.defineProperty(exports2, "__esModule", { value: true });
5290
+ exports2.UnsafeRevocationError = exports2.MAX_API_KEYS_PER_USER = void 0;
5291
+ exports2.getUser = getUser;
5292
+ exports2.listUsers = listUsers;
5293
+ exports2.addApiKeys = addApiKeys;
5294
+ exports2.deleteApiKeys = deleteApiKeys;
5295
+ exports2.isDurableApiKey = isDurableApiKey;
5296
+ exports2.isExpiredApiKey = isExpiredApiKey;
5297
+ exports2.planRevocation = planRevocation;
5298
+ exports2.findApiKeyByPublicKey = findApiKeyByPublicKey;
5299
+ exports2.MAX_API_KEYS_PER_USER = 10;
5300
+ async function getUser(client, organizationId, userId) {
5301
+ const r = await client.query("/public/v1/query/get_user", {
5302
+ organizationId,
5303
+ userId
5304
+ });
5305
+ if (!r.user?.userId) {
5306
+ throw new Error(`get_user returned no user for ${userId} in ${organizationId}`);
5307
+ }
5308
+ return normalizeUser(r.user);
5309
+ }
5310
+ async function listUsers(client, organizationId) {
5311
+ const r = await client.query("/public/v1/query/list_users", {
5312
+ organizationId
5313
+ });
5314
+ return (r.users ?? []).map(normalizeUser);
5315
+ }
5316
+ async function addApiKeys(client, input) {
5317
+ if (input.apiKeys.length === 0)
5318
+ throw new Error("addApiKeys called with no keys");
5319
+ const result = await client.executeActivity("ACTIVITY_TYPE_CREATE_API_KEYS_V2", "create_api_keys", {
5320
+ userId: input.userId,
5321
+ apiKeys: input.apiKeys.map((k) => ({
5322
+ apiKeyName: k.apiKeyName,
5323
+ publicKey: k.publicKey,
5324
+ curveType: k.curveType ?? "API_KEY_CURVE_P256",
5325
+ ...k.expirationSeconds ? { expirationSeconds: k.expirationSeconds } : {}
5326
+ }))
5327
+ });
5328
+ const ids = result.createApiKeysResult?.apiKeyIds;
5329
+ if (!ids?.length) {
5330
+ throw new Error(`CREATE_API_KEYS_V2 returned no apiKeyIds for user ${input.userId}: ${JSON.stringify(result)}`);
5331
+ }
5332
+ return ids;
5333
+ }
5334
+ async function deleteApiKeys(client, input) {
5335
+ if (input.apiKeyIds.length === 0)
5336
+ throw new Error("deleteApiKeys called with no apiKeyIds");
5337
+ const result = await client.executeActivity("ACTIVITY_TYPE_DELETE_API_KEYS", "delete_api_keys", { userId: input.userId, apiKeyIds: [...input.apiKeyIds] });
5338
+ return result.deleteApiKeysResult?.apiKeyIds ?? [];
5339
+ }
5340
+ function isDurableApiKey(key) {
5341
+ return !key.expirationSeconds;
5342
+ }
5343
+ function isExpiredApiKey(key, nowSeconds) {
5344
+ if (!key.expirationSeconds)
5345
+ return false;
5346
+ const created = Number(key.createdAt?.seconds);
5347
+ const ttl = Number(key.expirationSeconds);
5348
+ if (!Number.isFinite(created) || !Number.isFinite(ttl))
5349
+ return false;
5350
+ return created + ttl <= nowSeconds;
5351
+ }
5352
+ var UnsafeRevocationError = class extends Error {
5353
+ code;
5354
+ constructor(code, message) {
5355
+ super(message);
5356
+ this.code = code;
5357
+ this.name = "UnsafeRevocationError";
5358
+ }
5359
+ };
5360
+ exports2.UnsafeRevocationError = UnsafeRevocationError;
5361
+ function planRevocation(input) {
5362
+ const { user, nowSeconds } = input;
5363
+ const stampingPub = input.stampingPublicKey.toLowerCase();
5364
+ const verifyPub = input.verifyPublicKey?.toLowerCase();
5365
+ const explicitIds = input.explicitIds;
5366
+ if (explicitIds.length === 0) {
5367
+ throw new UnsafeRevocationError("NO_KEY_ID", `No key ids given. Name every key to revoke from "${user.userName}" explicitly, so which key dies never depends on which credential is in the environment.`);
5368
+ }
5369
+ const byId = new Map(user.apiKeys.map((k) => [k.apiKeyId, k]));
5370
+ const unknown = explicitIds.filter((id) => !byId.has(id));
5371
+ if (unknown.length > 0) {
5372
+ throw new UnsafeRevocationError("UNKNOWN_KEY_ID", `--key-id names keys that are not on user "${user.userName}": ${unknown.join(", ")}. They may belong to another user, or already be revoked.`);
5373
+ }
5374
+ const targets = [...new Set(explicitIds)].map((id) => byId.get(id));
5375
+ const revokedIds = new Set(targets.map((k) => k.apiKeyId));
5376
+ const survivors = user.apiKeys.filter((k) => !revokedIds.has(k.apiKeyId));
5377
+ const live = survivors.filter((k) => !isExpiredApiKey(k, nowSeconds));
5378
+ const durableSurvivors = live.filter(isDurableApiKey);
5379
+ const hasPasskey = user.authenticators.length > 0;
5380
+ const stampingKey = user.apiKeys.find((k) => k.credential?.publicKey?.toLowerCase() === stampingPub);
5381
+ if (input.selfRotation && !stampingKey) {
5382
+ throw new UnsafeRevocationError("STAMPING_KEY_NOT_ON_USER", `The public key stamping this request is not among "${user.userName}"'s registered keys, yet Turnkey resolved it to that user. Nothing that protects the surviving key can be trusted in that state. Re-check the credential env vars before revoking anything.`);
5383
+ }
5384
+ const suicidal = targets.find((k) => k.credential?.publicKey?.toLowerCase() === stampingPub);
5385
+ if (suicidal) {
5386
+ throw new UnsafeRevocationError("DELETES_AUTHORIZING_KEY", `${suicidal.apiKeyId} ("${suicidal.apiKeyName}") is the key stamping this request. Stamp with the key that should survive, or name the old key with --key-id.`);
5387
+ }
5388
+ if (verifyPub) {
5389
+ const survivor = user.apiKeys.find((k) => k.credential?.publicKey?.toLowerCase() === verifyPub);
5390
+ if (!survivor) {
5391
+ throw new UnsafeRevocationError("SURVIVOR_NOT_REGISTERED", `--verify-public-key is not registered on "${user.userName}". Run --add first, or check you pasted the public key of the right user.`);
5392
+ }
5393
+ if (revokedIds.has(survivor.apiKeyId)) {
5394
+ throw new UnsafeRevocationError("SURVIVOR_IN_REVOKE_SET", `--verify-public-key resolves to ${survivor.apiKeyId} ("${survivor.apiKeyName}"), which is in the revoke set. That would delete the key you just deployed.`);
5395
+ }
5396
+ }
5397
+ const stampedAt = Number(stampingKey?.createdAt?.seconds);
5398
+ if (!input.force && Number.isFinite(stampedAt)) {
5399
+ const newer = targets.filter((k) => {
5400
+ const created = Number(k.createdAt?.seconds);
5401
+ return Number.isFinite(created) && created > stampedAt;
5402
+ });
5403
+ if (newer.length > 0) {
5404
+ const list = newer.map((k) => `${k.apiKeyId} ("${k.apiKeyName}")`).join(", ");
5405
+ throw new UnsafeRevocationError("DELETES_NEWER_KEY", `${list} was created AFTER the key stamping this request, so this would delete the replacement and keep the key being replaced. Stamp with the NEW key instead (that is what proves it works), or pass --force if deleting the newer key is really the intent.`);
5406
+ }
5407
+ }
5408
+ if (live.length === 0 && !hasPasskey) {
5409
+ const expiredNote = survivors.length > 0 ? " (the remaining key(s) have already expired)" : "";
5410
+ throw new UnsafeRevocationError("NO_WORKING_CREDENTIAL", `This would leave "${user.userName}" with no working API key and no authenticator${expiredNote}, which is unrecoverable \u2014 a parent org cannot add credentials inside a sub-org. Run --add first. There is no --force for this.`);
5411
+ }
5412
+ if (durableSurvivors.length === 0 && !hasPasskey && !input.force) {
5413
+ const deadlines = live.map((k) => `${k.apiKeyId} ("${k.apiKeyName}") expires ${k.expirationSeconds}s after creation`).join("; ");
5414
+ throw new UnsafeRevocationError("ALL_SURVIVORS_EXPIRING", `Every key that would survive on "${user.userName}" has a TTL, so this schedules a lockout rather than causing one now: ${deadlines}. Add a key with no --expiration-seconds first, or pass --force if the expiry is intended.`);
5415
+ }
5416
+ return { targets, survivors, durableSurvivors };
5417
+ }
5418
+ function findApiKeyByPublicKey(user, publicKey) {
5419
+ const want = publicKey.toLowerCase();
5420
+ return user.apiKeys.find((k) => k.credential?.publicKey?.toLowerCase() === want);
5421
+ }
5422
+ function normalizeUser(user) {
5423
+ return { ...user, apiKeys: user.apiKeys ?? [], authenticators: user.authenticators ?? [] };
5424
+ }
5425
+ }
5426
+ });
5427
+
3693
5428
  // ../key-management/providers/turnkey/typescript/dist/admin/wallets.js
3694
5429
  var require_wallets = __commonJS({
3695
5430
  "../key-management/providers/turnkey/typescript/dist/admin/wallets.js"(exports2) {
@@ -4033,6 +5768,19 @@ var require_sender_policies = __commonJS({
4033
5768
  "Ed25519SigVerify111111111111111111111111111"
4034
5769
  // Ed25519 (inner signature verification)
4035
5770
  ];
5771
+ function solanaEscrowPrograms(value) {
5772
+ const raw = value === void 0 ? [] : typeof value === "string" ? [value] : value;
5773
+ const seen = /* @__PURE__ */ new Set();
5774
+ const out = [];
5775
+ for (const entry of raw) {
5776
+ const id = typeof entry === "string" ? entry.trim() : "";
5777
+ if (!id || seen.has(id))
5778
+ continue;
5779
+ seen.add(id);
5780
+ out.push(id);
5781
+ }
5782
+ return out;
5783
+ }
4036
5784
  function buildSenderPolicies(extras, chains) {
4037
5785
  const policies = [];
4038
5786
  policies.push({
@@ -4111,10 +5859,11 @@ var require_sender_policies = __commonJS({
4111
5859
  }
4112
5860
  }
4113
5861
  if (chain.kind === "solana") {
4114
- if (!extras.solanaEscrowProgramId) {
4115
- throw new Error(`Sender extras includes Solana chain but no solanaEscrowProgramId. Set it to Atum's escrow program ID for this deployment.`);
5862
+ const escrowPrograms = solanaEscrowPrograms(extras.solanaEscrowProgramId);
5863
+ if (escrowPrograms.length === 0) {
5864
+ throw new Error(`Sender extras includes Solana chain but no solanaEscrowProgramId. Set it to Atum's escrow program ID for this deployment, or to a list of them.`);
4116
5865
  }
4117
- const allowed = [...SOLANA_STANDARD_PROGRAMS, extras.solanaEscrowProgramId];
5866
+ const allowed = [...SOLANA_STANDARD_PROGRAMS, ...escrowPrograms];
4118
5867
  const list = allowed.map((p) => `'${p}'`).join(", ");
4119
5868
  policies.push({
4120
5869
  policyName: `allowedPrograms (${chain.chainId})`,
@@ -4229,7 +5978,7 @@ var require_extras_policies = __commonJS({
4229
5978
  var sender_policies_1 = require_sender_policies();
4230
5979
  var SPL_TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
4231
5980
  var ASSOCIATED_TOKEN_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
4232
- var EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
5981
+ var EVM_ADDRESS2 = /^0x[0-9a-fA-F]{40}$/;
4233
5982
  var TRON_ADDRESS = /^T[1-9A-HJ-NP-Za-km-z]{33}$/;
4234
5983
  var ALLOWED_EXTRAS_KEYS = [
4235
5984
  "allowedErc20Recipients",
@@ -4249,7 +5998,7 @@ var require_extras_policies = __commonJS({
4249
5998
  }
4250
5999
  }
4251
6000
  if (obj.allowedErc20Recipients != null) {
4252
- validateAddressMap(obj.allowedErc20Recipients, "allowedErc20Recipients", EVM_ADDRESS, source);
6001
+ validateAddressMap(obj.allowedErc20Recipients, "allowedErc20Recipients", EVM_ADDRESS2, source);
4253
6002
  }
4254
6003
  if (obj.allowedTrc20Recipients != null) {
4255
6004
  validateAddressMap(obj.allowedTrc20Recipients, "allowedTrc20Recipients", TRON_ADDRESS, source);
@@ -4448,7 +6197,7 @@ var require_admin = __commonJS({
4448
6197
  "../key-management/providers/turnkey/typescript/dist/admin/index.js"(exports2) {
4449
6198
  "use strict";
4450
6199
  Object.defineProperty(exports2, "__esModule", { value: true });
4451
- exports2.validateExtras = exports2.buildExtrasPolicies = exports2.tronBase58ToEvmHex = exports2.TRON_PERMIT2 = exports2.EVM_PERMIT2 = exports2.buildSenderPolicies = exports2.listPolicies = exports2.derivePoliciesFromAllowlist = exports2.deletePolicy = exports2.buildDenyApproveToNonAllowedSpenderTron = exports2.buildDenyApproveToNonAllowedSpenderEvm = exports2.buildAllowSignRawPayloadPolicy = exports2.applyPolicies = exports2.createWalletWithChainAccounts = exports2.provisionAgentUser = exports2.deleteSubOrganization = exports2.listSubOrganizations = exports2.createSubOrganization = void 0;
6200
+ exports2.validateExtras = exports2.buildExtrasPolicies = exports2.tronBase58ToEvmHex = exports2.TRON_PERMIT2 = exports2.EVM_PERMIT2 = exports2.buildSenderPolicies = exports2.listPolicies = exports2.derivePoliciesFromAllowlist = exports2.deletePolicy = exports2.buildDenyApproveToNonAllowedSpenderTron = exports2.buildDenyApproveToNonAllowedSpenderEvm = exports2.buildAllowSignRawPayloadPolicy = exports2.applyPolicies = exports2.createWalletWithChainAccounts = exports2.planRevocation = exports2.listUsers = exports2.isExpiredApiKey = exports2.isDurableApiKey = exports2.getUser = exports2.findApiKeyByPublicKey = exports2.deleteApiKeys = exports2.addApiKeys = exports2.UnsafeRevocationError = exports2.MAX_API_KEYS_PER_USER = exports2.listPendingActivities = exports2.getRootQuorum = exports2.getActivity = exports2.approvedVoterIds = exports2.approveActivity = exports2.provisionAgentUser = exports2.deleteSubOrganization = exports2.listSubOrganizations = exports2.createSubOrganization = void 0;
4452
6201
  var sub_organizations_1 = require_sub_organizations();
4453
6202
  Object.defineProperty(exports2, "createSubOrganization", { enumerable: true, get: function() {
4454
6203
  return sub_organizations_1.createSubOrganization;
@@ -4465,6 +6214,53 @@ var require_admin = __commonJS({
4465
6214
  Object.defineProperty(exports2, "provisionAgentUser", { enumerable: true, get: function() {
4466
6215
  return users_1.provisionAgentUser;
4467
6216
  } });
6217
+ var activities_1 = require_activities();
6218
+ Object.defineProperty(exports2, "approveActivity", { enumerable: true, get: function() {
6219
+ return activities_1.approveActivity;
6220
+ } });
6221
+ Object.defineProperty(exports2, "approvedVoterIds", { enumerable: true, get: function() {
6222
+ return activities_1.approvedVoterIds;
6223
+ } });
6224
+ Object.defineProperty(exports2, "getActivity", { enumerable: true, get: function() {
6225
+ return activities_1.getActivity;
6226
+ } });
6227
+ Object.defineProperty(exports2, "getRootQuorum", { enumerable: true, get: function() {
6228
+ return activities_1.getRootQuorum;
6229
+ } });
6230
+ Object.defineProperty(exports2, "listPendingActivities", { enumerable: true, get: function() {
6231
+ return activities_1.listPendingActivities;
6232
+ } });
6233
+ var api_keys_1 = require_api_keys();
6234
+ Object.defineProperty(exports2, "MAX_API_KEYS_PER_USER", { enumerable: true, get: function() {
6235
+ return api_keys_1.MAX_API_KEYS_PER_USER;
6236
+ } });
6237
+ Object.defineProperty(exports2, "UnsafeRevocationError", { enumerable: true, get: function() {
6238
+ return api_keys_1.UnsafeRevocationError;
6239
+ } });
6240
+ Object.defineProperty(exports2, "addApiKeys", { enumerable: true, get: function() {
6241
+ return api_keys_1.addApiKeys;
6242
+ } });
6243
+ Object.defineProperty(exports2, "deleteApiKeys", { enumerable: true, get: function() {
6244
+ return api_keys_1.deleteApiKeys;
6245
+ } });
6246
+ Object.defineProperty(exports2, "findApiKeyByPublicKey", { enumerable: true, get: function() {
6247
+ return api_keys_1.findApiKeyByPublicKey;
6248
+ } });
6249
+ Object.defineProperty(exports2, "getUser", { enumerable: true, get: function() {
6250
+ return api_keys_1.getUser;
6251
+ } });
6252
+ Object.defineProperty(exports2, "isDurableApiKey", { enumerable: true, get: function() {
6253
+ return api_keys_1.isDurableApiKey;
6254
+ } });
6255
+ Object.defineProperty(exports2, "isExpiredApiKey", { enumerable: true, get: function() {
6256
+ return api_keys_1.isExpiredApiKey;
6257
+ } });
6258
+ Object.defineProperty(exports2, "listUsers", { enumerable: true, get: function() {
6259
+ return api_keys_1.listUsers;
6260
+ } });
6261
+ Object.defineProperty(exports2, "planRevocation", { enumerable: true, get: function() {
6262
+ return api_keys_1.planRevocation;
6263
+ } });
4468
6264
  var wallets_1 = require_wallets();
4469
6265
  Object.defineProperty(exports2, "createWalletWithChainAccounts", { enumerable: true, get: function() {
4470
6266
  return wallets_1.createWalletWithChainAccounts;
@@ -4515,7 +6311,7 @@ var require_admin = __commonJS({
4515
6311
  });
4516
6312
 
4517
6313
  // ../key-management/providers/turnkey/typescript/dist/index.js
4518
- var require_dist6 = __commonJS({
6314
+ var require_dist8 = __commonJS({
4519
6315
  "../key-management/providers/turnkey/typescript/dist/index.js"(exports2) {
4520
6316
  "use strict";
4521
6317
  var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
@@ -4570,18 +6366,18 @@ var require_dist6 = __commonJS({
4570
6366
  Object.defineProperty(exports2, "noopMeter", { enumerable: true, get: function() {
4571
6367
  return meter_1.noopMeter;
4572
6368
  } });
4573
- var evm_1 = require_evm2();
6369
+ var evm_1 = require_evm3();
4574
6370
  Object.defineProperty(exports2, "TurnkeyEvmSigner", { enumerable: true, get: function() {
4575
6371
  return evm_1.TurnkeyEvmSigner;
4576
6372
  } });
4577
- var solana_1 = require_solana2();
6373
+ var solana_1 = require_solana3();
4578
6374
  Object.defineProperty(exports2, "TurnkeySolanaSigner", { enumerable: true, get: function() {
4579
6375
  return solana_1.TurnkeySolanaSigner;
4580
6376
  } });
4581
6377
  Object.defineProperty(exports2, "encodePayload", { enumerable: true, get: function() {
4582
6378
  return solana_1.encodePayload;
4583
6379
  } });
4584
- var tron_1 = require_tron2();
6380
+ var tron_1 = require_tron3();
4585
6381
  Object.defineProperty(exports2, "TurnkeyTronSigner", { enumerable: true, get: function() {
4586
6382
  return tron_1.TurnkeyTronSigner;
4587
6383
  } });
@@ -4634,11 +6430,12 @@ async function resolveSenderAddresses(cfg) {
4634
6430
  return accounts.map((a) => ({ address: a.address, addressFormat: a.addressFormat }));
4635
6431
  }
4636
6432
  async function signWithTurnkeyClient(client, chainPrefix, cfg, message, messagePrehash) {
6433
+ const pinnedAddress = requirePinnedSender(cfg.pinnedAddress);
4637
6434
  const deps = {
4638
6435
  walletId: cfg.walletId,
4639
6436
  log: cfg.logger ?? import_turnkey_signer.noopLogger,
4640
6437
  discoveryTimeoutMs: cfg.discoveryTimeoutMs ?? DEFAULTS.discoveryTimeoutMs,
4641
- ...cfg.pinnedAddress ? { pinnedAddress: cfg.pinnedAddress } : {}
6438
+ ...pinnedAddress ? { pinnedAddress } : {}
4642
6439
  };
4643
6440
  switch (chainPrefix) {
4644
6441
  case "eip155": {
@@ -4648,7 +6445,11 @@ async function signWithTurnkeyClient(client, chainPrefix, cfg, message, messageP
4648
6445
  return { signature: await signer.signTypedData(domain, types, typedMessage) };
4649
6446
  }
4650
6447
  case "tron": {
4651
- const { domain, types, message: typedMessage } = parsePrehash(messagePrehash, "Tron", message);
6448
+ const {
6449
+ domain,
6450
+ types,
6451
+ message: typedMessage
6452
+ } = parsePrehash(messagePrehash, "Tron", message);
4652
6453
  const signer = new import_turnkey_signer.TurnkeyTronSigner(client, deps);
4653
6454
  await signer.initialize();
4654
6455
  return { signature: await signer.signTypedData(domain, types, typedMessage) };
@@ -4688,23 +6489,29 @@ function parsePrehash(messagePrehash, label, advertisedDigest) {
4688
6489
  }
4689
6490
  const isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
4690
6491
  if (!isObject(parsed) || !isObject(parsed.domain) || !isObject(parsed.types) || !isObject(parsed.message)) {
4691
- throw new Error(`Turnkey ${label} signing: message_prehash must be a JSON object with domain, types and message`);
6492
+ throw new Error(
6493
+ `Turnkey ${label} signing: message_prehash must be a JSON object with domain, types and message`
6494
+ );
4692
6495
  }
4693
6496
  const { EIP712Domain: _derived, ...structTypes } = parsed.types;
4694
- const prehashDigest = import_ethers5.TypedDataEncoder.hash(parsed.domain, structTypes, parsed.message);
6497
+ const domain = parsed.domain;
6498
+ const types = structTypes;
6499
+ const message = parsed.message;
6500
+ const prehashDigest = import_ethers6.TypedDataEncoder.hash(domain, types, message);
4695
6501
  if (prehashDigest.toLowerCase() !== advertisedDigest.toLowerCase()) {
4696
6502
  throw new Error(
4697
6503
  `Turnkey ${label} signing: message_prehash implies digest ${prehashDigest} but message is ${advertisedDigest}`
4698
6504
  );
4699
6505
  }
4700
- return { domain: parsed.domain, types: structTypes, message: parsed.message };
6506
+ return { domain, types, message };
4701
6507
  }
4702
- var import_turnkey_signer, import_ethers5, TURNKEY_API_URL, DEFAULTS;
6508
+ var import_turnkey_signer, import_ethers6, TURNKEY_API_URL, DEFAULTS;
4703
6509
  var init_turnkey_impl = __esm({
4704
6510
  "src/signers/turnkey-impl.ts"() {
4705
6511
  "use strict";
4706
- import_turnkey_signer = __toESM(require_dist6());
4707
- import_ethers5 = require("ethers");
6512
+ import_turnkey_signer = __toESM(require_dist8());
6513
+ import_ethers6 = require("ethers");
6514
+ init_pinned_address();
4708
6515
  TURNKEY_API_URL = "https://api.turnkey.com";
4709
6516
  DEFAULTS = {
4710
6517
  concurrencyLimit: 10,
@@ -4716,6 +6523,7 @@ var init_turnkey_impl = __esm({
4716
6523
 
4717
6524
  // src/cli/send-payment.ts
4718
6525
  var import_commander = require("commander");
6526
+ var import_fs = require("fs");
4719
6527
 
4720
6528
  // src/generated/core/OpenAPI.ts
4721
6529
  var Interceptors = class {
@@ -5192,7 +7000,7 @@ payment.
5192
7000
  `,
5193
7001
  413: "Payment request too large to process",
5194
7002
  500: "Internal server error",
5195
- 503: "A dependency is temporarily unavailable"
7003
+ 503: "The request was not accepted: a dependency is temporarily unavailable, or this operation is paused (`SERVICE_PAUSED`). Nothing was submitted, so the request is safe to retry."
5196
7004
  }
5197
7005
  });
5198
7006
  }
@@ -5277,6 +7085,9 @@ payment.
5277
7085
  *
5278
7086
  * The response includes everything needed to sign and submit a payment, except the signature itself.
5279
7087
  *
7088
+ * Not available on every gateway or every source chain; where it is not, this
7089
+ * returns `501`. Sign the returned request and submit it to `POST /v1/payments`.
7090
+ *
5280
7091
  * @param data The data for the request.
5281
7092
  * @param data.requestBody
5282
7093
  * @returns PreparePaymentResponse Payment request prepared successfully
@@ -5323,11 +7134,30 @@ var AuthorizationsService = class {
5323
7134
  body: data.requestBody,
5324
7135
  mediaType: "application/json",
5325
7136
  errors: {
5326
- 400: "Invalid payment request",
5327
- 404: "Counterparty not found (no registration for the resolved DID)",
5328
- 500: "Internal server error",
5329
- 502: "Counterparty webhook error (HTTP error or connection failure)",
5330
- 504: "Authorization timed out (counterparty did not respond)"
7137
+ 400: `The request was rejected before authorization was attempted, so no
7138
+ authorization outcome exists.
7139
+ `,
7140
+ 401: `The counterparty's proof was rejected (\`PROOF_INVALID\` or \`PROOF_STALE\`).
7141
+ This is an authorization outcome, so the body is an \`AuthorizationResult\`
7142
+ with \`status: error\`.
7143
+ `,
7144
+ 404: `Counterparty not found (no registration for the resolved DID). An
7145
+ authorization outcome, so the body is an \`AuthorizationResult\` with
7146
+ \`status: error\` and \`error_code: COUNTERPARTY_NOT_FOUND\`.
7147
+ `,
7148
+ 500: `Either shape, depending on where the failure happened. A failure before
7149
+ authorization was attempted returns \`ErrorResponse\`. A failure carrying an
7150
+ authorization outcome returns \`AuthorizationResult\` with \`status: error\`.
7151
+ `,
7152
+ 502: `Counterparty webhook error (HTTP error or connection failure). An
7153
+ authorization outcome, so the body is an \`AuthorizationResult\` with
7154
+ \`status: error\` and \`error_code: WEBHOOK_ERROR\` or
7155
+ \`WEBHOOK_CONNECTION_ERROR\`.
7156
+ `,
7157
+ 504: `Authorization timed out (the counterparty did not respond). An
7158
+ authorization outcome, so the body is an \`AuthorizationResult\` with
7159
+ \`status: timeout\`.
7160
+ `
5331
7161
  }
5332
7162
  });
5333
7163
  }
@@ -5354,6 +7184,31 @@ var QuoteRequestsService = class {
5354
7184
  * Collection continues server-side until the quote deadline regardless of the HTTP
5355
7185
  * connection, so quotes remain retrievable via the status endpoint in either mode.
5356
7186
  *
7187
+ * **Idempotency.** `request_id` is the idempotency key, scoped to the source account
7188
+ * and originator — the same key, and the same contract, as POST /v1/payments.
7189
+ * Submitting the same `request_id` again returns the ORIGINAL batch instead of opening
7190
+ * a second one, so a client whose request timed out or failed in transit can safely
7191
+ * re-submit and recover its `quote_request_id`.
7192
+ *
7193
+ * Because a re-submission must be admissible on its own, some fields legitimately
7194
+ * differ between attempts and are excluded from the comparison: `quote_deadline` and
7195
+ * `fulfillment_deadline` (both must be in the future, so a later attempt has to move
7196
+ * them) and the `proof` that covers them. An expired `quote_deadline` on a
7197
+ * re-submission is NOT an error — the request is resolved onto the batch that already
7198
+ * exists rather than used to open one. There is no `sender_auth` to re-sign here: this
7199
+ * endpoint rejects it, because the spend authorization belongs to the award call.
7200
+ *
7201
+ * The collection window belongs to the BATCH, not to the request. Asking again with a
7202
+ * later `quote_deadline` does not extend a window already open; `quote_deadline` in the
7203
+ * response is the batch's own, and `status` says whether collection is still running.
7204
+ *
7205
+ * What must NOT differ is the corridor's economics — source account and asset,
7206
+ * destination accounts and assets, `fulfillment_amount`, and `max_source_amount`.
7207
+ * Re-using one `request_id` for a genuinely different corridor is a client bug that
7208
+ * would otherwise be silently collapsed onto the first batch, returning quotes for a
7209
+ * corridor that was never requested. It is rejected with `409` and
7210
+ * `IDEMPOTENCY_TERMS_MISMATCH`. Use a distinct `request_id` per quote-request.
7211
+ *
5357
7212
  * @param data The data for the request.
5358
7213
  * @param data.requestBody
5359
7214
  * @param data.wait Return a handle immediately (`false`, default) or hold the connection for collected quotes (`true`).
@@ -5373,8 +7228,19 @@ var QuoteRequestsService = class {
5373
7228
  body: data.requestBody,
5374
7229
  mediaType: "application/json",
5375
7230
  errors: {
5376
- 400: "Invalid request",
5377
- 500: "Internal server error"
7231
+ 400: `Invalid request. \`QUOTE_DEADLINE_NOT_FUTURE\` is the one worth planning for: a NEW
7232
+ quote-request whose \`quote_deadline\` has already passed is refused, because there is
7233
+ no window left to collect quotes in. It does not apply to a re-submission \u2014 an
7234
+ already-used \`request_id\` resolves onto the batch that exists and its expired
7235
+ deadline is ignored, which is what makes a retry recoverable.
7236
+ `,
7237
+ 409: `The \`request_id\` has already been used for a quote-request with different
7238
+ economics (\`IDEMPOTENCY_TERMS_MISMATCH\`). Re-submitting one \`request_id\` is how a
7239
+ retry is made safe, so it must identify one batch; use a distinct \`request_id\`
7240
+ per quote-request.
7241
+ `,
7242
+ 500: "Internal server error",
7243
+ 503: "The request was not accepted: a dependency is temporarily unavailable, or this operation is paused (`SERVICE_PAUSED`). Nothing was submitted, so the request is safe to retry."
5378
7244
  }
5379
7245
  });
5380
7246
  }
@@ -5457,6 +7323,43 @@ var QuoteRequestsService = class {
5457
7323
  });
5458
7324
  }
5459
7325
  };
7326
+ var ChainDefaultsService = class {
7327
+ constructor(httpRequest) {
7328
+ this.httpRequest = httpRequest;
7329
+ }
7330
+ /**
7331
+ * Get chain defaults
7332
+ * The addresses needed to build a payment on a chain: the escrow, the accounts named
7333
+ * in the deposit authorization, and the fulfillment verifier. Fetch these rather than
7334
+ * hardcoding them - they change when a chain's contracts are redeployed.
7335
+ *
7336
+ * With `chain_id`, returns that chain. Without it, or with an empty value, returns
7337
+ * every chain the gateway serves, keyed by CAIP-2 chain id.
7338
+ *
7339
+ * A chain that is not fully configured is still returned when asked for by
7340
+ * `chain_id`, with the missing address empty, but is left out of the full listing.
7341
+ * Treat an empty address as a chain you cannot pay on.
7342
+ *
7343
+ * @param data The data for the request.
7344
+ * @param data.chainId CAIP-2 chain identifier. Omit it, or send it empty, to receive every chain the gateway serves, keyed by chain id.
7345
+ * @returns GetDefaultsResult Chain defaults. A single object when `chain_id` was supplied, otherwise an object keyed by CAIP-2 chain id.
7346
+ * @throws ApiError
7347
+ */
7348
+ getDefaults(data = {}) {
7349
+ return this.httpRequest.request({
7350
+ method: "GET",
7351
+ url: "/v1/defaults",
7352
+ query: {
7353
+ chain_id: data.chainId
7354
+ },
7355
+ errors: {
7356
+ 400: "The `chain_id` is not a valid CAIP-2 chain identifier",
7357
+ 404: "The requested chain is not served by this gateway, or - when `chain_id` was omitted - no chain could be resolved at all",
7358
+ 503: "A dependency is temporarily unavailable"
7359
+ }
7360
+ });
7361
+ }
7362
+ };
5460
7363
  var HealthService = class {
5461
7364
  constructor(httpRequest) {
5462
7365
  this.httpRequest = httpRequest;
@@ -5494,19 +7397,126 @@ var PaymentGatewayClient = class {
5494
7397
  }
5495
7398
  });
5496
7399
  this.authorizations = new AuthorizationsService(this.request);
7400
+ this.chainDefaults = new ChainDefaultsService(this.request);
5497
7401
  this.health = new HealthService(this.request);
5498
7402
  this.payments = new PaymentsService(this.request);
5499
7403
  this.quoteRequests = new QuoteRequestsService(this.request);
5500
7404
  }
5501
7405
  };
5502
7406
 
7407
+ // src/errors.ts
7408
+ var GatewayTimeoutError = class extends Error {
7409
+ constructor(baseUrl, timeoutMs) {
7410
+ super(
7411
+ `Gateway at ${baseUrl || "(same origin)"} did not respond within ${formatSeconds(timeoutMs)}`
7412
+ );
7413
+ this.baseUrl = baseUrl;
7414
+ this.timeoutMs = timeoutMs;
7415
+ this.name = "GatewayTimeoutError";
7416
+ }
7417
+ };
7418
+ function formatSeconds(ms) {
7419
+ const seconds = ms / 1e3;
7420
+ return `${Number.isInteger(seconds) ? seconds : seconds.toFixed(1)}s`;
7421
+ }
7422
+ function isGatewayTimeoutError(err) {
7423
+ return err instanceof GatewayTimeoutError;
7424
+ }
7425
+ function isApiError(err) {
7426
+ return err instanceof ApiError;
7427
+ }
7428
+
7429
+ // src/request-timeout.ts
7430
+ var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
7431
+ var DEFAULT_SYNC_WAIT_TIMEOUT_MS = 12e4;
7432
+ var SYNC_HOLD_PATHS = ["/v1/payments", "/v1/payments/awards"];
7433
+ function pathOf(url) {
7434
+ if (!url) return "";
7435
+ const path = url.split("?")[0];
7436
+ const scheme = path.indexOf("://");
7437
+ if (scheme === -1) return path;
7438
+ const host = path.indexOf("/", scheme + 3);
7439
+ return host === -1 ? "" : path.slice(host);
7440
+ }
7441
+ function hasWaitTrueQuery(url) {
7442
+ const query = url?.indexOf("?") ?? -1;
7443
+ if (query === -1) return false;
7444
+ return new URLSearchParams(url.slice(query + 1)).get("wait") === "true";
7445
+ }
7446
+ function isSyncWaitRequest({ method, url, wait }) {
7447
+ if (wait === true || wait === "true" || hasWaitTrueQuery(url)) return true;
7448
+ if (method?.toUpperCase() !== "POST") return false;
7449
+ const path = pathOf(url);
7450
+ return SYNC_HOLD_PATHS.some((held) => path === held || path.endsWith(held));
7451
+ }
7452
+ function ordinaryTimeout(timeouts = {}) {
7453
+ return timeouts.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
7454
+ }
7455
+ function timeoutForRequest(request2, timeouts = {}) {
7456
+ return isSyncWaitRequest(request2) ? timeouts.syncWaitTimeoutMs ?? DEFAULT_SYNC_WAIT_TIMEOUT_MS : ordinaryTimeout(timeouts);
7457
+ }
7458
+ function applyRequestTimeout(timeouts = {}) {
7459
+ return (config2) => ({
7460
+ ...config2,
7461
+ timeout: config2.timeout ?? timeoutForRequest({ method: config2.method, url: config2.url }, timeouts)
7462
+ });
7463
+ }
7464
+ function isAxiosTimeout(error) {
7465
+ const failure = error;
7466
+ if (!failure) return false;
7467
+ if (failure.code === "ECONNABORTED" || failure.code === "ETIMEDOUT") return true;
7468
+ return failure.code === "ERR_BAD_RESPONSE" && /stream has been aborted/i.test(failure.message ?? "");
7469
+ }
7470
+ function translateTimeout(error, baseUrl, fallbackTimeoutMs) {
7471
+ if (!isAxiosTimeout(error)) return error;
7472
+ const configured = error.config?.timeout;
7473
+ return new GatewayTimeoutError(baseUrl, configured ?? fallbackTimeoutMs);
7474
+ }
7475
+
7476
+ // src/timeout-http-request.ts
7477
+ function withRequestTimeout(config2, timeouts) {
7478
+ const request2 = new Interceptors();
7479
+ for (const fn of config2?.interceptors?.request?._fns ?? []) request2.use(fn);
7480
+ request2.use(applyRequestTimeout(timeouts));
7481
+ return {
7482
+ interceptors: { request: request2, response: config2?.interceptors?.response ?? new Interceptors() }
7483
+ };
7484
+ }
7485
+ var TimeoutHttpRequest = class extends AxiosHttpRequest {
7486
+ constructor(config2, timeouts = {}) {
7487
+ super(config2);
7488
+ this.timeouts = timeouts;
7489
+ }
7490
+ request(options) {
7491
+ return new CancelablePromise((resolve2, reject, onCancel) => {
7492
+ const pending = super.request(options);
7493
+ onCancel(() => pending.cancel());
7494
+ pending.then(resolve2, (error) => {
7495
+ const request2 = { method: options.method, url: options.url, wait: options.query?.wait };
7496
+ reject(
7497
+ translateTimeout(error, this.config.BASE, timeoutForRequest(request2, this.timeouts))
7498
+ );
7499
+ });
7500
+ });
7501
+ }
7502
+ };
7503
+ function timeoutHttpRequest(timeouts) {
7504
+ return class extends TimeoutHttpRequest {
7505
+ constructor(config2) {
7506
+ super(config2, timeouts);
7507
+ }
7508
+ };
7509
+ }
7510
+
5503
7511
  // src/chain-adapters/evm.ts
5504
7512
  var import_ethers = require("ethers");
5505
7513
 
5506
7514
  // src/chain-adapters/types.ts
5507
7515
  function assertKeyMatchesSender(matches, sender, derived) {
5508
7516
  if (!matches) {
5509
- throw new Error(`The private key derives ${derived}, which does not match the sender address ${sender}`);
7517
+ throw new Error(
7518
+ `The private key derives ${derived}, which does not match the sender address ${sender}`
7519
+ );
5510
7520
  }
5511
7521
  }
5512
7522
 
@@ -5558,10 +7568,9 @@ var tronAdapter = {
5558
7568
  throw new Error("Invalid private key");
5559
7569
  }
5560
7570
  },
5561
- // Tron addresses are the same secp256k1-derived 20 bytes as EVM. Compare the
5562
- // derived hex directly against the canonical sender; do NOT run normalizeAddress
5563
- // on the derived side — it strips a leading 41, which would corrupt an address
5564
- // whose first byte is 0x41.
7571
+ // Tron addresses are the same secp256k1-derived 20 bytes as EVM. The derived
7572
+ // address is already canonical 20-byte hex, so only the sender side — which
7573
+ // arrives in whichever spelling the caller chose — needs normalizing.
5565
7574
  verifyAddressMatchesKey(privateKey, address) {
5566
7575
  const key = privateKey.startsWith("0x") ? privateKey : "0x" + privateKey;
5567
7576
  const derived = new import_ethers2.ethers.Wallet(key).address;
@@ -5597,24 +7606,135 @@ function secretKeyFromPrivate(privateKey) {
5597
7606
  if (decoded.length === 64) {
5598
7607
  return decoded;
5599
7608
  }
5600
- if (decoded.length === 32) {
5601
- return import_tweetnacl.default.sign.keyPair.fromSeed(decoded).secretKey;
7609
+ if (decoded.length === 32) {
7610
+ return import_tweetnacl.default.sign.keyPair.fromSeed(decoded).secretKey;
7611
+ }
7612
+ throw new Error(
7613
+ `Invalid Solana private key length: expected 32 or 64 bytes, got ${decoded.length}`
7614
+ );
7615
+ }
7616
+
7617
+ // src/chain-adapters/index.ts
7618
+ var adapters = {
7619
+ eip155: evmAdapter,
7620
+ tron: tronAdapter,
7621
+ solana: solanaAdapter
7622
+ };
7623
+ function getChainAdapter(sourceChainId) {
7624
+ const prefix = sourceChainId.split(":")[0]?.toLowerCase() ?? "";
7625
+ const adapter = adapters[prefix];
7626
+ if (!adapter) throw new Error(`Unsupported source chain: ${sourceChainId}`);
7627
+ return adapter;
7628
+ }
7629
+
7630
+ // src/asset-identifier.ts
7631
+ var import_ethers3 = require("ethers");
7632
+ var SHAPE_EXAMPLE = "eip155:421614/erc20:0x...";
7633
+ var NAMESPACE = /^[a-z0-9]+$/;
7634
+ var CHAIN_REFERENCE = /^[a-zA-Z0-9_-]+$/;
7635
+ var ASSET_NAMESPACE = /^[a-z0-9-]{3,8}$/;
7636
+ var ASSET_REFERENCE = /^[-.%a-zA-Z0-9]{1,128}$/;
7637
+ var TOKEN_ID = /^[-.%a-zA-Z0-9]{1,78}$/;
7638
+ var EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
7639
+ var EIP155_REFERENCE = /^[0-9]+$/;
7640
+ var HEX_REFERENCE = /^0[xX][0-9a-fA-F]{1,16}$/;
7641
+ var MAX_ECHO = 120;
7642
+ var MAX_REFERENCE_ECHO = 32;
7643
+ function parseAssetIdentifier(value) {
7644
+ if (typeof value !== "string" || value === "") {
7645
+ throw new Error(shapeError(value));
7646
+ }
7647
+ const firstSlash = value.indexOf("/");
7648
+ if (firstSlash === -1) {
7649
+ throw new Error(shapeError(value));
7650
+ }
7651
+ const chainSegments = value.slice(0, firstSlash).split(":");
7652
+ if (chainSegments.length !== 2) {
7653
+ throw new Error(shapeError(value));
7654
+ }
7655
+ const namespace = chainSegments[0].toLowerCase();
7656
+ const reference = namespace === "tron" ? chainSegments[1].toLowerCase() : chainSegments[1];
7657
+ if (!NAMESPACE.test(namespace) || !CHAIN_REFERENCE.test(reference)) {
7658
+ throw new Error(shapeError(value));
7659
+ }
7660
+ if (namespace === "eip155" && !EIP155_REFERENCE.test(reference)) {
7661
+ throw new Error(eip155ReferenceError(reference, value));
7662
+ }
7663
+ const assetPart = value.slice(firstSlash + 1);
7664
+ const separator = assetPart.indexOf(":");
7665
+ if (separator === -1) {
7666
+ throw new Error(tokenAddressError(value));
7667
+ }
7668
+ const assetNamespace = assetPart.slice(0, separator).toLowerCase();
7669
+ const rest = assetPart.slice(separator + 1);
7670
+ const referenceSlash = rest.indexOf("/");
7671
+ const tokenAddress = referenceSlash === -1 ? rest : rest.slice(0, referenceSlash);
7672
+ const tokenId = referenceSlash === -1 ? void 0 : rest.slice(referenceSlash + 1);
7673
+ if (!ASSET_NAMESPACE.test(assetNamespace)) {
7674
+ throw new Error(tokenAddressError(value));
7675
+ }
7676
+ if (assetNamespace === "slip44") {
7677
+ throw new Error(nativeAssetError(value));
7678
+ }
7679
+ if (!ASSET_REFERENCE.test(tokenAddress)) {
7680
+ throw new Error(tokenAddressError(value));
7681
+ }
7682
+ if (tokenId !== void 0 && !TOKEN_ID.test(tokenId)) {
7683
+ throw new Error(tokenAddressError(value));
7684
+ }
7685
+ assertTokenAddress(namespace, tokenAddress, value);
7686
+ const chainId = `${namespace}:${reference}`;
7687
+ return {
7688
+ chainId,
7689
+ namespace,
7690
+ reference,
7691
+ assetNamespace,
7692
+ tokenAddress,
7693
+ ...tokenId === void 0 ? {} : { tokenId },
7694
+ normalized: `${chainId}/${assetNamespace}:${tokenAddress}${tokenId === void 0 ? "" : `/${tokenId}`}`
7695
+ };
7696
+ }
7697
+ function assetChainId(value) {
7698
+ return parseAssetIdentifier(value).chainId;
7699
+ }
7700
+ function echo(value, limit = MAX_ECHO) {
7701
+ const shown = typeof value === "string" ? value : String(value);
7702
+ return shown.length > limit ? `${shown.slice(0, limit)}\u2026` : shown;
7703
+ }
7704
+ function shapeError(value) {
7705
+ return `Invalid asset identifier "${echo(value)}": expected CAIP-19 "<chain>/<type>:<address>", e.g. ${SHAPE_EXAMPLE}`;
7706
+ }
7707
+ function tokenAddressError(value) {
7708
+ return `Invalid token address in asset "${echo(value)}".`;
7709
+ }
7710
+ function eip155ReferenceError(reference, value) {
7711
+ const prefix = `Invalid eip155 chain id "${echo(reference, MAX_REFERENCE_ECHO)}" in asset "${echo(value)}"`;
7712
+ if (HEX_REFERENCE.test(reference)) {
7713
+ return `${prefix}: use the decimal chain id (${BigInt(reference)}), not hex.`;
7714
+ }
7715
+ return `${prefix}: an eip155 chain id is decimal, e.g. 421614.`;
7716
+ }
7717
+ function nativeAssetError(value) {
7718
+ return `Asset "${echo(value)}" is a native asset (slip44) and has no contract to deposit. Use the wrapped token's erc20 identifier.`;
7719
+ }
7720
+ function assertTokenAddress(namespace, tokenAddress, value) {
7721
+ if (namespace !== "eip155") return;
7722
+ if (!EVM_ADDRESS.test(tokenAddress)) {
7723
+ throw new Error(tokenAddressError(value));
7724
+ }
7725
+ const body = tokenAddress.slice(2);
7726
+ if (body === body.toLowerCase() || body === body.toUpperCase()) return;
7727
+ try {
7728
+ (0, import_ethers3.getAddress)(tokenAddress);
7729
+ } catch {
7730
+ throw new Error(
7731
+ `Token address "${tokenAddress}" has an invalid checksum. Fix the capitalization or use the all-lowercase form.`
7732
+ );
5602
7733
  }
5603
- throw new Error(`Invalid Solana private key length: expected 32 or 64 bytes, got ${decoded.length}`);
5604
7734
  }
5605
7735
 
5606
- // src/chain-adapters/index.ts
5607
- var adapters = {
5608
- "eip155": evmAdapter,
5609
- "tron": tronAdapter,
5610
- "solana": solanaAdapter
5611
- };
5612
- function getChainAdapter(sourceChainId) {
5613
- const prefix = sourceChainId.split(":")[0];
5614
- const adapter = adapters[prefix];
5615
- if (!adapter) throw new Error(`Unsupported source chain: ${sourceChainId}`);
5616
- return adapter;
5617
- }
7736
+ // src/index.ts
7737
+ var import_chain_address = __toESM(require_dist2());
5618
7738
 
5619
7739
  // src/chain-adapters/solana-clock.ts
5620
7740
  var DEFAULT_SOLANA_RPC_URLS = {
@@ -5684,19 +7804,84 @@ async function resolveSolanaIssuedAt(opts) {
5684
7804
  }
5685
7805
 
5686
7806
  // src/index.ts
5687
- var import_payment_request_sender_auth2 = __toESM(require_dist4());
7807
+ var import_payment_request_sender_auth2 = __toESM(require_dist5());
7808
+ var import_chain_address2 = __toESM(require_dist2());
7809
+
7810
+ // src/payment-tracking.ts
7811
+ function isTerminalStatus(status) {
7812
+ return status === "completed" || status === "failed" || status === "cancelled";
7813
+ }
7814
+ var DEFAULT_WAIT_SECONDS = 60;
7815
+ var DEFAULT_WAIT_BUDGET_MS = DEFAULT_WAIT_SECONDS * 1e3;
7816
+ var DEFAULT_POLL_INTERVAL_MS = 2e3;
7817
+ async function waitForTerminalStatus(params) {
7818
+ const {
7819
+ fetchStatus,
7820
+ budgetMs = DEFAULT_WAIT_BUDGET_MS,
7821
+ intervalMs = DEFAULT_POLL_INTERVAL_MS,
7822
+ now = () => Date.now(),
7823
+ signal,
7824
+ // Closes over `signal` so the default wakes on abort instead of sleeping out the interval.
7825
+ sleep = (ms) => defaultSleep(ms, signal),
7826
+ onError
7827
+ } = params;
7828
+ const deadline = now() + budgetMs;
7829
+ let snapshot;
7830
+ let errorCount = 0;
7831
+ while (now() < deadline) {
7832
+ if (signal?.aborted) {
7833
+ return { snapshot, timedOut: true, aborted: true, errorCount };
7834
+ }
7835
+ const remaining = deadline - now();
7836
+ await sleep(Math.min(intervalMs, remaining));
7837
+ if (signal?.aborted) {
7838
+ return { snapshot, timedOut: true, aborted: true, errorCount };
7839
+ }
7840
+ try {
7841
+ snapshot = await fetchStatus();
7842
+ } catch (error) {
7843
+ errorCount += 1;
7844
+ onError?.(error);
7845
+ continue;
7846
+ }
7847
+ if (isTerminalStatus(snapshot.status)) {
7848
+ return { snapshot, timedOut: false, aborted: false, errorCount };
7849
+ }
7850
+ }
7851
+ return { snapshot, timedOut: true, aborted: false, errorCount };
7852
+ }
7853
+ function defaultSleep(ms, signal) {
7854
+ if (!signal) {
7855
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
7856
+ }
7857
+ return new Promise((resolve2) => {
7858
+ const done = () => {
7859
+ clearTimeout(timer);
7860
+ signal.removeEventListener("abort", done);
7861
+ resolve2();
7862
+ };
7863
+ const timer = setTimeout(done, ms);
7864
+ signal.addEventListener("abort", done, { once: true });
7865
+ });
7866
+ }
7867
+
7868
+ // src/index.ts
7869
+ var import_payment_request_token_approval = __toESM(require_dist6());
5688
7870
 
5689
7871
  // src/sender_auth_schemes/evm_permit2.ts
5690
- var import_ethers3 = require("ethers");
5691
- var import_evm_escrow_encoding = __toESM(require_dist2());
7872
+ var import_ethers4 = require("ethers");
7873
+ var import_evm_escrow_encoding = __toESM(require_dist3());
5692
7874
 
5693
7875
  // src/sender_auth_schemes/solana.ts
5694
- var import_ethers4 = require("ethers");
7876
+ var import_ethers5 = require("ethers");
5695
7877
  var import_bs582 = __toESM(require("bs58"));
5696
- var import_solana_escrow_encoding = __toESM(require_dist3());
7878
+ var import_solana_escrow_encoding = __toESM(require_dist4());
7879
+
7880
+ // src/signers/index.ts
7881
+ init_pinned_address();
5697
7882
 
5698
7883
  // src/signers/raw.ts
5699
- var import_payment_request_sender_auth = __toESM(require_dist4());
7884
+ var import_payment_request_sender_auth = __toESM(require_dist5());
5700
7885
  var RawSenderSigner = class {
5701
7886
  constructor(network, privateKey) {
5702
7887
  const adapter = getChainAdapter(network);
@@ -5709,6 +7894,7 @@ var RawSenderSigner = class {
5709
7894
  };
5710
7895
 
5711
7896
  // src/signers/turnkey.ts
7897
+ init_pinned_address();
5712
7898
  async function loadImpl() {
5713
7899
  return Promise.resolve().then(() => (init_turnkey_impl(), turnkey_impl_exports));
5714
7900
  }
@@ -5717,6 +7903,7 @@ var TurnkeySenderSigner = class {
5717
7903
  this.chainPrefix = chainPrefix;
5718
7904
  this.cfg = cfg;
5719
7905
  this.loader = loader;
7906
+ this.pinnedAddress = requirePinnedSender(cfg.pinnedAddress);
5720
7907
  }
5721
7908
  async sign(signedMessage) {
5722
7909
  const impl = await this.loader();
@@ -5727,7 +7914,7 @@ var TurnkeySenderSigner = class {
5727
7914
  walletId: this.cfg.walletId,
5728
7915
  apiPublicKey: this.cfg.apiPublicKey,
5729
7916
  apiPrivateKey: this.cfg.apiPrivateKey,
5730
- ...this.cfg.pinnedAddress ? { pinnedAddress: this.cfg.pinnedAddress } : {},
7917
+ ...this.pinnedAddress ? { pinnedAddress: this.pinnedAddress } : {},
5731
7918
  ...this.cfg.logger ? { logger: this.cfg.logger } : {},
5732
7919
  ...this.cfg.meter ? { meter: this.cfg.meter } : {}
5733
7920
  },
@@ -5739,24 +7926,30 @@ var TurnkeySenderSigner = class {
5739
7926
 
5740
7927
  // src/signers/index.ts
5741
7928
  function createSenderSigner(sourceChainId, opts) {
5742
- const chainPrefix = sourceChainId.split(":")[0];
7929
+ const chainPrefix = sourceChainId.split(":")[0]?.toLowerCase() ?? "";
5743
7930
  if (opts.provider === "turnkey") {
5744
7931
  return new TurnkeySenderSigner(chainPrefix, opts);
5745
7932
  }
7933
+ const pinnedAddress = requirePinnedSender(opts.pinnedAddress);
5746
7934
  const adapter = getChainAdapter(sourceChainId);
5747
7935
  const privateKey = adapter.formatPrivateKey(opts.privateKey);
5748
7936
  adapter.validatePrivateKey?.(opts.privateKey);
5749
- if (opts.pinnedAddress) {
7937
+ if (pinnedAddress) {
5750
7938
  if (!adapter.verifyAddressMatchesKey) {
5751
- throw new Error(`pinnedAddress was provided but the ${sourceChainId} adapter cannot verify the key derives it`);
7939
+ throw new Error(
7940
+ `pinnedAddress was provided but the ${sourceChainId} adapter cannot verify the key derives it`
7941
+ );
5752
7942
  }
5753
- adapter.verifyAddressMatchesKey(privateKey, opts.pinnedAddress);
7943
+ adapter.verifyAddressMatchesKey(privateKey, pinnedAddress);
5754
7944
  }
5755
7945
  return new RawSenderSigner(sourceChainId, opts.privateKey);
5756
7946
  }
5757
7947
 
5758
7948
  // src/index.ts
5759
7949
  var PAYMENT_REQUEST_VERSION = "1.0";
7950
+ function assertPayableAccount(assetIdentifier, account) {
7951
+ (0, import_chain_address.validate)(assetChainId(assetIdentifier), account);
7952
+ }
5760
7953
  var defaultGateway = "https://payment-gw.production-testnet.atum.xyz";
5761
7954
  var OpenAPI2 = { ...OpenAPI, BASE: defaultGateway };
5762
7955
  var DEFAULT_QUOTE_DEADLINE_SECONDS = 5;
@@ -5773,10 +7966,14 @@ function resolveDeadlines(params, defaultQuoteSeconds) {
5773
7966
  const quoteDeadlineSeconds = params.quoteDeadlineSeconds ?? defaultQuoteSeconds;
5774
7967
  const fulfillmentDeadlineSeconds = params.fulfillmentDeadlineSeconds ?? DEFAULT_FULFILLMENT_DEADLINE_SECONDS;
5775
7968
  if (!Number.isFinite(quoteDeadlineSeconds) || !Number.isFinite(fulfillmentDeadlineSeconds)) {
5776
- throw new Error("quoteDeadlineSeconds and fulfillmentDeadlineSeconds must be finite numbers of seconds.");
7969
+ throw new Error(
7970
+ "quoteDeadlineSeconds and fulfillmentDeadlineSeconds must be finite numbers of seconds."
7971
+ );
5777
7972
  }
5778
7973
  if (quoteDeadlineSeconds <= 0 || fulfillmentDeadlineSeconds <= 0) {
5779
- throw new Error("quoteDeadlineSeconds and fulfillmentDeadlineSeconds must be positive numbers of seconds.");
7974
+ throw new Error(
7975
+ "quoteDeadlineSeconds and fulfillmentDeadlineSeconds must be positive numbers of seconds."
7976
+ );
5780
7977
  }
5781
7978
  if (quoteDeadlineSeconds >= fulfillmentDeadlineSeconds) {
5782
7979
  throw new Error(
@@ -5789,18 +7986,67 @@ function resolveDeadlines(params, defaultQuoteSeconds) {
5789
7986
  fulfillment_deadline: new Date(now + fulfillmentDeadlineSeconds * 1e3).toISOString()
5790
7987
  };
5791
7988
  }
7989
+ function defaultsErrorDetail(error) {
7990
+ if (!isApiError(error)) {
7991
+ return error instanceof Error ? error.message : String(error);
7992
+ }
7993
+ const body = error.body;
7994
+ const parts = [];
7995
+ if (typeof body?.code === "string" && body.code.trim() !== "") parts.push(body.code);
7996
+ if (typeof body?.message === "string" && body.message.trim() !== "") parts.push(body.message);
7997
+ const requestId = typeof body?.request_id === "string" && body.request_id.trim() !== "" ? body.request_id : "";
7998
+ if (parts.length > 0) {
7999
+ return `${parts.join(": ")}${requestId === "" ? "" : ` (request_id=${requestId})`}`;
8000
+ }
8001
+ return error.statusText || `HTTP ${error.status}`;
8002
+ }
8003
+ function singleChainOf(response, chainId) {
8004
+ if (typeof response !== "object" || response === null) {
8005
+ throw new Error(
8006
+ `Failed to fetch defaults for chain ${chainId}: the gateway did not return a JSON object. Check that the configured base URL points at the payment gateway.`
8007
+ );
8008
+ }
8009
+ const single = response;
8010
+ if (typeof single.chain_id !== "string") {
8011
+ throw new Error(
8012
+ `Failed to fetch defaults for chain ${chainId}: the gateway answered with defaults for every chain rather than the one requested`
8013
+ );
8014
+ }
8015
+ if (single.chain_id.toLowerCase() !== chainId.toLowerCase()) {
8016
+ throw new Error(
8017
+ `Failed to fetch defaults for chain ${chainId}: the gateway answered with defaults for ` + single.chain_id
8018
+ );
8019
+ }
8020
+ return single;
8021
+ }
5792
8022
  async function assemblePaymentRequest(params) {
5793
- const sourceChainId = params.sourceAsset.split("/")[0];
5794
- const namespace = sourceChainId.split(":")[0];
8023
+ const source = parseAssetIdentifier(params.sourceAsset);
8024
+ const destination = parseAssetIdentifier(params.destinationAsset);
8025
+ const { chainId: sourceChainId, namespace } = source;
5795
8026
  const adapter = getChainAdapter(sourceChainId);
5796
8027
  const nonce = params.nonce ?? (namespace === "solana" ? (0, import_payment_request_sender_auth2.deterministicSolanaNonce)({ requestId: params.requestId, depositor: params.depositor }) : (0, import_payment_request_sender_auth2.deterministicPermitNonce)({ requestId: params.requestId, depositor: params.depositor }));
5797
8028
  const auth = await (0, import_payment_request_sender_auth2.getChainAdapter)(sourceChainId).buildAuthMessage({
5798
- sourceAsset: params.sourceAsset,
8029
+ // Canonicalized: the Tron adapter resolves its Permit2 address by exact chain-id key, so an
8030
+ // uppercase namespace would miss the lookup and fail inside the SDK.
8031
+ sourceAsset: source.normalized,
5799
8032
  depositor: params.depositor,
5800
8033
  // The gateway pins the signed deposit amount to max_source_amount (the cap).
5801
8034
  maxSourceAmount: params.maxSourceAmount,
5802
8035
  requestId: params.requestId,
5803
8036
  sourceDefaults: params.sourceDefaults,
8037
+ // The payee the deposit commits to. Passed as CAIP components, not a composed string:
8038
+ // the adapter composes it through the shared buildEscrowDestination so this producer
8039
+ // and the release signer cannot disagree by a byte. These are the SAME two values that
8040
+ // become paymentRequest.destination[0] below, so the signed commitment and the request
8041
+ // body cannot describe different payees.
8042
+ // Canonicalized for the same reason `sourceAsset` is, and additionally because the claim
8043
+ // three lines up has to be TRUE: destination[0] below carries `destination.normalized`, so
8044
+ // passing the raw string here would sign a commitment over different bytes than the request
8045
+ // body names whenever a caller supplies a non-canonical namespace (e.g. "EIP155:42220").
8046
+ // `normalized` lowercases only the namespaces and the asset namespace — the chain reference
8047
+ // and token address keep their case, so base58 (Solana genesis reference, SPL mint) survives.
8048
+ destinationAsset: destination.normalized,
8049
+ destinationAccount: params.destinationAccount,
5804
8050
  deadline: params.deadline,
5805
8051
  nonce,
5806
8052
  ...namespace === "solana" ? {
@@ -5816,13 +8062,15 @@ async function assemblePaymentRequest(params) {
5816
8062
  version: params.version ?? PAYMENT_REQUEST_VERSION,
5817
8063
  request_id: params.requestId,
5818
8064
  source: {
5819
- asset_identifier: params.sourceAsset,
8065
+ asset_identifier: source.normalized,
5820
8066
  account: params.depositor
5821
8067
  },
5822
- destination: [{
5823
- asset_identifier: params.destinationAsset,
5824
- account: params.destinationAccount
5825
- }],
8068
+ destination: [
8069
+ {
8070
+ asset_identifier: destination.normalized,
8071
+ account: params.destinationAccount
8072
+ }
8073
+ ],
5826
8074
  fulfillment_amount: params.fulfillmentAmount,
5827
8075
  max_source_amount: params.maxSourceAmount,
5828
8076
  quote_deadline: params.quoteDeadline,
@@ -5837,43 +8085,58 @@ async function assemblePaymentRequest(params) {
5837
8085
  ...params.settlerRequirements ? { settler_requirements: params.settlerRequirements } : {},
5838
8086
  sender_auth: {
5839
8087
  message_scheme: auth.messageScheme,
5840
- signed_messages: [{
5841
- message: auth.messageHash,
5842
- message_prehash: auth.messagePrehash,
5843
- signature: ""
5844
- }]
8088
+ signed_messages: [
8089
+ {
8090
+ message: auth.messageHash,
8091
+ message_prehash: auth.messagePrehash,
8092
+ signature: ""
8093
+ }
8094
+ ]
5845
8095
  }
5846
8096
  };
5847
8097
  }
5848
8098
  var PaymentGatewayClient2 = class extends PaymentGatewayClient {
5849
- constructor(config2, HttpRequest = AxiosHttpRequest) {
8099
+ constructor(config2, HttpRequest) {
5850
8100
  const envBase = (typeof process !== "undefined" ? process.env.GATEWAY_URL : void 0)?.trim();
5851
8101
  const base = config2?.BASE ?? (envBase || defaultGateway);
5852
- super({ ...config2, BASE: base }, HttpRequest);
5853
- this.baseUrl = base;
8102
+ const timeouts = {
8103
+ timeoutMs: config2?.timeoutMs,
8104
+ syncWaitTimeoutMs: config2?.syncWaitTimeoutMs
8105
+ };
8106
+ super(
8107
+ { ...config2, BASE: base, ...withRequestTimeout(config2, timeouts) },
8108
+ HttpRequest ?? timeoutHttpRequest(timeouts)
8109
+ );
5854
8110
  }
5855
8111
  /**
5856
8112
  * Fetches chain defaults from the payment gateway.
5857
- *
8113
+ *
8114
+ * Goes through the generated typed client, so the request shares the payment calls'
8115
+ * transport: one base URL, one timeout policy, and `/v1/defaults` is described by the
8116
+ * OpenAPI contract rather than assembled by hand here.
8117
+ *
5858
8118
  * @param chainId The CAIP-2 chain identifier (e.g., "eip155:42161")
5859
8119
  * @returns The chain defaults including escrow, quote selector, and fulfillment verifier
5860
8120
  */
5861
8121
  async fetchChainDefaults(chainId) {
5862
- const response = await fetch(`${this.baseUrl}/defaults?chain_id=${chainId}`);
5863
- if (!response.ok) {
5864
- let availableDefaults = null;
5865
- try {
5866
- const allDefaultsResponse = await fetch(`${this.baseUrl}/defaults`);
5867
- if (allDefaultsResponse.ok) {
5868
- availableDefaults = await allDefaultsResponse.json();
8122
+ if (chainId.trim() === "") {
8123
+ throw new Error(
8124
+ 'payment-gateway-client: fetchChainDefaults requires a CAIP-2 chain id, for example "eip155:8453"'
8125
+ );
8126
+ }
8127
+ let response;
8128
+ try {
8129
+ response = await this.chainDefaults.getDefaults({ chainId });
8130
+ } catch (error) {
8131
+ if (isGatewayTimeoutError(error)) throw error;
8132
+ throw new Error(
8133
+ `Failed to fetch defaults for chain ${chainId}: ${defaultsErrorDetail(error)}`,
8134
+ {
8135
+ cause: error
5869
8136
  }
5870
- } catch {
5871
- }
5872
- const error = new Error(`Failed to fetch defaults for chain ${chainId}: ${response.statusText}`);
5873
- error.availableDefaults = availableDefaults;
5874
- throw error;
8137
+ );
5875
8138
  }
5876
- const data = await response.json();
8139
+ const data = singleChainOf(response, chainId);
5877
8140
  if (!data.escrow_contract) {
5878
8141
  throw new Error("defaults missing escrow_contract");
5879
8142
  }
@@ -5892,23 +8155,34 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
5892
8155
  if (!data.fulfillment_verifier.endpoint) {
5893
8156
  throw new Error("defaults missing fulfillment_verifier.endpoint");
5894
8157
  }
8158
+ if (typeof data.permit2_contract === "string" && data.permit2_contract.trim() === "") {
8159
+ throw new Error("defaults returned an empty permit2_contract");
8160
+ }
5895
8161
  return {
5896
8162
  escrowContract: data.escrow_contract,
5897
8163
  quoteSelector: data.quote_selector,
5898
8164
  fulfillmentVerifierAccount: data.fulfillment_verifier.account,
5899
8165
  fulfillmentVerifierEndpoint: data.fulfillment_verifier.endpoint,
5900
8166
  fulfillmentProxy: data.fulfillment_proxy,
5901
- permit2Contract: data.permit2_contract,
8167
+ // `?? undefined` normalises a JSON null at the boundary. The declared type is
8168
+ // `string | undefined`, and a consumer testing `!== undefined` or `in` - both
8169
+ // reasonable against that type - would otherwise build an EIP-712 domain around a
8170
+ // null verifyingContract.
8171
+ permit2Contract: data.permit2_contract ?? void 0,
8172
+ // Which deposit witness the escrow on this chain pins (CORE-2033). Absent means the
8173
+ // four-member CORE-2120 witness — see ChainDefaults.depositWitnessVersion for why
8174
+ // absence is the permissive default. EVM/Tron only; Solana uses the svm_* fields below.
8175
+ depositWitnessVersion: data.deposit_witness_version ?? void 0,
5902
8176
  // V3 Solana escrow domain separation. Present only for Solana
5903
8177
  // source chains; the Solana adapter requires them to build the deposit hash.
5904
- svmSignatureClusterId: data.svm_signature_cluster_id,
5905
- svmSignatureDomainVersion: data.svm_signature_domain_version
8178
+ svmSignatureClusterId: data.svm_signature_cluster_id ?? void 0,
8179
+ svmSignatureDomainVersion: data.svm_signature_domain_version ?? void 0
5906
8180
  };
5907
8181
  }
5908
8182
  /**
5909
8183
  * Prepares a payment request with defaults, ready for signing.
5910
8184
  *
5911
- * By default this resolves the corridor addresses from the gateway `/defaults`
8185
+ * By default this resolves the corridor addresses from the gateway `/v1/defaults`
5912
8186
  * endpoint. It reaches the gateway only for what the caller has NOT already
5913
8187
  * supplied via `resolvedDefaults`: supply `resolvedDefaults.source` to skip the
5914
8188
  * source-chain fetch and `resolvedDefaults.destination` to skip the destination
@@ -5938,10 +8212,14 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
5938
8212
  * @returns A complete PaymentRequest object without the signature
5939
8213
  */
5940
8214
  async preparePaymentRequest(params) {
8215
+ assertPayableAccount(params.destinationAsset, params.destinationAccount);
5941
8216
  const now = (params.now ?? Date.now)();
5942
- const { quote_deadline, fulfillment_deadline } = resolveDeadlines({ ...params, now: () => now }, DEFAULT_PAYMENT_QUOTE_DEADLINE_SECONDS);
5943
- const sourceChainId = params.sourceAsset.split("/")[0];
5944
- const destChainId = params.destinationAsset.split("/")[0];
8217
+ const { quote_deadline, fulfillment_deadline } = resolveDeadlines(
8218
+ { ...params, now: () => now },
8219
+ DEFAULT_PAYMENT_QUOTE_DEADLINE_SECONDS
8220
+ );
8221
+ const sourceChainId = assetChainId(params.sourceAsset);
8222
+ const destChainId = assetChainId(params.destinationAsset);
5945
8223
  const [sourceDefaults, fulfillmentProxy] = await Promise.all([
5946
8224
  params.resolvedDefaults?.source ?? this.fetchChainDefaults(sourceChainId),
5947
8225
  params.resolvedDefaults?.destination?.fulfillmentProxy ?? this.fetchChainDefaults(destChainId).then((d) => d.fulfillmentProxy)
@@ -6011,7 +8289,7 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
6011
8289
  * defaults and populates the SAME contract fields (`escrow_contract_address`,
6012
8290
  * `quote_selector`, `fulfillment_verifier`, `fulfillment_proxy`). These are not
6013
8291
  * optional in practice: the gateway requires `fulfillment_verifier` to build the
6014
- * QuoteRequested event it broadcasts to settlers, so the quote-request body
8292
+ * request event it broadcasts to settlers, so the quote-request body
6015
8293
  * must carry the identical contract fields the payment flow does. The ONLY
6016
8294
  * field this drops relative to `preparePaymentRequest` is `sender_auth`, which
6017
8295
  * is supplied at award time (quote-time is unauthenticated — no signing, no
@@ -6021,26 +8299,38 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
6021
8299
  * @returns A complete `CreateQuoteRequest` body (no signature step needed)
6022
8300
  */
6023
8301
  async prepareQuoteRequest(params) {
6024
- const { quote_deadline, fulfillment_deadline } = resolveDeadlines(params, DEFAULT_QUOTE_DEADLINE_SECONDS);
6025
- const sourceChainId = params.sourceAsset.split("/")[0];
6026
- const destChainId = params.destinationAsset.split("/")[0];
8302
+ assertPayableAccount(params.destinationAsset, params.destinationAccount);
8303
+ if (!params.requestId) {
8304
+ throw new Error(
8305
+ "payment-gateway-client: requestId is required \u2014 it is the idempotency key the gateway dedups on; supply a stable id per logical quote-request and reuse it on retry"
8306
+ );
8307
+ }
8308
+ const { quote_deadline, fulfillment_deadline } = resolveDeadlines(
8309
+ params,
8310
+ DEFAULT_QUOTE_DEADLINE_SECONDS
8311
+ );
8312
+ const source = parseAssetIdentifier(params.sourceAsset);
8313
+ const destination = parseAssetIdentifier(params.destinationAsset);
8314
+ const sourceChainId = source.chainId;
8315
+ const destChainId = destination.chainId;
6027
8316
  const [sourceDefaults, destDefaults] = await Promise.all([
6028
8317
  this.fetchChainDefaults(sourceChainId),
6029
8318
  this.fetchChainDefaults(destChainId)
6030
8319
  ]);
6031
8320
  const contractOverrides = getChainAdapter(sourceChainId).resolveContractOverrides?.(sourceDefaults);
6032
- const requestId = params.requestId || `${params.requestIdPrefix || "quote-gw-sdk"}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
6033
8321
  return {
6034
8322
  version: PAYMENT_REQUEST_VERSION,
6035
- request_id: requestId,
8323
+ request_id: params.requestId,
6036
8324
  source: {
6037
- asset_identifier: params.sourceAsset,
8325
+ asset_identifier: source.normalized,
6038
8326
  account: params.depositor
6039
8327
  },
6040
- destination: [{
6041
- asset_identifier: params.destinationAsset,
6042
- account: params.destinationAccount
6043
- }],
8328
+ destination: [
8329
+ {
8330
+ asset_identifier: destination.normalized,
8331
+ account: params.destinationAccount
8332
+ }
8333
+ ],
6044
8334
  fulfillment_amount: params.fulfillmentAmount,
6045
8335
  max_source_amount: params.maxSourceAmount ?? defaultMaxSourceAmount(params.fulfillmentAmount),
6046
8336
  // Required + originator-supplied: the gateway injects no default and never
@@ -6065,27 +8355,43 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
6065
8355
  }
6066
8356
  };
6067
8357
 
8358
+ // src/cli/cli-input-error.ts
8359
+ var CliInputError = class extends Error {
8360
+ constructor(message) {
8361
+ super(message);
8362
+ this.name = "CliInputError";
8363
+ }
8364
+ };
8365
+
6068
8366
  // src/cli/parse-seconds.ts
6069
8367
  function parseSeconds(optionName) {
6070
8368
  return (value) => {
6071
8369
  if (!/^-?\d+$/.test(value.trim())) {
6072
- throw new Error(`${optionName} must be an integer number of seconds`);
8370
+ throw new CliInputError(`${optionName} must be an integer number of seconds`);
6073
8371
  }
6074
8372
  return Number(value);
6075
8373
  };
6076
8374
  }
6077
8375
 
8376
+ // src/cli/run-cli.ts
8377
+ function runCli(program2, ...parseArgs) {
8378
+ try {
8379
+ program2.parse(...parseArgs);
8380
+ } catch (error) {
8381
+ if (!(error instanceof CliInputError)) throw error;
8382
+ console.error("\n\u274C Error:", error.message);
8383
+ process.exit(1);
8384
+ }
8385
+ }
8386
+
6078
8387
  // src/version.ts
6079
- var PACKAGE_VERSION = true ? "2.2.0" : "0.0.0-dev";
8388
+ var PACKAGE_VERSION = true ? "3.0.0" : "0.0.0-dev";
6080
8389
 
6081
8390
  // src/cli/payment-outcome.ts
6082
8391
  var EXIT_COMPLETED = 0;
6083
8392
  var EXIT_ERROR = 1;
6084
8393
  var EXIT_PENDING = 2;
6085
8394
  var EXIT_TERMINAL_FAILURE = 3;
6086
- function isTerminalStatus(status) {
6087
- return status === "completed" || status === "failed" || status === "cancelled";
6088
- }
6089
8395
  function describePaymentOutcome(input) {
6090
8396
  const { status, paymentId, requestId, idempotentReplay, errorCode } = input;
6091
8397
  const payment = paymentId ? `payment ${paymentId}` : "the payment";
@@ -6110,43 +8416,98 @@ function describePaymentOutcome(input) {
6110
8416
  };
6111
8417
  }
6112
8418
 
6113
- // src/cli/wait-for-terminal.ts
6114
- var DEFAULT_WAIT_SECONDS = 60;
6115
- var DEFAULT_POLL_INTERVAL_MS = 2e3;
6116
- async function waitForTerminalStatus(params) {
8419
+ // src/cli/submit-and-report.ts
8420
+ async function submitAndReport(params) {
6117
8421
  const {
6118
- fetchStatus,
6119
- budgetMs,
6120
- intervalMs = DEFAULT_POLL_INTERVAL_MS,
6121
- now = () => Date.now(),
6122
- sleep = defaultSleep,
6123
- onError
8422
+ client,
8423
+ paymentRequest,
8424
+ requestId,
8425
+ wait = false,
8426
+ waitSeconds = DEFAULT_WAIT_SECONDS,
8427
+ pollIntervalMs,
8428
+ writeOut = (line) => console.log(line),
8429
+ writeErr = (line) => console.error(line)
6124
8430
  } = params;
6125
- const deadline = now() + budgetMs;
6126
- let snapshot;
6127
- let errorCount = 0;
6128
- while (now() < deadline) {
6129
- const remaining = deadline - now();
6130
- await sleep(Math.min(intervalMs, remaining));
6131
- try {
6132
- snapshot = await fetchStatus();
6133
- } catch (error) {
6134
- errorCount += 1;
6135
- onError?.(error);
6136
- continue;
6137
- }
6138
- if (isTerminalStatus(snapshot.status)) {
6139
- return { snapshot, timedOut: false, errorCount };
6140
- }
6141
- }
6142
- return { snapshot, timedOut: true, errorCount };
8431
+ const response = await client.payments.submitPayment({ requestBody: paymentRequest });
8432
+ let reported = response;
8433
+ if (wait && response.payment_id && !isTerminalStatus(response.status)) {
8434
+ writeErr(`waiting up to ${waitSeconds}s for ${response.payment_id} to settle...`);
8435
+ const paymentId = response.payment_id;
8436
+ const waited = await waitForTerminalStatus({
8437
+ budgetMs: waitSeconds * 1e3,
8438
+ intervalMs: pollIntervalMs,
8439
+ fetchStatus: () => client.payments.getPaymentStatus({ paymentId }),
8440
+ // A blip mid-settlement is the worst moment to give up, so report and keep checking.
8441
+ onError: (err) => writeErr(
8442
+ `status check failed, still waiting: ${err instanceof Error ? err.message : String(err)}`
8443
+ )
8444
+ });
8445
+ if (waited.snapshot) {
8446
+ reported = { ...reported, ...waited.snapshot };
8447
+ }
8448
+ if (waited.timedOut) {
8449
+ writeErr(`still not settled after ${waitSeconds}s \u2014 reporting it as pending.`);
8450
+ }
8451
+ }
8452
+ writeOut(JSON.stringify(reported, null, 2));
8453
+ const outcome = {
8454
+ status: reported.status,
8455
+ paymentId: reported.payment_id,
8456
+ requestId,
8457
+ idempotentReplay: reported.idempotent_replay,
8458
+ // Present when the gateway has recorded a reason — which includes the case where this
8459
+ // submission was deduplicated onto a payment that had already failed.
8460
+ errorCode: reported.error?.code
8461
+ };
8462
+ const { exitCode, summary } = describePaymentOutcome(outcome);
8463
+ writeErr(summary);
8464
+ return exitCode;
6143
8465
  }
6144
- function defaultSleep(ms) {
6145
- return new Promise((resolve2) => setTimeout(resolve2, ms));
8466
+
8467
+ // src/cli/option-groups.ts
8468
+ var BUILD_ONLY_OPTIONS = [
8469
+ "--request-id",
8470
+ "--request-id-prefix",
8471
+ "--quote-deadline-seconds",
8472
+ "--fulfillment-deadline-seconds",
8473
+ "--whitelistSettler",
8474
+ "--provider",
8475
+ "--solana-rpc-url"
8476
+ ];
8477
+ function attributeNameOf(flag) {
8478
+ return flag.replace(/^--/, "").replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
6146
8479
  }
6147
8480
 
6148
8481
  // src/cli/send-payment.ts
8482
+ init_pinned_address();
8483
+
8484
+ // src/cli/prompt-private-key.ts
6149
8485
  var readline = __toESM(require("readline"));
8486
+ async function promptPrivateKey() {
8487
+ const rl = readline.createInterface({
8488
+ input: process.stdin,
8489
+ output: process.stdout,
8490
+ terminal: true
8491
+ });
8492
+ return new Promise((resolve2) => {
8493
+ process.stderr.write("Enter private key (input hidden): ");
8494
+ const originalWrite = process.stdout.write;
8495
+ process.stdout.write = function(chunk, _encoding, _callback) {
8496
+ if (chunk === "\n" || chunk === "\r\n") {
8497
+ return originalWrite.apply(process.stdout, arguments);
8498
+ }
8499
+ return true;
8500
+ };
8501
+ rl.question("", (answer) => {
8502
+ process.stdout.write = originalWrite;
8503
+ process.stderr.write("\n");
8504
+ rl.close();
8505
+ resolve2(answer);
8506
+ });
8507
+ rl._writeToOutput = function() {
8508
+ };
8509
+ });
8510
+ }
6150
8511
 
6151
8512
  // src/cli/load-env.ts
6152
8513
  var import_dotenv = require("dotenv");
@@ -6175,7 +8536,64 @@ function loadTurnkeyConfigFromEnv() {
6175
8536
  };
6176
8537
  }
6177
8538
  var program = new import_commander.Command();
6178
- program.name("send-payment").description("Send a cross-chain payment through Atum Payment Gateway").version(PACKAGE_VERSION).argument("<sender>", "Depositor address (e.g., 0xF0D0...)").argument("<amount>", "Amount to send (in smallest units, e.g., 100000 for 0.10 USDC)").argument("<sourceAsset>", "Source asset in CAIP-19 format").argument("<receiver>", "Destination account address").argument("<destinationAsset>", "Destination asset in CAIP-19 format").option("--gateway <url>", "Payment gateway URL (overrides GATEWAY_URL env; default: production-testnet)").option("--request-id <id>", "Idempotency key; seeds the on-chain deposit nonce. Re-run with the SAME id to re-attempt one payment \u2014 it resolves to the original instead of paying twice. Omitted, an id is generated and printed, which makes every bare re-run a SEPARATE payment (a second charge).").option("--request-id-prefix <prefix>", "Custom request ID prefix (default: pmt-gw-cli)").option("--quote-deadline-seconds <n>", `Quote collection window in seconds (default: ${DEFAULT_PAYMENT_QUOTE_DEADLINE_SECONDS})`, parseSeconds("--quote-deadline-seconds")).option("--fulfillment-deadline-seconds <n>", `Settlement horizon in seconds (default: ${DEFAULT_FULFILLMENT_DEADLINE_SECONDS})`, parseSeconds("--fulfillment-deadline-seconds")).option("--whitelistSettler <did>", "Settler DID to whitelist (can be specified multiple times)", collect, []).option("--provider <raw|turnkey>", "Sender signing provider", "raw").option("--wait", "After submitting, keep checking the payment until it settles or fails instead of reporting it as still pending").option("--wait-seconds <n>", `How long --wait keeps checking (default: ${DEFAULT_WAIT_SECONDS}). A convenience bound only \u2014 giving up does not affect the payment`, parseSeconds("--wait-seconds")).option("--solana-rpc-url <url>", "Solana RPC used to read the cluster clock for issued_at (falls back to the SOLANA_RPC_URL env var, then the public endpoint for the cluster)").addHelpText("after", `
8539
+ program.name("send-payment").description(
8540
+ [
8541
+ "Send a cross-chain payment through Atum Payment Gateway.",
8542
+ "",
8543
+ " Normally this prepares, signs and submits in one step. To have the payment",
8544
+ " approved before it is sent, split it in two: --prepare-only writes the signed",
8545
+ " request out, --submit sends one back in.",
8546
+ "",
8547
+ " PREREQUISITE: paying from an EVM or Tron chain needs a one-off ERC-20/TRC-20",
8548
+ " approval of the source token for the Permit2 contract, made by the sender",
8549
+ " before this runs. Without it the payment is built and signed correctly and",
8550
+ " still fails to settle. Run `approve-permit2` to grant it; contract addresses",
8551
+ " are at the end of this help."
8552
+ ].join("\n")
8553
+ ).usage(
8554
+ "[options] <sender> <amount> <sourceAsset> <receiver> <destinationAsset>\n or: send-payment --submit <file> [options]"
8555
+ ).version(PACKAGE_VERSION).argument("[sender]", "Depositor address (e.g., 0xF0D0...)").argument("[amount]", "Amount to send (in smallest units, e.g., 100000 for 0.10 USDC)").argument("[sourceAsset]", "Source asset in CAIP-19 format").argument("[receiver]", "Destination account address").argument("[destinationAsset]", "Destination asset in CAIP-19 format").option(
8556
+ "--gateway <url>",
8557
+ "Payment gateway URL (overrides GATEWAY_URL env; default: production-testnet)"
8558
+ ).option(
8559
+ "--request-id <id>",
8560
+ "Idempotency key; seeds the on-chain deposit nonce. Re-run with the SAME id to re-attempt one payment \u2014 it resolves to the original instead of paying twice. Omitted, an id is generated and printed, which makes every bare re-run a SEPARATE payment (a second charge)."
8561
+ ).option("--request-id-prefix <prefix>", "Custom request ID prefix (default: pmt-gw-cli)").option(
8562
+ "--quote-deadline-seconds <n>",
8563
+ `Quote collection window in seconds (default: ${DEFAULT_PAYMENT_QUOTE_DEADLINE_SECONDS})`,
8564
+ parseSeconds("--quote-deadline-seconds")
8565
+ ).option(
8566
+ "--fulfillment-deadline-seconds <n>",
8567
+ `Settlement horizon in seconds (default: ${DEFAULT_FULFILLMENT_DEADLINE_SECONDS})`,
8568
+ parseSeconds("--fulfillment-deadline-seconds")
8569
+ ).option(
8570
+ "--whitelistSettler <did>",
8571
+ "Settler DID to whitelist (can be specified multiple times)",
8572
+ collect,
8573
+ []
8574
+ ).option("--provider <raw|turnkey>", "Sender signing provider", "raw").option(
8575
+ "--wait",
8576
+ "After submitting, keep checking the payment until it settles or fails instead of reporting it as still pending"
8577
+ ).option(
8578
+ "--wait-seconds <n>",
8579
+ `How long --wait keeps checking (default: ${DEFAULT_WAIT_SECONDS}). A convenience bound only \u2014 giving up does not affect the payment`,
8580
+ parseSeconds("--wait-seconds")
8581
+ ).option(
8582
+ "--solana-rpc-url <url>",
8583
+ "Solana RPC used to read the cluster clock for issued_at (falls back to the SOLANA_RPC_URL env var, then the public endpoint for the cluster)"
8584
+ ).addOption(
8585
+ new import_commander.Option(
8586
+ "--prepare-only",
8587
+ "Build and sign the payment request, print it, and stop without submitting. For inspecting an authorization, or for review before paying. Send it later with --submit"
8588
+ ).conflicts(["wait", "waitSeconds"])
8589
+ ).addOption(
8590
+ new import_commander.Option(
8591
+ "--submit <file>",
8592
+ "Submit a request built earlier by --prepare-only, instead of building one. Signs nothing and needs no private key. Use - to read stdin"
8593
+ ).conflicts(["prepareOnly", ...BUILD_ONLY_OPTIONS.map(attributeNameOf)])
8594
+ ).addHelpText(
8595
+ "after",
8596
+ `
6179
8597
  CAIP-19 Examples:
6180
8598
  EVM ERC20: eip155:42161/erc20:0xaf88d065e77c8cC2239327C5EDb3A432268e5831
6181
8599
  Tron TRC20: tron:shasta/trc20:TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs
@@ -6195,6 +8613,34 @@ Output:
6195
8613
  With --wait the JSON is printed once the wait ends, reporting the payment's state
6196
8614
  as of the last check rather than as of the submit.
6197
8615
 
8616
+ --prepare-only:
8617
+ Builds and signs the request, prints it to stdout, and stops. Nothing is
8618
+ submitted and no payment exists. The document printed is exactly what would
8619
+ have been POSTed, so you can inspect it, have it reviewed, then send it with
8620
+ \`send-payment --submit <file>\` (or pipe it:
8621
+ \`send-payment --prepare-only ... | send-payment --submit -\`).
8622
+
8623
+ It still contacts the gateway, which is where the corridor addresses come from,
8624
+ so it is not an offline mode.
8625
+
8626
+ The file it writes is a signed authorization, not a draft. Anyone holding it can
8627
+ send it with --submit, which needs no key. Treat it like a signed cheque: keep it
8628
+ where you would keep a credential, and delete it once the payment is sent or the
8629
+ request is abandoned.
8630
+
8631
+ Re-preparing with the same --request-id targets the same payment: the deposit nonce
8632
+ comes from the id, so it cannot pay twice. It does not reproduce the same bytes \u2014
8633
+ the deadlines are stamped from the clock and the signature covers them.
8634
+
8635
+ Intending to submit later? The document is only submittable while its quote
8636
+ window is open, and the default is ${DEFAULT_PAYMENT_QUOTE_DEADLINE_SECONDS}s, so widen it with
8637
+ --quote-deadline-seconds to leave room to read it.
8638
+
8639
+ Widen it by tens of seconds, not minutes. The window is also the auction: the
8640
+ gateway waits it out before choosing a settler, and settler quotes expire on
8641
+ their own, so an over-long window ends in QUOTES_EXPIRED \u2014 which is terminal,
8642
+ and a fresh attempt then needs a NEW --request-id.
8643
+
6198
8644
  Exit codes:
6199
8645
  0 completed \u2014 settled
6200
8646
  2 pending \u2014 accepted, no result yet; follow it with payment-status <payment_id>,
@@ -6204,20 +8650,55 @@ Exit codes:
6204
8650
 
6205
8651
  So \`send-payment ... && <next step>\` runs the next step only for a settled payment.
6206
8652
 
8653
+ The table above describes a SUBMITTED payment, so it does not apply to
8654
+ --prepare-only: there, 0 means the request was built and signed, not that anything
8655
+ was paid. Do not chain a payment-conditional step off a --prepare-only run.
8656
+
6207
8657
  Exit 1 means unknown, not "nothing happened" \u2014 a request that timed out may still
6208
8658
  have been accepted, and you may have no payment_id to look up. Re-run with the same
6209
8659
  --request-id, which resolves to the payment if one was created and creates it if not.
6210
8660
 
6211
8661
  After submission, you can check payment status at eg http://PAYMENT_GW/v1/payments/PAYMENT_ID/status
6212
8662
 
6213
- NOTE: Payments from EVM chains require prior ERC-20 approval on the source
6214
- token for the Permit2 contract (0x000000000022D473030F116dDEE9F6B43aC78BA3 on
6215
- virtually all EVM chains). (And the same applies for Tron/TRC-20, with a
6216
- Permit2 address of TJhMXTHQHeQyMD7TcKQFqAePNgG4b31H9m on mainnet or
6217
- TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp on Shasta)`).action(async (sender, amount, sourceAsset, receiver, destinationAsset, options) => {
8663
+ Permit2 contract addresses, for the approval named under PREREQUISITE above:
8664
+ EVM: 0x000000000022D473030F116dDEE9F6B43aC78BA3 (virtually all chains)
8665
+ Tron mainnet: TJhMXTHQHeQyMD7TcKQFqAePNgG4b31H9m
8666
+ Tron Shasta: TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp`
8667
+ ).action(async (sender, amount, sourceAsset, receiver, destinationAsset, options) => {
6218
8668
  let requestId;
8669
+ let submittedRequest;
6219
8670
  try {
6220
- const sourceChainId = sourceAsset.split("/")[0];
8671
+ const corridor = [sender, amount, sourceAsset, receiver, destinationAsset];
8672
+ const supplied = corridor.filter((value) => value !== void 0).length;
8673
+ if (options.submit && supplied > 0) {
8674
+ throw new Error(
8675
+ "--submit sends a request that was already built, so the corridor arguments do not apply. Drop them, or drop --submit to build a new payment."
8676
+ );
8677
+ }
8678
+ if (!options.submit && supplied < corridor.length) {
8679
+ throw new Error(
8680
+ `send-payment needs five arguments (sender, amount, sourceAsset, receiver, destinationAsset), or --submit <file> to send a request prepared earlier. Got ${supplied}.`
8681
+ );
8682
+ }
8683
+ if (options.submit) {
8684
+ const prepared = await readPaymentRequest(options.submit);
8685
+ submittedRequest = prepared;
8686
+ requestId = prepared.request_id;
8687
+ warnIfQuoteWindowClosed(prepared);
8688
+ console.error(
8689
+ `submitting request_id ${requestId} (quote_deadline ${prepared.quote_deadline})`
8690
+ );
8691
+ const submittedCode = await submitAndReport({
8692
+ client: new PaymentGatewayClient2({ BASE: options.gateway }),
8693
+ paymentRequest: prepared,
8694
+ requestId,
8695
+ wait: options.wait,
8696
+ waitSeconds: options.waitSeconds
8697
+ });
8698
+ process.exit(submittedCode);
8699
+ }
8700
+ requirePinnedSender(sender);
8701
+ const sourceChainId = assetChainId(sourceAsset);
6221
8702
  let privateKey = "";
6222
8703
  let signer;
6223
8704
  if (options.provider === "turnkey") {
@@ -6228,7 +8709,11 @@ TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp on Shasta)`).action(async (sender, amount, so
6228
8709
  });
6229
8710
  } else if (options.provider === "raw") {
6230
8711
  privateKey = process.env.PRIVATE_KEY || await promptPrivateKey();
6231
- signer = createSenderSigner(sourceChainId, { provider: "raw", privateKey, pinnedAddress: sender });
8712
+ signer = createSenderSigner(sourceChainId, {
8713
+ provider: "raw",
8714
+ privateKey,
8715
+ pinnedAddress: sender
8716
+ });
6232
8717
  } else {
6233
8718
  throw new Error(`Unknown --provider '${options.provider}' (expected 'raw' or 'turnkey')`);
6234
8719
  }
@@ -6256,84 +8741,103 @@ TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp on Shasta)`).action(async (sender, amount, so
6256
8741
  delegate_signer: delegateSigner
6257
8742
  };
6258
8743
  }
6259
- console.error(JSON.stringify(paymentRequest, null, 2));
6260
- console.error(`request_id: ${requestId} (re-run with --request-id ${requestId} to retry this same payment)`);
6261
- const response = await client.payments.submitPayment({
6262
- requestBody: paymentRequest
6263
- });
6264
- let reported = response;
6265
- if (options.wait && response.payment_id && !isTerminalStatus(response.status)) {
6266
- const waitSeconds = options.waitSeconds ?? DEFAULT_WAIT_SECONDS;
6267
- console.error(`waiting up to ${waitSeconds}s for ${response.payment_id} to settle...`);
6268
- const paymentId = response.payment_id;
6269
- const waited = await waitForTerminalStatus({
6270
- budgetMs: waitSeconds * 1e3,
6271
- fetchStatus: () => client.payments.getPaymentStatus({ paymentId }),
6272
- // A blip mid-settlement is the worst moment to give up, so report and keep checking.
6273
- onError: (err) => console.error(`status check failed, still waiting: ${err instanceof Error ? err.message : String(err)}`)
6274
- });
6275
- if (waited.snapshot) {
6276
- reported = { ...reported, ...waited.snapshot };
6277
- }
6278
- if (waited.timedOut) {
6279
- console.error(`still not settled after ${waitSeconds}s \u2014 reporting it as pending.`);
6280
- }
8744
+ if (options.prepareOnly) {
8745
+ console.log(JSON.stringify(paymentRequest, null, 2));
8746
+ console.error(
8747
+ `request_id: ${requestId} (re-preparing with this id targets the same payment, but stamps fresh deadlines and a fresh signature, so the document itself will differ)`
8748
+ );
8749
+ console.error(
8750
+ `quote_deadline: ${paymentRequest.quote_deadline} (the gateway refuses this document after that instant; pass --quote-deadline-seconds to widen it)`
8751
+ );
8752
+ console.error(
8753
+ "prepared: nothing was submitted and no payment exists. Send it with `send-payment --submit <file>`."
8754
+ );
8755
+ console.error(
8756
+ "KEEP IT SAFE: this file is a signed authorization for this payment, not a draft. Anyone holding it can send it, with no key. Delete it once the payment is sent or the request is abandoned."
8757
+ );
8758
+ process.exit(EXIT_COMPLETED);
6281
8759
  }
6282
- console.log(JSON.stringify(reported, null, 2));
6283
- const outcome = {
6284
- status: reported.status,
6285
- paymentId: reported.payment_id,
8760
+ console.error(JSON.stringify(paymentRequest, null, 2));
8761
+ console.error(
8762
+ `request_id: ${requestId} (re-run with --request-id ${requestId} to retry this same payment)`
8763
+ );
8764
+ const exitCode = await submitAndReport({
8765
+ client,
8766
+ paymentRequest,
6286
8767
  requestId,
6287
- idempotentReplay: reported.idempotent_replay,
6288
- // Present when the gateway has recorded a reason — which includes the case where this
6289
- // submission was deduplicated onto a payment that had already failed.
6290
- errorCode: reported.error?.code
6291
- };
6292
- const { exitCode, summary } = describePaymentOutcome(outcome);
6293
- console.error(summary);
8768
+ wait: options.wait,
8769
+ waitSeconds: options.waitSeconds
8770
+ });
6294
8771
  process.exit(exitCode);
6295
8772
  } catch (error) {
6296
8773
  if (error instanceof ApiError && error.body) {
6297
8774
  console.log(JSON.stringify(error.body, null, 2));
6298
8775
  } else {
6299
8776
  console.error("\n\u274C Error:", error instanceof Error ? error.message : String(error));
6300
- if (error instanceof Error && error.availableDefaults) {
6301
- console.error("\n\u{1F4CB} Available gateway defaults:");
6302
- console.error(JSON.stringify(error.availableDefaults, null, 2));
6303
- }
6304
8777
  }
6305
8778
  if (requestId) {
6306
- console.error(`request_id: ${requestId} (re-run with --request-id ${requestId} to retry this same payment)`);
8779
+ const windowStillOpen = submittedRequest !== void 0 && quoteWindowOpen(submittedRequest);
8780
+ console.error(
8781
+ options.submit ? windowStillOpen ? `request_id: ${requestId} (the quote window on this file may still be open, so sending it again is the first thing to try)` : `request_id: ${requestId} (this file's quote window has closed, so sending it again will be refused. Ask whoever holds the key to prepare a fresh request with --request-id ${requestId}: that targets this same payment, so it cannot pay twice)` : `request_id: ${requestId} (re-run with --request-id ${requestId} to retry this same payment)`
8782
+ );
6307
8783
  }
6308
8784
  process.exit(EXIT_ERROR);
6309
8785
  }
6310
8786
  });
6311
- async function promptPrivateKey() {
6312
- const rl = readline.createInterface({
6313
- input: process.stdin,
6314
- output: process.stdout,
6315
- terminal: true
6316
- });
6317
- return new Promise((resolve2) => {
6318
- process.stderr.write("Enter private key (input hidden): ");
6319
- const originalWrite = process.stdout.write;
6320
- process.stdout.write = function(chunk, encoding, callback) {
6321
- if (chunk === "\n" || chunk === "\r\n") {
6322
- return originalWrite.apply(process.stdout, arguments);
6323
- }
6324
- return true;
6325
- };
6326
- rl.question("", (answer) => {
6327
- process.stdout.write = originalWrite;
6328
- process.stderr.write("\n");
6329
- rl.close();
6330
- resolve2(answer);
6331
- });
6332
- rl._writeToOutput = function() {
6333
- };
6334
- });
8787
+ async function readPaymentRequest(file) {
8788
+ if (file === "-" && process.stdin.isTTY) {
8789
+ throw new Error("--submit - reads stdin, but nothing is piped in. Pass a file path instead");
8790
+ }
8791
+ const raw = file === "-" ? await readStdin() : (0, import_fs.readFileSync)(file, "utf8");
8792
+ if (raw.trim() === "") {
8793
+ throw new Error(
8794
+ file === "-" ? "nothing arrived on stdin. Pipe a prepared request in, or pass a file path instead" : `${file} is empty`
8795
+ );
8796
+ }
8797
+ let parsed;
8798
+ try {
8799
+ parsed = JSON.parse(raw);
8800
+ } catch (error) {
8801
+ throw new Error(
8802
+ `${file === "-" ? "stdin" : file} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
8803
+ { cause: error }
8804
+ );
8805
+ }
8806
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
8807
+ throw new Error(`${file === "-" ? "stdin" : file} does not hold a PaymentRequest object`);
8808
+ }
8809
+ const request2 = parsed;
8810
+ if (!request2.request_id) {
8811
+ throw new Error(
8812
+ "this does not look like a PaymentRequest: no request_id. Produce one with `send-payment --prepare-only`"
8813
+ );
8814
+ }
8815
+ const signature = request2.sender_auth?.signed_messages?.[0]?.signature;
8816
+ if (!signature) {
8817
+ throw new Error(
8818
+ "this request carries no sender_auth signature, so it cannot be submitted. `send-payment --prepare-only` signs the request it prints; a request built with the SDK needs signPaymentRequest before it is submittable"
8819
+ );
8820
+ }
8821
+ return request2;
8822
+ }
8823
+ async function readStdin() {
8824
+ const chunks = [];
8825
+ for await (const chunk of process.stdin) {
8826
+ chunks.push(chunk);
8827
+ }
8828
+ return Buffer.concat(chunks).toString("utf8");
8829
+ }
8830
+ function quoteWindowOpen(request2) {
8831
+ const deadline = Date.parse(request2.quote_deadline ?? "");
8832
+ return Number.isNaN(deadline) || deadline > Date.now();
8833
+ }
8834
+ function warnIfQuoteWindowClosed(request2) {
8835
+ if (quoteWindowOpen(request2)) return;
8836
+ console.error(
8837
+ `warning: this request's quote_deadline (${request2.quote_deadline}) has passed by this machine's clock, and the gateway refuses a closed quote window. Sending anyway, since the gateway goes by its own clock. If it rejects this, prepare a fresh request \u2014 and give the next one a longer --quote-deadline-seconds, which is an option of the form that builds a request, not of --submit.`
8838
+ );
6335
8839
  }
6336
- program.parse();
8840
+ runCli(program);
6337
8841
  /*! Bundled license information:
6338
8842
 
6339
8843
  @noble/hashes/utils.js: