@atumlabs/payment-gateway-client 2.2.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /*
3
- * Copyright (c) 2026 Atum Labs, Inc. All rights reserved.
4
- * Proprietary and confidential.
5
- * Access and use are governed by the LICENSE file distributed with this package.
6
- * Do not remove, alter, or obscure this notice.
3
+ * Copyright 2026 Atum Labs, Inc.
4
+ * SPDX-License-Identifier: Apache-2.0
7
5
  */
8
6
  "use strict";
9
7
  var __create = Object.create;
@@ -12,11 +10,20 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
10
  var __getOwnPropNames = Object.getOwnPropertyNames;
13
11
  var __getProtoOf = Object.getPrototypeOf;
14
12
  var __hasOwnProp = Object.prototype.hasOwnProperty;
15
- var __esm = (fn, res) => function __init() {
16
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
13
+ var __esm = (fn, res, err) => function __init() {
14
+ if (err) throw err[0];
15
+ try {
16
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
17
+ } catch (e) {
18
+ throw err = [e], e;
19
+ }
17
20
  };
18
21
  var __commonJS = (cb, mod) => function __require() {
19
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
22
+ try {
23
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
24
+ } catch (e) {
25
+ throw mod = 0, e;
26
+ }
20
27
  };
21
28
  var __export = (target, all) => {
22
29
  for (var name in all)
@@ -89,7 +96,7 @@ var require_tron_address = __commonJS({
89
96
  hexAddress = base58ToHex2(address);
90
97
  }
91
98
  hexAddress = hexAddress.replace(/^0x/, "");
92
- if (hexAddress.startsWith(TVM_MAINNET_PREFIX)) {
99
+ if (hexAddress.length === 42 && hexAddress.startsWith(TVM_MAINNET_PREFIX)) {
93
100
  hexAddress = hexAddress.substring(2);
94
101
  }
95
102
  if (hexAddress.length !== 40) {
@@ -103,14 +110,62 @@ var require_tron_address = __commonJS({
103
110
  }
104
111
  });
105
112
 
113
+ // ../contracts/tvm/escrow-encoding/typescript/dist/witness-values.js
114
+ var require_witness_values = __commonJS({
115
+ "../contracts/tvm/escrow-encoding/typescript/dist/witness-values.js"(exports2) {
116
+ "use strict";
117
+ Object.defineProperty(exports2, "__esModule", { value: true });
118
+ exports2.normalizeBytes32 = normalizeBytes32;
119
+ exports2.normalizeUint256 = normalizeUint256;
120
+ exports2.maskedChainIdToHex = maskedChainIdToHex;
121
+ var ethers_1 = require("ethers");
122
+ var chain_id_1 = require_chain_id();
123
+ function normalizeBytes32(label, value) {
124
+ let bytes;
125
+ try {
126
+ bytes = (0, ethers_1.getBytes)(value);
127
+ } catch {
128
+ throw new Error(`${label} must be 0x-prefixed hex (32 bytes), got ${JSON.stringify(value)}`);
129
+ }
130
+ if (bytes.length !== 32) {
131
+ throw new Error(`${label} must be exactly 32 bytes, got ${bytes.length}`);
132
+ }
133
+ return (0, ethers_1.hexlify)(bytes);
134
+ }
135
+ function normalizeUint256(label, value) {
136
+ let n;
137
+ try {
138
+ n = BigInt(value);
139
+ } catch {
140
+ throw new Error(`${label} must be an integer (bigint or decimal string), got ${JSON.stringify(value)}`);
141
+ }
142
+ if (n < 0n) {
143
+ throw new Error(`${label} must be non-negative (uint256), got ${n.toString()}`);
144
+ }
145
+ return n.toString();
146
+ }
147
+ function maskedChainIdToHex(chainId) {
148
+ if (!Number.isSafeInteger(chainId) || chainId < 0) {
149
+ throw new Error(`chainId must be a non-negative safe integer, got ${chainId}`);
150
+ }
151
+ return `0x${(0, chain_id_1.maskChainId)(chainId).toString(16)}`;
152
+ }
153
+ }
154
+ });
155
+
106
156
  // ../contracts/tvm/escrow-encoding/typescript/dist/reserve-encoder.js
107
157
  var require_reserve_encoder = __commonJS({
108
158
  "../contracts/tvm/escrow-encoding/typescript/dist/reserve-encoder.js"(exports2) {
109
159
  "use strict";
110
160
  Object.defineProperty(exports2, "__esModule", { value: true });
161
+ exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE = void 0;
111
162
  exports2.computeReserveDigest = computeReserveDigest;
163
+ exports2.buildTvmReserveTypedDataWithQuoteSource = buildTvmReserveTypedDataWithQuoteSource;
164
+ exports2.computeTvmReserveDigestWithQuoteSource = computeTvmReserveDigestWithQuoteSource;
112
165
  var ethers_1 = require("ethers");
113
166
  var chain_id_1 = require_chain_id();
167
+ var tron_address_1 = require_tron_address();
168
+ var witness_values_1 = require_witness_values();
114
169
  var RESERVE_WITNESS_TYPES = {
115
170
  ReserveWitness: [
116
171
  { name: "paymentId", type: "bytes32" },
@@ -129,6 +184,36 @@ var require_reserve_encoder = __commonJS({
129
184
  settler: input.settler
130
185
  });
131
186
  }
187
+ exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE = {
188
+ ReserveWitness: [
189
+ { name: "depositId", type: "bytes32" },
190
+ { name: "quoteHash", type: "bytes32" },
191
+ { name: "settler", type: "address" },
192
+ { name: "sourceAmount", type: "uint256" }
193
+ ]
194
+ };
195
+ function buildTvmReserveTypedDataWithQuoteSource(input) {
196
+ return {
197
+ types: exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE,
198
+ primaryType: "ReserveWitness",
199
+ domain: {
200
+ name: "Escrow",
201
+ version: "3",
202
+ chainId: (0, witness_values_1.maskedChainIdToHex)(input.chainId),
203
+ verifyingContract: (0, tron_address_1.normalizeAddress)(input.escrowContract)
204
+ },
205
+ message: {
206
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", input.depositId),
207
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", input.quoteHash),
208
+ settler: (0, tron_address_1.normalizeAddress)(input.settler),
209
+ sourceAmount: (0, witness_values_1.normalizeUint256)("sourceAmount", input.sourceAmount)
210
+ }
211
+ };
212
+ }
213
+ function computeTvmReserveDigestWithQuoteSource(input) {
214
+ const prehash = buildTvmReserveTypedDataWithQuoteSource(input);
215
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
216
+ }
132
217
  }
133
218
  });
134
219
 
@@ -155,11 +240,14 @@ var require_deposit_encoder = __commonJS({
155
240
  "../contracts/tvm/escrow-encoding/typescript/dist/deposit-encoder.js"(exports2) {
156
241
  "use strict";
157
242
  Object.defineProperty(exports2, "__esModule", { value: true });
243
+ exports2.MAX_DESTINATION_BYTES = exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION = void 0;
158
244
  exports2.createTvmPermitWitnessTransferFromPrehash = createTvmPermitWitnessTransferFromPrehash2;
159
245
  exports2.hashTvmPermitWitnessTransferFrom = hashTvmPermitWitnessTransferFrom2;
246
+ exports2.createTvmPermitWitnessTransferFromPrehashWithDestination = createTvmPermitWitnessTransferFromPrehashWithDestination;
160
247
  var ethers_1 = require("ethers");
161
248
  var chain_id_1 = require_chain_id();
162
249
  var tron_address_1 = require_tron_address();
250
+ var witness_values_1 = require_witness_values();
163
251
  var PERMIT_WITNESS_TYPES_V2 = {
164
252
  PermitWitnessTransferFrom: [
165
253
  { name: "permitted", type: "TokenPermissions" },
@@ -205,6 +293,180 @@ var require_deposit_encoder = __commonJS({
205
293
  function hashTvmPermitWitnessTransferFrom2(prehash) {
206
294
  return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
207
295
  }
296
+ exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION = {
297
+ PermitWitnessTransferFrom: [
298
+ { name: "permitted", type: "TokenPermissions" },
299
+ { name: "spender", type: "address" },
300
+ { name: "nonce", type: "uint256" },
301
+ { name: "deadline", type: "uint256" },
302
+ { name: "witness", type: "DepositWitness" }
303
+ ],
304
+ TokenPermissions: [
305
+ { name: "token", type: "address" },
306
+ { name: "amount", type: "uint256" }
307
+ ],
308
+ DepositWitness: [
309
+ { name: "depositRequestHash", type: "bytes32" },
310
+ { name: "destination", type: "string" },
311
+ { name: "reserver", type: "address" },
312
+ { name: "releaser", type: "address" }
313
+ ]
314
+ };
315
+ exports2.MAX_DESTINATION_BYTES = 256;
316
+ function assertDestinationWithinBounds(destination) {
317
+ if (destination === "") {
318
+ 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');
319
+ }
320
+ const byteLength = (0, ethers_1.toUtf8Bytes)(destination).length;
321
+ if (byteLength > exports2.MAX_DESTINATION_BYTES) {
322
+ 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`);
323
+ }
324
+ }
325
+ function createTvmPermitWitnessTransferFromPrehashWithDestination(params) {
326
+ assertDestinationWithinBounds(params.destination);
327
+ return {
328
+ types: exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION,
329
+ primaryType: "PermitWitnessTransferFrom",
330
+ domain: {
331
+ name: "Permit2",
332
+ chainId: (0, witness_values_1.maskedChainIdToHex)(params.chainId),
333
+ verifyingContract: (0, tron_address_1.normalizeAddress)(params.permit2Address)
334
+ },
335
+ message: {
336
+ permitted: {
337
+ token: (0, tron_address_1.normalizeAddress)(params.tokenAddress),
338
+ amount: (0, witness_values_1.normalizeUint256)("amount", params.amount)
339
+ },
340
+ spender: (0, tron_address_1.normalizeAddress)(params.spenderAddress),
341
+ nonce: (0, witness_values_1.normalizeUint256)("nonce", params.nonce),
342
+ deadline: (0, witness_values_1.normalizeUint256)("deadline", params.deadline),
343
+ witness: {
344
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", params.depositRequestHash),
345
+ destination: params.destination,
346
+ reserver: (0, tron_address_1.normalizeAddress)(params.reserverAddress),
347
+ releaser: (0, tron_address_1.normalizeAddress)(params.releaserAddress)
348
+ }
349
+ }
350
+ };
351
+ }
352
+ }
353
+ });
354
+
355
+ // ../contracts/tvm/escrow-encoding/typescript/dist/release-encoder.js
356
+ var require_release_encoder = __commonJS({
357
+ "../contracts/tvm/escrow-encoding/typescript/dist/release-encoder.js"(exports2) {
358
+ "use strict";
359
+ Object.defineProperty(exports2, "__esModule", { value: true });
360
+ exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH = void 0;
361
+ exports2.buildTvmReleaseTypedDataWithQuoteHash = buildTvmReleaseTypedDataWithQuoteHash;
362
+ exports2.computeTvmReleaseDigestWithQuoteHash = computeTvmReleaseDigestWithQuoteHash;
363
+ var ethers_1 = require("ethers");
364
+ var tron_address_1 = require_tron_address();
365
+ var witness_values_1 = require_witness_values();
366
+ exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH = {
367
+ ReleaseWitness: [
368
+ { name: "depositId", type: "bytes32" },
369
+ { name: "quoteHash", type: "bytes32" },
370
+ { name: "depositRequestHash", type: "bytes32" },
371
+ { name: "destinationHash", type: "bytes32" },
372
+ { name: "depositor", type: "address" },
373
+ { name: "token", type: "address" },
374
+ { name: "amount", type: "uint256" },
375
+ { name: "feeAmount", type: "uint256" },
376
+ { name: "reserver", type: "address" },
377
+ { name: "releaser", type: "address" },
378
+ { name: "settler", type: "address" }
379
+ ]
380
+ };
381
+ function buildTvmReleaseTypedDataWithQuoteHash(input) {
382
+ const w = input.witness;
383
+ return {
384
+ types: exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH,
385
+ primaryType: "ReleaseWitness",
386
+ domain: {
387
+ name: "Escrow",
388
+ version: "3",
389
+ chainId: (0, witness_values_1.maskedChainIdToHex)(input.chainId),
390
+ verifyingContract: (0, tron_address_1.normalizeAddress)(input.escrowContract)
391
+ },
392
+ message: {
393
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", w.depositId),
394
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", w.quoteHash),
395
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", w.depositRequestHash),
396
+ destinationHash: (0, witness_values_1.normalizeBytes32)("destinationHash", w.destinationHash),
397
+ depositor: (0, tron_address_1.normalizeAddress)(w.depositor),
398
+ token: (0, tron_address_1.normalizeAddress)(w.token),
399
+ amount: (0, witness_values_1.normalizeUint256)("amount", w.amount),
400
+ feeAmount: (0, witness_values_1.normalizeUint256)("feeAmount", w.feeAmount),
401
+ reserver: (0, tron_address_1.normalizeAddress)(w.reserver),
402
+ releaser: (0, tron_address_1.normalizeAddress)(w.releaser),
403
+ settler: (0, tron_address_1.normalizeAddress)(w.settler)
404
+ }
405
+ };
406
+ }
407
+ function computeTvmReleaseDigestWithQuoteHash(input) {
408
+ const prehash = buildTvmReleaseTypedDataWithQuoteHash(input);
409
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
410
+ }
411
+ }
412
+ });
413
+
414
+ // ../contracts/tvm/escrow-encoding/typescript/dist/refund-encoder.js
415
+ var require_refund_encoder = __commonJS({
416
+ "../contracts/tvm/escrow-encoding/typescript/dist/refund-encoder.js"(exports2) {
417
+ "use strict";
418
+ Object.defineProperty(exports2, "__esModule", { value: true });
419
+ exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH = void 0;
420
+ exports2.buildTvmRefundTypedDataWithQuoteHash = buildTvmRefundTypedDataWithQuoteHash;
421
+ exports2.computeTvmRefundDigestWithQuoteHash = computeTvmRefundDigestWithQuoteHash;
422
+ var ethers_1 = require("ethers");
423
+ var tron_address_1 = require_tron_address();
424
+ var witness_values_1 = require_witness_values();
425
+ exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH = {
426
+ RefundWitness: [
427
+ { name: "depositId", type: "bytes32" },
428
+ { name: "quoteHash", type: "bytes32" },
429
+ { name: "depositRequestHash", type: "bytes32" },
430
+ { name: "destinationHash", type: "bytes32" },
431
+ { name: "depositor", type: "address" },
432
+ { name: "token", type: "address" },
433
+ { name: "amount", type: "uint256" },
434
+ { name: "feeAmount", type: "uint256" },
435
+ { name: "reserver", type: "address" },
436
+ { name: "releaser", type: "address" },
437
+ { name: "settler", type: "address" }
438
+ ]
439
+ };
440
+ function buildTvmRefundTypedDataWithQuoteHash(input) {
441
+ const w = input.witness;
442
+ return {
443
+ types: exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH,
444
+ primaryType: "RefundWitness",
445
+ domain: {
446
+ name: "Escrow",
447
+ version: "3",
448
+ chainId: (0, witness_values_1.maskedChainIdToHex)(input.chainId),
449
+ verifyingContract: (0, tron_address_1.normalizeAddress)(input.escrowContract)
450
+ },
451
+ message: {
452
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", w.depositId),
453
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", w.quoteHash),
454
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", w.depositRequestHash),
455
+ destinationHash: (0, witness_values_1.normalizeBytes32)("destinationHash", w.destinationHash),
456
+ depositor: (0, tron_address_1.normalizeAddress)(w.depositor),
457
+ token: (0, tron_address_1.normalizeAddress)(w.token),
458
+ amount: (0, witness_values_1.normalizeUint256)("amount", w.amount),
459
+ feeAmount: (0, witness_values_1.normalizeUint256)("feeAmount", w.feeAmount),
460
+ reserver: (0, tron_address_1.normalizeAddress)(w.reserver),
461
+ releaser: (0, tron_address_1.normalizeAddress)(w.releaser),
462
+ settler: (0, tron_address_1.normalizeAddress)(w.settler)
463
+ }
464
+ };
465
+ }
466
+ function computeTvmRefundDigestWithQuoteHash(input) {
467
+ const prehash = buildTvmRefundTypedDataWithQuoteHash(input);
468
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
469
+ }
208
470
  }
209
471
  });
210
472
 
@@ -213,7 +475,7 @@ var require_dist = __commonJS({
213
475
  "../contracts/tvm/escrow-encoding/typescript/dist/index.js"(exports2) {
214
476
  "use strict";
215
477
  Object.defineProperty(exports2, "__esModule", { value: true });
216
- exports2.hashTvmPermitWitnessTransferFrom = exports2.createTvmPermitWitnessTransferFromPrehash = exports2.computePaymentId = exports2.computeReserveDigest = exports2.normalizeAddress = exports2.base58ToHex = exports2.maskChainId = void 0;
478
+ 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
479
  var chain_id_1 = require_chain_id();
218
480
  Object.defineProperty(exports2, "maskChainId", { enumerable: true, get: function() {
219
481
  return chain_id_1.maskChainId;
@@ -240,6 +502,222 @@ var require_dist = __commonJS({
240
502
  Object.defineProperty(exports2, "hashTvmPermitWitnessTransferFrom", { enumerable: true, get: function() {
241
503
  return deposit_encoder_1.hashTvmPermitWitnessTransferFrom;
242
504
  } });
505
+ var reserve_encoder_2 = require_reserve_encoder();
506
+ Object.defineProperty(exports2, "RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE", { enumerable: true, get: function() {
507
+ return reserve_encoder_2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE;
508
+ } });
509
+ Object.defineProperty(exports2, "buildTvmReserveTypedDataWithQuoteSource", { enumerable: true, get: function() {
510
+ return reserve_encoder_2.buildTvmReserveTypedDataWithQuoteSource;
511
+ } });
512
+ Object.defineProperty(exports2, "computeTvmReserveDigestWithQuoteSource", { enumerable: true, get: function() {
513
+ return reserve_encoder_2.computeTvmReserveDigestWithQuoteSource;
514
+ } });
515
+ var release_encoder_1 = require_release_encoder();
516
+ Object.defineProperty(exports2, "RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH", { enumerable: true, get: function() {
517
+ return release_encoder_1.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH;
518
+ } });
519
+ Object.defineProperty(exports2, "buildTvmReleaseTypedDataWithQuoteHash", { enumerable: true, get: function() {
520
+ return release_encoder_1.buildTvmReleaseTypedDataWithQuoteHash;
521
+ } });
522
+ Object.defineProperty(exports2, "computeTvmReleaseDigestWithQuoteHash", { enumerable: true, get: function() {
523
+ return release_encoder_1.computeTvmReleaseDigestWithQuoteHash;
524
+ } });
525
+ var refund_encoder_1 = require_refund_encoder();
526
+ Object.defineProperty(exports2, "REFUND_WITNESS_TYPES_WITH_QUOTE_HASH", { enumerable: true, get: function() {
527
+ return refund_encoder_1.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH;
528
+ } });
529
+ Object.defineProperty(exports2, "buildTvmRefundTypedDataWithQuoteHash", { enumerable: true, get: function() {
530
+ return refund_encoder_1.buildTvmRefundTypedDataWithQuoteHash;
531
+ } });
532
+ Object.defineProperty(exports2, "computeTvmRefundDigestWithQuoteHash", { enumerable: true, get: function() {
533
+ return refund_encoder_1.computeTvmRefundDigestWithQuoteHash;
534
+ } });
535
+ var deposit_encoder_2 = require_deposit_encoder();
536
+ Object.defineProperty(exports2, "PERMIT_WITNESS_TYPES_WITH_DESTINATION", { enumerable: true, get: function() {
537
+ return deposit_encoder_2.PERMIT_WITNESS_TYPES_WITH_DESTINATION;
538
+ } });
539
+ Object.defineProperty(exports2, "createTvmPermitWitnessTransferFromPrehashWithDestination", { enumerable: true, get: function() {
540
+ return deposit_encoder_2.createTvmPermitWitnessTransferFromPrehashWithDestination;
541
+ } });
542
+ Object.defineProperty(exports2, "MAX_DESTINATION_BYTES", { enumerable: true, get: function() {
543
+ return deposit_encoder_2.MAX_DESTINATION_BYTES;
544
+ } });
545
+ }
546
+ });
547
+
548
+ // ../schemas/declarations/common/chain-address/typescript/dist/index.js
549
+ var require_dist2 = __commonJS({
550
+ "../schemas/declarations/common/chain-address/typescript/dist/index.js"(exports2) {
551
+ "use strict";
552
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
553
+ return mod && mod.__esModule ? mod : { "default": mod };
554
+ };
555
+ Object.defineProperty(exports2, "__esModule", { value: true });
556
+ exports2.InvalidAccountError = exports2.REASONS = exports2.NAMESPACE_SOLANA = exports2.NAMESPACE_TRON = exports2.NAMESPACE_EIP155 = void 0;
557
+ exports2.supportedNamespaces = supportedNamespaces;
558
+ exports2.parse = parse;
559
+ exports2.validate = validate;
560
+ exports2.checkAccount = checkAccount;
561
+ var bs58_1 = __importDefault(require("bs58"));
562
+ var ethers_1 = require("ethers");
563
+ var tvm_escrow_encoding_1 = require_dist();
564
+ exports2.NAMESPACE_EIP155 = "eip155";
565
+ exports2.NAMESPACE_TRON = "tron";
566
+ exports2.NAMESPACE_SOLANA = "solana";
567
+ exports2.REASONS = [
568
+ "EMPTY",
569
+ "SURROUNDING_WHITESPACE",
570
+ "UNSUPPORTED_NAMESPACE",
571
+ "UNPARSEABLE",
572
+ "ZERO"
573
+ ];
574
+ var InvalidAccountError2 = class extends Error {
575
+ reason;
576
+ network;
577
+ account;
578
+ detail;
579
+ constructor(reason, network, account, detail = "") {
580
+ super(messageFor(reason, network, detail));
581
+ this.name = "InvalidAccountError";
582
+ this.reason = reason;
583
+ this.network = network;
584
+ this.account = account;
585
+ this.detail = detail;
586
+ }
587
+ };
588
+ exports2.InvalidAccountError = InvalidAccountError2;
589
+ function messageFor(reason, network, detail) {
590
+ switch (reason) {
591
+ case "EMPTY":
592
+ return "account is required and cannot be empty";
593
+ case "SURROUNDING_WHITESPACE":
594
+ return "account must not contain leading or trailing whitespace";
595
+ case "UNSUPPORTED_NAMESPACE":
596
+ return `no address rules are known for chain ${network}`;
597
+ case "ZERO":
598
+ return `account is the zero address on ${network}, which cannot receive a payout`;
599
+ default:
600
+ return `account is not a valid address for ${network}`;
601
+ }
602
+ }
603
+ function supportedNamespaces() {
604
+ return [exports2.NAMESPACE_EIP155, exports2.NAMESPACE_SOLANA, exports2.NAMESPACE_TRON];
605
+ }
606
+ function trimSurrounding(value) {
607
+ return value.replace(/^[\s\u0085]+|[\s\u0085]+$/gu, "");
608
+ }
609
+ function parse(network, account) {
610
+ if (trimSurrounding(account) === "") {
611
+ throw new InvalidAccountError2("EMPTY", network, account);
612
+ }
613
+ if (account !== trimSurrounding(account)) {
614
+ throw new InvalidAccountError2("SURROUNDING_WHITESPACE", network, account);
615
+ }
616
+ const separator = network.indexOf(":");
617
+ if (separator <= 0) {
618
+ throw new InvalidAccountError2("UNSUPPORTED_NAMESPACE", network, account);
619
+ }
620
+ const namespace = network.slice(0, separator);
621
+ let bytes;
622
+ try {
623
+ switch (namespace) {
624
+ case exports2.NAMESPACE_EIP155:
625
+ bytes = parseEvm(account);
626
+ break;
627
+ case exports2.NAMESPACE_TRON:
628
+ bytes = parseTron(account);
629
+ break;
630
+ case exports2.NAMESPACE_SOLANA:
631
+ bytes = parseSolana(account);
632
+ break;
633
+ default:
634
+ throw new InvalidAccountError2("UNSUPPORTED_NAMESPACE", network, account);
635
+ }
636
+ } catch (error) {
637
+ if (error instanceof InvalidAccountError2)
638
+ throw error;
639
+ throw new InvalidAccountError2("UNPARSEABLE", network, account, error.message);
640
+ }
641
+ return { namespace, bytes };
642
+ }
643
+ function validate(network, account) {
644
+ const parsed = parse(network, account);
645
+ if (isZero(parsed.bytes)) {
646
+ throw new InvalidAccountError2("ZERO", network, account);
647
+ }
648
+ return parsed;
649
+ }
650
+ function checkAccount(network, account) {
651
+ try {
652
+ validate(network, account);
653
+ return null;
654
+ } catch (error) {
655
+ if (error instanceof InvalidAccountError2)
656
+ return error;
657
+ throw error;
658
+ }
659
+ }
660
+ function isZero(bytes) {
661
+ return bytes.length > 0 && bytes.every((one) => one === 0);
662
+ }
663
+ var HEX_40 = /^(0[xX])?[0-9a-fA-F]{40}$/;
664
+ function parseEvm(account) {
665
+ if (!HEX_40.test(account)) {
666
+ throw new Error("expected 40 hex characters, optionally 0x-prefixed");
667
+ }
668
+ const body = account.replace(/^0[xX]/, "");
669
+ const lower = body.toLowerCase();
670
+ if (body !== lower && body !== body.toUpperCase()) {
671
+ if ((0, ethers_1.getAddress)(`0x${lower}`) !== account) {
672
+ throw new Error("mixed-case address fails its EIP-55 checksum");
673
+ }
674
+ }
675
+ return hexToBytes2(lower);
676
+ }
677
+ function parseTron(account) {
678
+ let hexBody;
679
+ if (account.startsWith("T") && account.length === 34) {
680
+ try {
681
+ hexBody = (0, tvm_escrow_encoding_1.base58ToHex)(account);
682
+ } catch (error) {
683
+ throw new Error(`base58 address failed its checksum: ${error.message}`);
684
+ }
685
+ } else if (account.toLowerCase().startsWith("0x41") && account.length === 44) {
686
+ hexBody = account.slice(2);
687
+ } else if (HEX_40.test(account)) {
688
+ return parseEvm(account);
689
+ } else {
690
+ throw new Error("expected a T-prefixed base58 address or 40 hex characters");
691
+ }
692
+ hexBody = hexBody.startsWith("41") ? hexBody.slice(2) : hexBody;
693
+ if (hexBody.length !== 40) {
694
+ throw new Error(`expected 40 hex characters after conversion, got ${hexBody.length}`);
695
+ }
696
+ return hexToBytes2(hexBody);
697
+ }
698
+ function parseSolana(account) {
699
+ let decoded;
700
+ try {
701
+ decoded = bs58_1.default.decode(account);
702
+ } catch {
703
+ throw new Error("expected a 32-byte base58 public key");
704
+ }
705
+ if (decoded.length !== 32) {
706
+ throw new Error(`expected a 32-byte base58 public key, got ${decoded.length} bytes`);
707
+ }
708
+ return decoded;
709
+ }
710
+ var HEX_BODY = /^[0-9a-fA-F]*$/;
711
+ function hexToBytes2(hex) {
712
+ if (hex.length % 2 !== 0 || !HEX_BODY.test(hex)) {
713
+ throw new Error("expected hex characters");
714
+ }
715
+ const out = new Uint8Array(hex.length / 2);
716
+ for (let i = 0; i < out.length; i += 1) {
717
+ out[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
718
+ }
719
+ return out;
720
+ }
243
721
  }
244
722
  });
245
723
 
@@ -251,12 +729,96 @@ var require_types = __commonJS({
251
729
  }
252
730
  });
253
731
 
732
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/destination.js
733
+ var require_destination = __commonJS({
734
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/destination.js"(exports2) {
735
+ "use strict";
736
+ Object.defineProperty(exports2, "__esModule", { value: true });
737
+ exports2.DESTINATION_COMMITMENT_WITNESS_VERSION = exports2.MAX_DESTINATION_BYTES = void 0;
738
+ exports2.usesDestinationCommitment = usesDestinationCommitment;
739
+ exports2.deriveDepositRequestHash = deriveDepositRequestHash;
740
+ exports2.buildEscrowDestination = buildEscrowDestination;
741
+ var ethers_1 = require("ethers");
742
+ exports2.MAX_DESTINATION_BYTES = 256;
743
+ var NAMESPACE_EIP155 = "eip155";
744
+ exports2.DESTINATION_COMMITMENT_WITNESS_VERSION = 4;
745
+ function usesDestinationCommitment(depositWitnessVersion) {
746
+ return depositWitnessVersion === void 0 || depositWitnessVersion >= exports2.DESTINATION_COMMITMENT_WITNESS_VERSION;
747
+ }
748
+ function deriveDepositRequestHash(requestId) {
749
+ if (requestId === "") {
750
+ 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');
751
+ }
752
+ return (0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)(requestId));
753
+ }
754
+ function buildEscrowDestination(assetIdentifier, account) {
755
+ if (assetIdentifier === "") {
756
+ throw new Error("sender_auth: destination asset_identifier is empty");
757
+ }
758
+ if (account === "") {
759
+ throw new Error("sender_auth: destination account is empty");
760
+ }
761
+ if (assetIdentifier.includes("@") || account.includes("@")) {
762
+ 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`);
763
+ }
764
+ const namespace = caip2Namespace(assetIdentifier);
765
+ let asset = assetIdentifier;
766
+ let acct = account;
767
+ if (namespace === NAMESPACE_EIP155) {
768
+ asset = asset.toLowerCase();
769
+ acct = acct.toLowerCase();
770
+ }
771
+ const destination = `${asset}@${acct}`;
772
+ const byteLength = (0, ethers_1.toUtf8Bytes)(destination).length;
773
+ if (byteLength > exports2.MAX_DESTINATION_BYTES) {
774
+ 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`);
775
+ }
776
+ return destination;
777
+ }
778
+ function caip2Namespace(assetIdentifier) {
779
+ const slash = assetIdentifier.indexOf("/");
780
+ const chainPart = slash === -1 ? "" : assetIdentifier.slice(0, slash);
781
+ const assetPart = slash === -1 ? "" : assetIdentifier.slice(slash + 1);
782
+ if (slash === -1 || chainPart === "" || assetPart === "") {
783
+ const looksLegacy = !assetIdentifier.includes("/") && countChar(assetIdentifier, ":") === 2;
784
+ const hint = looksLegacy ? " (this looks like the deprecated `<chain>:<ref>:<asset>` form; migrate it to `<chain>:<ref>/<asset-namespace>:<asset-reference>`)" : "";
785
+ throw new Error(`sender_auth: destination asset_identifier ${JSON.stringify(assetIdentifier)} is not CAIP-19: expected <caip2-chain-id>/<asset-namespace>:<asset-reference>${hint}`);
786
+ }
787
+ const assetColon = assetPart.indexOf(":");
788
+ if (assetColon <= 0 || assetColon === assetPart.length - 1) {
789
+ throw new Error(`sender_auth: destination asset_identifier ${JSON.stringify(assetIdentifier)} has a malformed asset part ${JSON.stringify(assetPart)}: expected <asset-namespace>:<asset-reference>`);
790
+ }
791
+ const assetNamespace = assetPart.slice(0, assetColon);
792
+ if (assetNamespace !== assetNamespace.toLowerCase()) {
793
+ 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`);
794
+ }
795
+ const chainColon = chainPart.indexOf(":");
796
+ if (chainColon <= 0 || chainColon === chainPart.length - 1) {
797
+ throw new Error(`sender_auth: destination asset_identifier ${JSON.stringify(assetIdentifier)} has a malformed chain part ${JSON.stringify(chainPart)}: expected <namespace>:<reference>`);
798
+ }
799
+ const namespace = chainPart.slice(0, chainColon);
800
+ if (namespace !== namespace.toLowerCase()) {
801
+ 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`);
802
+ }
803
+ return namespace;
804
+ }
805
+ function countChar(s, c) {
806
+ let n = 0;
807
+ for (const ch of s) {
808
+ if (ch === c)
809
+ n++;
810
+ }
811
+ return n;
812
+ }
813
+ }
814
+ });
815
+
254
816
  // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/utils.js
255
817
  var require_utils = __commonJS({
256
818
  "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/utils.js"(exports2) {
257
819
  "use strict";
258
820
  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;
821
+ exports2.REQUEST_ID_DOMAIN = exports2.SOLANA_REPLAY_BUCKETS = exports2.SOLANA_REPLAY_SLOTS = exports2.PERMIT_NONCE_DOMAIN = exports2.REPLAY_HORIZON_SECS = void 0;
260
822
  exports2.resolvePermitDeadline = resolvePermitDeadline;
261
823
  exports2.generatePermitNonce = generatePermitNonce;
262
824
  exports2.resolvePermitNonce = resolvePermitNonce;
@@ -264,6 +826,7 @@ var require_utils = __commonJS({
264
826
  exports2.deterministicPermitNonce = deterministicPermitNonce2;
265
827
  exports2.deterministicSolanaNonce = deterministicSolanaNonce2;
266
828
  exports2.deterministicRequestId = deterministicRequestId;
829
+ exports2.parseSourceAsset = parseSourceAsset;
267
830
  exports2.sameAddress = sameAddress;
268
831
  exports2.assertKeyMatchesSender = assertKeyMatchesSender2;
269
832
  exports2.assertToken = assertToken;
@@ -272,8 +835,11 @@ var require_utils = __commonJS({
272
835
  exports2.assertSpender = assertSpender;
273
836
  exports2.assertWitnessRoles = assertWitnessRoles;
274
837
  exports2.assertRolePairComplete = assertRolePairComplete;
838
+ exports2.assertDestination = assertDestination;
839
+ exports2.assertDepositRequestHash = assertDepositRequestHash;
275
840
  exports2.nowSec = nowSec;
276
841
  var ethers_1 = require("ethers");
842
+ var destination_js_1 = require_destination();
277
843
  exports2.REPLAY_HORIZON_SECS = 128;
278
844
  function resolvePermitDeadline(deadline) {
279
845
  return BigInt(deadline);
@@ -288,7 +854,7 @@ var require_utils = __commonJS({
288
854
  }
289
855
  exports2.PERMIT_NONCE_DOMAIN = "atum-permit:v1:";
290
856
  exports2.SOLANA_REPLAY_SLOTS = 235n;
291
- var SOLANA_BUCKET_BITS = 17n;
857
+ exports2.SOLANA_REPLAY_BUCKETS = 256n;
292
858
  function canonicalDepositor(depositor) {
293
859
  const lower = depositor.toLowerCase();
294
860
  return lower.startsWith("0x") ? lower : depositor;
@@ -305,7 +871,7 @@ var require_utils = __commonJS({
305
871
  function deterministicSolanaNonce2(params) {
306
872
  const seed = permitNonceSeed(params.requestId, params.depositor);
307
873
  const slot = seed % exports2.SOLANA_REPLAY_SLOTS;
308
- const bucket = (seed >> 8n) % (1n << SOLANA_BUCKET_BITS);
874
+ const bucket = (seed >> 8n) % exports2.SOLANA_REPLAY_BUCKETS;
309
875
  return bucket << 32n | slot;
310
876
  }
311
877
  exports2.REQUEST_ID_DOMAIN = "atum-request:v1:";
@@ -322,6 +888,17 @@ var require_utils = __commonJS({
322
888
  const digest = (0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)(`${exports2.REQUEST_ID_DOMAIN}${params.anchor}:${canonicalDepositor(params.account)}`));
323
889
  return `${params.prefix}${digest.slice(2, 26)}`;
324
890
  }
891
+ function parseSourceAsset(assetIdentifier) {
892
+ const parts = typeof assetIdentifier === "string" ? assetIdentifier.split("/") : [];
893
+ const nsParts = parts[1]?.split(":");
894
+ if (parts.length === 3 && parts[0] && parts[1] && parts[2]) {
895
+ throw new Error(`sender_auth: source asset ${JSON.stringify(assetIdentifier)} names a token id, which a deposit cannot bind`);
896
+ }
897
+ if (parts.length !== 2 || !parts[0] || !nsParts || nsParts.length !== 2 || !nsParts[0] || !nsParts[1]) {
898
+ throw new Error(`sender_auth: invalid source asset ${JSON.stringify(assetIdentifier)}`);
899
+ }
900
+ return { network: parts[0], asset: nsParts[1] };
901
+ }
325
902
  function sameAddress(a, b) {
326
903
  if (a.startsWith("0x") && b.startsWith("0x")) {
327
904
  return a.toLowerCase() === b.toLowerCase();
@@ -363,6 +940,17 @@ var require_utils = __commonJS({
363
940
  throw new Error("sender_auth: reserver and releaser must be supplied together");
364
941
  }
365
942
  }
943
+ function assertDestination(signed, expected) {
944
+ if (signed !== expected) {
945
+ 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`);
946
+ }
947
+ }
948
+ function assertDepositRequestHash(signedHex, expectedRequestId) {
949
+ const expected = (0, destination_js_1.deriveDepositRequestHash)(expectedRequestId);
950
+ if (signedHex.toLowerCase() !== expected.toLowerCase()) {
951
+ 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`);
952
+ }
953
+ }
366
954
  function nowSec() {
367
955
  return Math.floor(Date.now() / 1e3);
368
956
  }
@@ -374,7 +962,7 @@ var require_chain_id2 = __commonJS({
374
962
  "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/chain-id.js"(exports2) {
375
963
  "use strict";
376
964
  Object.defineProperty(exports2, "__esModule", { value: true });
377
- exports2.TRON_PERMIT2_FALLBACKS = exports2.TRON_CHAIN_IDS = void 0;
965
+ exports2.TRON_PERMIT2_FALLBACKS = exports2.TRON_CHAIN_IDS = exports2.MAX_EVM_CHAIN_ID = void 0;
378
966
  exports2.namespaceOf = namespaceOf;
379
967
  exports2.evmChainId = evmChainId;
380
968
  exports2.tronNumericChainId = tronNumericChainId;
@@ -383,21 +971,30 @@ var require_chain_id2 = __commonJS({
383
971
  function namespaceOf(network) {
384
972
  return network.split(":")[0];
385
973
  }
974
+ exports2.MAX_EVM_CHAIN_ID = Number.MAX_SAFE_INTEGER;
386
975
  function evmChainId(network) {
387
976
  const match = /^eip155:([0-9]+)$/.exec(network);
388
977
  if (!match) {
389
978
  throw new Error(`sender_auth: expected an eip155 network, got ${network}`);
390
979
  }
391
- return Number(match[1]);
980
+ const chainId = Number(match[1]);
981
+ if (chainId > exports2.MAX_EVM_CHAIN_ID) {
982
+ throw new Error(`sender_auth: eip155 chain id ${match[1]} exceeds the EIP-2294 maximum (${exports2.MAX_EVM_CHAIN_ID})`);
983
+ }
984
+ return chainId;
392
985
  }
393
986
  exports2.TRON_CHAIN_IDS = {
394
987
  mainnet: 728126428,
395
988
  shasta: 2494104990
396
989
  };
397
990
  function tronNumericChainId(network) {
398
- const cluster = network.split(":")[1];
399
- const id = exports2.TRON_CHAIN_IDS[cluster ?? ""];
400
- if (id === void 0) {
991
+ if (namespaceOf(network) !== "tron") {
992
+ throw new Error(`sender_auth: expected a tron network, got ${network}`);
993
+ }
994
+ const segments = network.split(":");
995
+ const cluster = segments.length === 2 ? segments[1] : void 0;
996
+ const id = cluster !== void 0 && Object.hasOwn(exports2.TRON_CHAIN_IDS, cluster) ? exports2.TRON_CHAIN_IDS[cluster] : void 0;
997
+ if (typeof id !== "number") {
401
998
  throw new Error(`sender_auth: unsupported Tron network '${network}'`);
402
999
  }
403
1000
  return id;
@@ -407,8 +1004,8 @@ var require_chain_id2 = __commonJS({
407
1004
  "tron:shasta": "TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp"
408
1005
  };
409
1006
  function resolveTronPermit2(network) {
410
- const resolved = exports2.TRON_PERMIT2_FALLBACKS[network];
411
- if (!resolved) {
1007
+ const resolved = Object.hasOwn(exports2.TRON_PERMIT2_FALLBACKS, network) ? exports2.TRON_PERMIT2_FALLBACKS[network] : void 0;
1008
+ if (typeof resolved !== "string" || resolved === "") {
412
1009
  throw new Error(`sender_auth: no Permit2 address known for Tron network '${network}'`);
413
1010
  }
414
1011
  return resolved;
@@ -464,7 +1061,7 @@ var require_permit_types = __commonJS({
464
1061
  "../contracts/evm/escrow-encoding/typescript/dist/permit-types.js"(exports2) {
465
1062
  "use strict";
466
1063
  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;
1064
+ 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
1065
  exports2.createPermit2Domain = createPermit2Domain;
469
1066
  exports2.createEscrowDomain = createEscrowDomain;
470
1067
  exports2.PERMIT_WITNESS_TYPES = {
@@ -547,6 +1144,63 @@ var require_permit_types = __commonJS({
547
1144
  { name: "settler", type: "address" }
548
1145
  ]
549
1146
  };
1147
+ exports2.PERMIT_WITNESS_TYPES_WITH_DESTINATION = {
1148
+ PermitWitnessTransferFrom: [
1149
+ { name: "permitted", type: "TokenPermissions" },
1150
+ { name: "spender", type: "address" },
1151
+ { name: "nonce", type: "uint256" },
1152
+ { name: "deadline", type: "uint256" },
1153
+ { name: "witness", type: "DepositWitness" }
1154
+ ],
1155
+ TokenPermissions: [
1156
+ { name: "token", type: "address" },
1157
+ { name: "amount", type: "uint256" }
1158
+ ],
1159
+ DepositWitness: [
1160
+ { name: "depositRequestHash", type: "bytes32" },
1161
+ { name: "destination", type: "string" },
1162
+ { name: "reserver", type: "address" },
1163
+ { name: "releaser", type: "address" }
1164
+ ]
1165
+ };
1166
+ exports2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE = {
1167
+ ReserveWitness: [
1168
+ { name: "depositId", type: "bytes32" },
1169
+ { name: "quoteHash", type: "bytes32" },
1170
+ { name: "settler", type: "address" },
1171
+ { name: "sourceAmount", type: "uint256" }
1172
+ ]
1173
+ };
1174
+ exports2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH = {
1175
+ ReleaseWitness: [
1176
+ { name: "depositId", type: "bytes32" },
1177
+ { name: "quoteHash", type: "bytes32" },
1178
+ { name: "depositRequestHash", type: "bytes32" },
1179
+ { name: "destinationHash", type: "bytes32" },
1180
+ { name: "depositor", type: "address" },
1181
+ { name: "token", type: "address" },
1182
+ { name: "amount", type: "uint256" },
1183
+ { name: "feeAmount", type: "uint256" },
1184
+ { name: "reserver", type: "address" },
1185
+ { name: "releaser", type: "address" },
1186
+ { name: "settler", type: "address" }
1187
+ ]
1188
+ };
1189
+ exports2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH = {
1190
+ RefundWitness: [
1191
+ { name: "depositId", type: "bytes32" },
1192
+ { name: "quoteHash", type: "bytes32" },
1193
+ { name: "depositRequestHash", type: "bytes32" },
1194
+ { name: "destinationHash", type: "bytes32" },
1195
+ { name: "depositor", type: "address" },
1196
+ { name: "token", type: "address" },
1197
+ { name: "amount", type: "uint256" },
1198
+ { name: "feeAmount", type: "uint256" },
1199
+ { name: "reserver", type: "address" },
1200
+ { name: "releaser", type: "address" },
1201
+ { name: "settler", type: "address" }
1202
+ ]
1203
+ };
550
1204
  }
551
1205
  });
552
1206
 
@@ -673,6 +1327,8 @@ var require_escrow_abi = __commonJS({
673
1327
  name: "depositWitness",
674
1328
  type: "tuple",
675
1329
  components: [
1330
+ { name: "depositRequestHash", type: "bytes32" },
1331
+ { name: "destination", type: "string" },
676
1332
  { name: "reserver", type: "address" },
677
1333
  { name: "releaser", type: "address" }
678
1334
  ]
@@ -682,15 +1338,17 @@ var require_escrow_abi = __commonJS({
682
1338
  name: "reserveWitness",
683
1339
  type: "tuple",
684
1340
  components: [
685
- { name: "paymentId", type: "bytes32" },
686
- { name: "settler", type: "address" }
1341
+ { name: "depositId", type: "bytes32" },
1342
+ { name: "quoteHash", type: "bytes32" },
1343
+ { name: "settler", type: "address" },
1344
+ { name: "sourceAmount", type: "uint256" }
687
1345
  ]
688
1346
  },
689
1347
  { name: "reserveSignature", type: "bytes" }
690
1348
  ]
691
1349
  }
692
1350
  ],
693
- outputs: [{ name: "paymentId", type: "bytes32" }],
1351
+ outputs: [{ name: "depositId", type: "bytes32" }],
694
1352
  stateMutability: "nonpayable"
695
1353
  },
696
1354
  {
@@ -705,7 +1363,10 @@ var require_escrow_abi = __commonJS({
705
1363
  name: "refundWitness",
706
1364
  type: "tuple",
707
1365
  components: [
708
- { name: "paymentId", type: "bytes32" },
1366
+ { name: "depositId", type: "bytes32" },
1367
+ { name: "quoteHash", type: "bytes32" },
1368
+ { name: "depositRequestHash", type: "bytes32" },
1369
+ { name: "destinationHash", type: "bytes32" },
709
1370
  { name: "depositor", type: "address" },
710
1371
  { name: "token", type: "address" },
711
1372
  { name: "amount", type: "uint256" },
@@ -725,7 +1386,7 @@ var require_escrow_abi = __commonJS({
725
1386
  {
726
1387
  type: "function",
727
1388
  name: "getDepositHash",
728
- inputs: [{ name: "paymentId", type: "bytes32" }],
1389
+ inputs: [{ name: "depositId", type: "bytes32" }],
729
1390
  outputs: [{ name: "", type: "bytes32" }],
730
1391
  stateMutability: "view"
731
1392
  },
@@ -741,14 +1402,67 @@ var require_escrow_abi = __commonJS({
741
1402
  }
742
1403
  });
743
1404
 
1405
+ // ../contracts/evm/escrow-encoding/typescript/dist/witness-values.js
1406
+ var require_witness_values2 = __commonJS({
1407
+ "../contracts/evm/escrow-encoding/typescript/dist/witness-values.js"(exports2) {
1408
+ "use strict";
1409
+ Object.defineProperty(exports2, "__esModule", { value: true });
1410
+ exports2.normalizeBytes32 = normalizeBytes32;
1411
+ exports2.normalizeAddressField = normalizeAddressField;
1412
+ exports2.normalizeUint256 = normalizeUint256;
1413
+ exports2.chainIdToHex = chainIdToHex;
1414
+ var ethers_1 = require("ethers");
1415
+ function normalizeBytes32(label, value) {
1416
+ let bytes;
1417
+ try {
1418
+ bytes = (0, ethers_1.getBytes)(value);
1419
+ } catch {
1420
+ throw new Error(`${label} must be 0x-prefixed hex (32 bytes), got ${JSON.stringify(value)}`);
1421
+ }
1422
+ if (bytes.length !== 32) {
1423
+ throw new Error(`${label} must be exactly 32 bytes, got ${bytes.length}`);
1424
+ }
1425
+ return (0, ethers_1.hexlify)(bytes);
1426
+ }
1427
+ function normalizeAddressField(label, value) {
1428
+ try {
1429
+ return (0, ethers_1.getAddress)(value);
1430
+ } catch {
1431
+ throw new Error(`${label} must be a 20-byte hex address, got ${JSON.stringify(value)}`);
1432
+ }
1433
+ }
1434
+ function normalizeUint256(label, value) {
1435
+ let n;
1436
+ try {
1437
+ n = BigInt(value);
1438
+ } catch {
1439
+ throw new Error(`${label} must be an integer (bigint or decimal string), got ${JSON.stringify(value)}`);
1440
+ }
1441
+ if (n < 0n) {
1442
+ throw new Error(`${label} must be non-negative (uint256), got ${n.toString()}`);
1443
+ }
1444
+ return n.toString();
1445
+ }
1446
+ function chainIdToHex(chainId) {
1447
+ if (!Number.isSafeInteger(chainId) || chainId < 0) {
1448
+ throw new Error(`chainId must be a non-negative safe integer, got ${chainId}`);
1449
+ }
1450
+ return `0x${chainId.toString(16)}`;
1451
+ }
1452
+ }
1453
+ });
1454
+
744
1455
  // ../contracts/evm/escrow-encoding/typescript/dist/reserve-encoder.js
745
1456
  var require_reserve_encoder2 = __commonJS({
746
1457
  "../contracts/evm/escrow-encoding/typescript/dist/reserve-encoder.js"(exports2) {
747
1458
  "use strict";
748
1459
  Object.defineProperty(exports2, "__esModule", { value: true });
749
1460
  exports2.computeReserveDigest = computeReserveDigest;
1461
+ exports2.buildReserveTypedDataWithQuoteSource = buildReserveTypedDataWithQuoteSource;
1462
+ exports2.computeReserveDigestWithQuoteSource = computeReserveDigestWithQuoteSource;
750
1463
  var ethers_1 = require("ethers");
751
1464
  var permit_types_1 = require_permit_types();
1465
+ var witness_values_1 = require_witness_values2();
752
1466
  function computeReserveDigest(input) {
753
1467
  const domain = (0, permit_types_1.createEscrowDomain)(input.chainId, input.escrowContract);
754
1468
  return ethers_1.TypedDataEncoder.hash(domain, permit_types_1.RESERVE_WITNESS_TYPES, {
@@ -756,6 +1470,114 @@ var require_reserve_encoder2 = __commonJS({
756
1470
  settler: input.settler
757
1471
  });
758
1472
  }
1473
+ function buildReserveTypedDataWithQuoteSource(input) {
1474
+ return {
1475
+ types: permit_types_1.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE,
1476
+ primaryType: "ReserveWitness",
1477
+ domain: {
1478
+ name: "Escrow",
1479
+ version: "3",
1480
+ chainId: (0, witness_values_1.chainIdToHex)(input.chainId),
1481
+ verifyingContract: (0, witness_values_1.normalizeAddressField)("escrowContract", input.escrowContract)
1482
+ },
1483
+ message: {
1484
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", input.depositId),
1485
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", input.quoteHash),
1486
+ settler: (0, witness_values_1.normalizeAddressField)("settler", input.settler),
1487
+ sourceAmount: (0, witness_values_1.normalizeUint256)("sourceAmount", input.sourceAmount)
1488
+ }
1489
+ };
1490
+ }
1491
+ function computeReserveDigestWithQuoteSource(input) {
1492
+ const prehash = buildReserveTypedDataWithQuoteSource(input);
1493
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
1494
+ }
1495
+ }
1496
+ });
1497
+
1498
+ // ../contracts/evm/escrow-encoding/typescript/dist/release-encoder.js
1499
+ var require_release_encoder2 = __commonJS({
1500
+ "../contracts/evm/escrow-encoding/typescript/dist/release-encoder.js"(exports2) {
1501
+ "use strict";
1502
+ Object.defineProperty(exports2, "__esModule", { value: true });
1503
+ exports2.buildReleaseTypedDataWithQuoteHash = buildReleaseTypedDataWithQuoteHash;
1504
+ exports2.computeReleaseDigestWithQuoteHash = computeReleaseDigestWithQuoteHash;
1505
+ var ethers_1 = require("ethers");
1506
+ var permit_types_1 = require_permit_types();
1507
+ var witness_values_1 = require_witness_values2();
1508
+ function buildReleaseTypedDataWithQuoteHash(input) {
1509
+ const w = input.witness;
1510
+ return {
1511
+ types: permit_types_1.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH,
1512
+ primaryType: "ReleaseWitness",
1513
+ domain: {
1514
+ name: "Escrow",
1515
+ version: "3",
1516
+ chainId: (0, witness_values_1.chainIdToHex)(input.chainId),
1517
+ verifyingContract: (0, witness_values_1.normalizeAddressField)("escrowContract", input.escrowContract)
1518
+ },
1519
+ message: {
1520
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", w.depositId),
1521
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", w.quoteHash),
1522
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", w.depositRequestHash),
1523
+ destinationHash: (0, witness_values_1.normalizeBytes32)("destinationHash", w.destinationHash),
1524
+ depositor: (0, witness_values_1.normalizeAddressField)("depositor", w.depositor),
1525
+ token: (0, witness_values_1.normalizeAddressField)("token", w.token),
1526
+ amount: (0, witness_values_1.normalizeUint256)("amount", w.amount),
1527
+ feeAmount: (0, witness_values_1.normalizeUint256)("feeAmount", w.feeAmount),
1528
+ reserver: (0, witness_values_1.normalizeAddressField)("reserver", w.reserver),
1529
+ releaser: (0, witness_values_1.normalizeAddressField)("releaser", w.releaser),
1530
+ settler: (0, witness_values_1.normalizeAddressField)("settler", w.settler)
1531
+ }
1532
+ };
1533
+ }
1534
+ function computeReleaseDigestWithQuoteHash(input) {
1535
+ const prehash = buildReleaseTypedDataWithQuoteHash(input);
1536
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
1537
+ }
1538
+ }
1539
+ });
1540
+
1541
+ // ../contracts/evm/escrow-encoding/typescript/dist/refund-encoder.js
1542
+ var require_refund_encoder2 = __commonJS({
1543
+ "../contracts/evm/escrow-encoding/typescript/dist/refund-encoder.js"(exports2) {
1544
+ "use strict";
1545
+ Object.defineProperty(exports2, "__esModule", { value: true });
1546
+ exports2.buildRefundTypedDataWithQuoteHash = buildRefundTypedDataWithQuoteHash;
1547
+ exports2.computeRefundDigestWithQuoteHash = computeRefundDigestWithQuoteHash;
1548
+ var ethers_1 = require("ethers");
1549
+ var permit_types_1 = require_permit_types();
1550
+ var witness_values_1 = require_witness_values2();
1551
+ function buildRefundTypedDataWithQuoteHash(input) {
1552
+ const w = input.witness;
1553
+ return {
1554
+ types: permit_types_1.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH,
1555
+ primaryType: "RefundWitness",
1556
+ domain: {
1557
+ name: "Escrow",
1558
+ version: "3",
1559
+ chainId: (0, witness_values_1.chainIdToHex)(input.chainId),
1560
+ verifyingContract: (0, witness_values_1.normalizeAddressField)("escrowContract", input.escrowContract)
1561
+ },
1562
+ message: {
1563
+ depositId: (0, witness_values_1.normalizeBytes32)("depositId", w.depositId),
1564
+ quoteHash: (0, witness_values_1.normalizeBytes32)("quoteHash", w.quoteHash),
1565
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", w.depositRequestHash),
1566
+ destinationHash: (0, witness_values_1.normalizeBytes32)("destinationHash", w.destinationHash),
1567
+ depositor: (0, witness_values_1.normalizeAddressField)("depositor", w.depositor),
1568
+ token: (0, witness_values_1.normalizeAddressField)("token", w.token),
1569
+ amount: (0, witness_values_1.normalizeUint256)("amount", w.amount),
1570
+ feeAmount: (0, witness_values_1.normalizeUint256)("feeAmount", w.feeAmount),
1571
+ reserver: (0, witness_values_1.normalizeAddressField)("reserver", w.reserver),
1572
+ releaser: (0, witness_values_1.normalizeAddressField)("releaser", w.releaser),
1573
+ settler: (0, witness_values_1.normalizeAddressField)("settler", w.settler)
1574
+ }
1575
+ };
1576
+ }
1577
+ function computeRefundDigestWithQuoteHash(input) {
1578
+ const prehash = buildRefundTypedDataWithQuoteHash(input);
1579
+ return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
1580
+ }
759
1581
  }
760
1582
  });
761
1583
 
@@ -764,11 +1586,13 @@ var require_deposit_encoder2 = __commonJS({
764
1586
  "../contracts/evm/escrow-encoding/typescript/dist/deposit-encoder.js"(exports2) {
765
1587
  "use strict";
766
1588
  Object.defineProperty(exports2, "__esModule", { value: true });
767
- exports2.PERMIT2_CONTRACT_ADDRESS = void 0;
1589
+ exports2.MAX_DESTINATION_BYTES = exports2.PERMIT2_CONTRACT_ADDRESS = void 0;
768
1590
  exports2.createPermitWitnessTransferFromPrehash = createPermitWitnessTransferFromPrehash2;
769
1591
  exports2.hashPermitWitnessTransferFrom = hashPermitWitnessTransferFrom2;
1592
+ exports2.createPermitWitnessTransferFromPrehashWithDestination = createPermitWitnessTransferFromPrehashWithDestination;
770
1593
  var ethers_1 = require("ethers");
771
1594
  var permit_types_1 = require_permit_types();
1595
+ var witness_values_1 = require_witness_values2();
772
1596
  exports2.PERMIT2_CONTRACT_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
773
1597
  function createPermitWitnessTransferFromPrehash2(params) {
774
1598
  return {
@@ -797,15 +1621,52 @@ var require_deposit_encoder2 = __commonJS({
797
1621
  function hashPermitWitnessTransferFrom2(prehash) {
798
1622
  return ethers_1.TypedDataEncoder.hash(prehash.domain, prehash.types, prehash.message);
799
1623
  }
1624
+ exports2.MAX_DESTINATION_BYTES = 256;
1625
+ function assertDestinationWithinBounds(destination) {
1626
+ if (destination === "") {
1627
+ 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');
1628
+ }
1629
+ const byteLength = (0, ethers_1.toUtf8Bytes)(destination).length;
1630
+ if (byteLength > exports2.MAX_DESTINATION_BYTES) {
1631
+ 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`);
1632
+ }
1633
+ }
1634
+ function createPermitWitnessTransferFromPrehashWithDestination(params) {
1635
+ assertDestinationWithinBounds(params.destination);
1636
+ return {
1637
+ types: permit_types_1.PERMIT_WITNESS_TYPES_WITH_DESTINATION,
1638
+ primaryType: "PermitWitnessTransferFrom",
1639
+ domain: {
1640
+ name: "Permit2",
1641
+ chainId: (0, witness_values_1.chainIdToHex)(params.chainId),
1642
+ verifyingContract: (0, witness_values_1.normalizeAddressField)("verifyingContract", params.verifyingContract)
1643
+ },
1644
+ message: {
1645
+ permitted: {
1646
+ token: (0, witness_values_1.normalizeAddressField)("token", params.token),
1647
+ amount: (0, witness_values_1.normalizeUint256)("amount", params.amount)
1648
+ },
1649
+ spender: (0, witness_values_1.normalizeAddressField)("spender", params.spender),
1650
+ nonce: (0, witness_values_1.normalizeUint256)("nonce", params.nonce),
1651
+ deadline: (0, witness_values_1.normalizeUint256)("deadline", params.deadline),
1652
+ witness: {
1653
+ depositRequestHash: (0, witness_values_1.normalizeBytes32)("depositRequestHash", params.depositRequestHash),
1654
+ destination: params.destination,
1655
+ reserver: (0, witness_values_1.normalizeAddressField)("reserver", params.reserver),
1656
+ releaser: (0, witness_values_1.normalizeAddressField)("releaser", params.releaser)
1657
+ }
1658
+ }
1659
+ };
1660
+ }
800
1661
  }
801
1662
  });
802
1663
 
803
1664
  // ../contracts/evm/escrow-encoding/typescript/dist/index.js
804
- var require_dist2 = __commonJS({
1665
+ var require_dist3 = __commonJS({
805
1666
  "../contracts/evm/escrow-encoding/typescript/dist/index.js"(exports2) {
806
1667
  "use strict";
807
1668
  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;
1669
+ 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
1670
  var payment_id_1 = require_payment_id2();
810
1671
  Object.defineProperty(exports2, "computePaymentId", { enumerable: true, get: function() {
811
1672
  return payment_id_1.computePaymentId;
@@ -839,6 +1700,19 @@ var require_dist2 = __commonJS({
839
1700
  Object.defineProperty(exports2, "REFUND_WITNESS_TYPES", { enumerable: true, get: function() {
840
1701
  return permit_types_1.REFUND_WITNESS_TYPES;
841
1702
  } });
1703
+ var permit_types_2 = require_permit_types();
1704
+ Object.defineProperty(exports2, "PERMIT_WITNESS_TYPES_WITH_DESTINATION", { enumerable: true, get: function() {
1705
+ return permit_types_2.PERMIT_WITNESS_TYPES_WITH_DESTINATION;
1706
+ } });
1707
+ Object.defineProperty(exports2, "RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE", { enumerable: true, get: function() {
1708
+ return permit_types_2.RESERVE_WITNESS_TYPES_WITH_QUOTE_SOURCE;
1709
+ } });
1710
+ Object.defineProperty(exports2, "RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH", { enumerable: true, get: function() {
1711
+ return permit_types_2.RELEASE_WITNESS_TYPES_WITH_QUOTE_HASH;
1712
+ } });
1713
+ Object.defineProperty(exports2, "REFUND_WITNESS_TYPES_WITH_QUOTE_HASH", { enumerable: true, get: function() {
1714
+ return permit_types_2.REFUND_WITNESS_TYPES_WITH_QUOTE_HASH;
1715
+ } });
842
1716
  var escrow_abi_1 = require_escrow_abi();
843
1717
  Object.defineProperty(exports2, "ESCROW_ABI", { enumerable: true, get: function() {
844
1718
  return escrow_abi_1.ESCROW_ABI;
@@ -852,9 +1726,30 @@ var require_dist2 = __commonJS({
852
1726
  Object.defineProperty(exports2, "ESCROW_V3_ABI_JSON", { enumerable: true, get: function() {
853
1727
  return escrow_abi_1.ESCROW_V3_ABI_JSON;
854
1728
  } });
855
- var reserve_encoder_1 = require_reserve_encoder2();
856
- Object.defineProperty(exports2, "computeReserveDigest", { enumerable: true, get: function() {
857
- return reserve_encoder_1.computeReserveDigest;
1729
+ var reserve_encoder_1 = require_reserve_encoder2();
1730
+ Object.defineProperty(exports2, "computeReserveDigest", { enumerable: true, get: function() {
1731
+ return reserve_encoder_1.computeReserveDigest;
1732
+ } });
1733
+ var reserve_encoder_2 = require_reserve_encoder2();
1734
+ Object.defineProperty(exports2, "buildReserveTypedDataWithQuoteSource", { enumerable: true, get: function() {
1735
+ return reserve_encoder_2.buildReserveTypedDataWithQuoteSource;
1736
+ } });
1737
+ Object.defineProperty(exports2, "computeReserveDigestWithQuoteSource", { enumerable: true, get: function() {
1738
+ return reserve_encoder_2.computeReserveDigestWithQuoteSource;
1739
+ } });
1740
+ var release_encoder_1 = require_release_encoder2();
1741
+ Object.defineProperty(exports2, "buildReleaseTypedDataWithQuoteHash", { enumerable: true, get: function() {
1742
+ return release_encoder_1.buildReleaseTypedDataWithQuoteHash;
1743
+ } });
1744
+ Object.defineProperty(exports2, "computeReleaseDigestWithQuoteHash", { enumerable: true, get: function() {
1745
+ return release_encoder_1.computeReleaseDigestWithQuoteHash;
1746
+ } });
1747
+ var refund_encoder_1 = require_refund_encoder2();
1748
+ Object.defineProperty(exports2, "buildRefundTypedDataWithQuoteHash", { enumerable: true, get: function() {
1749
+ return refund_encoder_1.buildRefundTypedDataWithQuoteHash;
1750
+ } });
1751
+ Object.defineProperty(exports2, "computeRefundDigestWithQuoteHash", { enumerable: true, get: function() {
1752
+ return refund_encoder_1.computeRefundDigestWithQuoteHash;
858
1753
  } });
859
1754
  var deposit_encoder_1 = require_deposit_encoder2();
860
1755
  Object.defineProperty(exports2, "createPermitWitnessTransferFromPrehash", { enumerable: true, get: function() {
@@ -866,6 +1761,13 @@ var require_dist2 = __commonJS({
866
1761
  Object.defineProperty(exports2, "PERMIT2_CONTRACT_ADDRESS", { enumerable: true, get: function() {
867
1762
  return deposit_encoder_1.PERMIT2_CONTRACT_ADDRESS;
868
1763
  } });
1764
+ var deposit_encoder_2 = require_deposit_encoder2();
1765
+ Object.defineProperty(exports2, "createPermitWitnessTransferFromPrehashWithDestination", { enumerable: true, get: function() {
1766
+ return deposit_encoder_2.createPermitWitnessTransferFromPrehashWithDestination;
1767
+ } });
1768
+ Object.defineProperty(exports2, "MAX_DESTINATION_BYTES", { enumerable: true, get: function() {
1769
+ return deposit_encoder_2.MAX_DESTINATION_BYTES;
1770
+ } });
869
1771
  }
870
1772
  });
871
1773
 
@@ -906,24 +1808,25 @@ var require_evm = __commonJS({
906
1808
  Object.defineProperty(exports2, "__esModule", { value: true });
907
1809
  exports2.evmAdapter = void 0;
908
1810
  var ethers_1 = require("ethers");
909
- var evm_escrow_encoding_1 = require_dist2();
1811
+ var evm_escrow_encoding_1 = require_dist3();
910
1812
  var utils_js_1 = require_utils();
1813
+ var destination_js_1 = require_destination();
911
1814
  var errors_js_1 = require_errors();
912
1815
  var chain_id_js_1 = require_chain_id2();
913
1816
  exports2.evmAdapter = {
914
- async buildAuthMessage({ sourceAsset, maxSourceAmount, sourceDefaults, deadline, nonce }) {
1817
+ async buildAuthMessage({ sourceAsset, maxSourceAmount, requestId, sourceDefaults, destinationAsset, destinationAccount, deadline, nonce }) {
915
1818
  if (nonce === void 0) {
916
1819
  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
1820
  }
918
1821
  if (deadline === void 0) {
919
1822
  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
1823
  }
921
- const sourceChainId = sourceAsset.split("/")[0];
922
- const chainIdNum = parseInt(sourceChainId.split(":")[1]);
923
- const tokenAddress = sourceAsset.split("/")[1].split(":")[1];
924
- const permitParams = {
1824
+ const { network: sourceChainId, asset: tokenAddress } = (0, utils_js_1.parseSourceAsset)(sourceAsset);
1825
+ const chainIdNum = (0, chain_id_js_1.evmChainId)(sourceChainId);
1826
+ const permit2Contract = sourceDefaults.permit2Contract ?? evm_escrow_encoding_1.PERMIT2_CONTRACT_ADDRESS;
1827
+ const basePermit = {
925
1828
  chainId: chainIdNum,
926
- verifyingContract: evm_escrow_encoding_1.PERMIT2_CONTRACT_ADDRESS,
1829
+ verifyingContract: permit2Contract,
927
1830
  token: tokenAddress,
928
1831
  amount: maxSourceAmount,
929
1832
  spender: sourceDefaults.escrowContract,
@@ -932,7 +1835,21 @@ var require_evm = __commonJS({
932
1835
  reserver: sourceDefaults.quoteSelector,
933
1836
  releaser: sourceDefaults.fulfillmentVerifierAccount
934
1837
  };
935
- const messagePrehash = (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehash)(permitParams);
1838
+ if ((0, destination_js_1.usesDestinationCommitment)(sourceDefaults.depositWitnessVersion)) {
1839
+ const permitParams = {
1840
+ ...basePermit,
1841
+ // The two escrow commitments. Composed here through the shared helpers rather than
1842
+ // accepted pre-built, so this producer and the release signer cannot disagree about
1843
+ // formatting — a disagreement the escrow cannot detect, because it stores only
1844
+ // keccak256(bytes(destination)).
1845
+ depositRequestHash: (0, destination_js_1.deriveDepositRequestHash)(requestId),
1846
+ destination: (0, destination_js_1.buildEscrowDestination)(destinationAsset, destinationAccount)
1847
+ };
1848
+ const messagePrehash2 = (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehashWithDestination)(permitParams);
1849
+ const messageHash2 = (0, evm_escrow_encoding_1.hashPermitWitnessTransferFrom)(messagePrehash2);
1850
+ return { messageScheme: "EVM_PERMIT2", messageHash: messageHash2, messagePrehash: JSON.stringify(messagePrehash2) };
1851
+ }
1852
+ const messagePrehash = (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehash)(basePermit);
936
1853
  const messageHash = (0, evm_escrow_encoding_1.hashPermitWitnessTransferFrom)(messagePrehash);
937
1854
  return { messageScheme: "EVM_PERMIT2", messageHash, messagePrehash: JSON.stringify(messagePrehash) };
938
1855
  },
@@ -965,17 +1882,31 @@ var require_evm = __commonJS({
965
1882
  let msg;
966
1883
  try {
967
1884
  msg = JSON.parse(signed.message_prehash).message;
968
- canonical = (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehash)({
1885
+ const base = {
969
1886
  chainId: (0, chain_id_js_1.evmChainId)(source.network),
970
- verifyingContract: evm_escrow_encoding_1.PERMIT2_CONTRACT_ADDRESS,
1887
+ // The same Permit2 buildAuthMessage signed against. Taken from the VERIFIER's
1888
+ // expectations, never from msg — the prehash is client-supplied, so reading the domain
1889
+ // out of it would let a caller nominate its own verifying contract and have the
1890
+ // signature check itself. Absent means canonical, matching the build side's default.
1891
+ verifyingContract: expected.permit2Contract ?? evm_escrow_encoding_1.PERMIT2_CONTRACT_ADDRESS,
971
1892
  token: msg.permitted.token,
972
1893
  amount: msg.permitted.amount,
973
1894
  spender: msg.spender,
974
1895
  nonce: BigInt(msg.nonce),
975
1896
  deadline: BigInt(msg.deadline),
976
- reserver: msg.witness.reserver,
977
- releaser: msg.witness.releaser
978
- });
1897
+ reserver: msg.witness?.reserver,
1898
+ releaser: msg.witness?.releaser
1899
+ };
1900
+ const hasHash = typeof msg.witness?.depositRequestHash === "string";
1901
+ const hasDestination = typeof msg.witness?.destination === "string";
1902
+ if (hasHash !== hasDestination) {
1903
+ throw new Error("half-populated deposit witness");
1904
+ }
1905
+ canonical = hasHash ? (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehashWithDestination)({
1906
+ ...base,
1907
+ depositRequestHash: msg.witness.depositRequestHash,
1908
+ destination: msg.witness.destination
1909
+ }) : (0, evm_escrow_encoding_1.createPermitWitnessTransferFromPrehash)(base);
979
1910
  } catch {
980
1911
  throw new errors_js_1.MalformedPrehashError();
981
1912
  }
@@ -999,6 +1930,12 @@ var require_evm = __commonJS({
999
1930
  if (expected.reserver !== void 0 && expected.releaser !== void 0) {
1000
1931
  (0, utils_js_1.assertWitnessRoles)(msg.witness.reserver, msg.witness.releaser, expected.reserver, expected.releaser, (a) => a);
1001
1932
  }
1933
+ if (expected.destination !== void 0) {
1934
+ (0, utils_js_1.assertDestination)(msg.witness.destination, expected.destination);
1935
+ }
1936
+ if (expected.requestId !== void 0) {
1937
+ (0, utils_js_1.assertDepositRequestHash)(msg.witness.depositRequestHash, expected.requestId);
1938
+ }
1002
1939
  return {
1003
1940
  amount: msg.permitted.amount,
1004
1941
  deadlineSec,
@@ -1009,7 +1946,11 @@ var require_evm = __commonJS({
1009
1946
  deadlineSec,
1010
1947
  reserver: msg.witness.reserver,
1011
1948
  releaser: msg.witness.releaser,
1012
- spender: msg.spender
1949
+ spender: msg.spender,
1950
+ // Surfaced whether or not the opt-in checks above ran, so a consumer binding these
1951
+ // downstream does not have to re-parse message_prehash and risk drifting from this parse.
1952
+ destination: msg.witness.destination,
1953
+ depositRequestHash: msg.witness.depositRequestHash
1013
1954
  }
1014
1955
  };
1015
1956
  }
@@ -1028,18 +1969,18 @@ var require_tron = __commonJS({
1028
1969
  var utils_js_1 = require_utils();
1029
1970
  var errors_js_1 = require_errors();
1030
1971
  var chain_id_js_1 = require_chain_id2();
1972
+ var destination_js_1 = require_destination();
1031
1973
  exports2.tronAdapter = {
1032
- async buildAuthMessage({ sourceAsset, maxSourceAmount, sourceDefaults, deadline, nonce }) {
1974
+ async buildAuthMessage({ sourceAsset, maxSourceAmount, requestId, sourceDefaults, destinationAsset, destinationAccount, deadline, nonce }) {
1033
1975
  if (nonce === void 0) {
1034
1976
  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
1977
  }
1036
1978
  if (deadline === void 0) {
1037
1979
  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
1980
  }
1039
- const sourceChainId = sourceAsset.split("/")[0];
1040
- const tokenAddress = sourceAsset.split("/")[1].split(":")[1];
1981
+ const { network: sourceChainId, asset: tokenAddress } = (0, utils_js_1.parseSourceAsset)(sourceAsset);
1041
1982
  const permit2Address = sourceDefaults.permit2Contract ?? (0, chain_id_js_1.resolveTronPermit2)(sourceChainId);
1042
- const tvmParams = {
1983
+ const baseParams = {
1043
1984
  chainId: (0, chain_id_js_1.tronNumericChainId)(sourceChainId),
1044
1985
  permit2Address,
1045
1986
  tokenAddress,
@@ -1050,7 +1991,21 @@ var require_tron = __commonJS({
1050
1991
  reserverAddress: sourceDefaults.quoteSelector,
1051
1992
  releaserAddress: sourceDefaults.fulfillmentVerifierAccount
1052
1993
  };
1053
- const messagePrehash = (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehash)(tvmParams);
1994
+ if ((0, destination_js_1.usesDestinationCommitment)(sourceDefaults.depositWitnessVersion)) {
1995
+ const tvmParams = {
1996
+ ...baseParams,
1997
+ // The two commitments, composed through the shared helpers rather than accepted
1998
+ // pre-built, so this producer and the Go release signer cannot disagree about
1999
+ // formatting — a disagreement the escrow cannot detect, because it stores only
2000
+ // keccak256(bytes(destination)).
2001
+ depositRequestHash: (0, destination_js_1.deriveDepositRequestHash)(requestId),
2002
+ destination: (0, destination_js_1.buildEscrowDestination)(destinationAsset, destinationAccount)
2003
+ };
2004
+ const messagePrehash2 = (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehashWithDestination)(tvmParams);
2005
+ const messageHash2 = (0, tvm_escrow_encoding_1.hashTvmPermitWitnessTransferFrom)(messagePrehash2);
2006
+ return { messageScheme: "EVM_PERMIT2", messageHash: messageHash2, messagePrehash: JSON.stringify(messagePrehash2) };
2007
+ }
2008
+ const messagePrehash = (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehash)(baseParams);
1054
2009
  const messageHash = (0, tvm_escrow_encoding_1.hashTvmPermitWitnessTransferFrom)(messagePrehash);
1055
2010
  return { messageScheme: "EVM_PERMIT2", messageHash, messagePrehash: JSON.stringify(messagePrehash) };
1056
2011
  },
@@ -1085,17 +2040,31 @@ var require_tron = __commonJS({
1085
2040
  let digest;
1086
2041
  try {
1087
2042
  msg = JSON.parse(signed.message_prehash).message;
1088
- const canonical = (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehash)({
2043
+ const base = {
1089
2044
  chainId: (0, chain_id_js_1.tronNumericChainId)(source.network),
1090
- permit2Address: (0, chain_id_js_1.resolveTronPermit2)(source.network),
2045
+ // The same Permit2 buildAuthMessage signed against, taken from the VERIFIER's
2046
+ // expectations rather than from msg — the prehash is payer-supplied, so reading the
2047
+ // domain out of it would let a caller nominate its own verifying contract. Absent means
2048
+ // the pinned per-chain address, matching the build side's default.
2049
+ permit2Address: expected.permit2Contract ?? (0, chain_id_js_1.resolveTronPermit2)(source.network),
1091
2050
  tokenAddress: msg.permitted.token,
1092
2051
  amount: msg.permitted.amount,
1093
2052
  spenderAddress: msg.spender,
1094
2053
  nonce: BigInt(msg.nonce),
1095
2054
  deadline: BigInt(msg.deadline),
1096
- reserverAddress: msg.witness.reserver,
1097
- releaserAddress: msg.witness.releaser
1098
- });
2055
+ reserverAddress: msg.witness?.reserver,
2056
+ releaserAddress: msg.witness?.releaser
2057
+ };
2058
+ const hasHash = typeof msg.witness?.depositRequestHash === "string";
2059
+ const hasDestination = typeof msg.witness?.destination === "string";
2060
+ if (hasHash !== hasDestination) {
2061
+ throw new Error("half-populated witness");
2062
+ }
2063
+ const canonical = hasHash ? (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehashWithDestination)({
2064
+ ...base,
2065
+ depositRequestHash: msg.witness.depositRequestHash,
2066
+ destination: msg.witness.destination
2067
+ }) : (0, tvm_escrow_encoding_1.createTvmPermitWitnessTransferFromPrehash)(base);
1099
2068
  digest = (0, tvm_escrow_encoding_1.hashTvmPermitWitnessTransferFrom)(canonical);
1100
2069
  } catch {
1101
2070
  throw new errors_js_1.MalformedPrehashError();
@@ -1143,7 +2112,7 @@ var require_errors2 = __commonJS({
1143
2112
  "../contracts/svm/escrow-encoding/typescript/dist/errors.js"(exports2) {
1144
2113
  "use strict";
1145
2114
  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;
2115
+ exports2.InvalidEscrowDomainError = 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
2116
  var EncodingError = class extends Error {
1148
2117
  constructor(message) {
1149
2118
  super(message);
@@ -1151,13 +2120,13 @@ var require_errors2 = __commonJS({
1151
2120
  }
1152
2121
  };
1153
2122
  exports2.EncodingError = EncodingError;
1154
- var ZeroPaymentIdError = class extends EncodingError {
2123
+ var ZeroDepositRequestHashError = class extends EncodingError {
1155
2124
  constructor() {
1156
- super("payment ID cannot be zero");
1157
- this.name = "ZeroPaymentIdError";
2125
+ super("deposit request hash cannot be zero");
2126
+ this.name = "ZeroDepositRequestHashError";
1158
2127
  }
1159
2128
  };
1160
- exports2.ZeroPaymentIdError = ZeroPaymentIdError;
2129
+ exports2.ZeroDepositRequestHashError = ZeroDepositRequestHashError;
1161
2130
  var ZeroDepositorError = class extends EncodingError {
1162
2131
  constructor() {
1163
2132
  super("depositor cannot be zero");
@@ -1228,6 +2197,41 @@ var require_errors2 = __commonJS({
1228
2197
  }
1229
2198
  };
1230
2199
  exports2.InvalidHexError = InvalidHexError;
2200
+ var ZeroQuoteHashError = class extends EncodingError {
2201
+ constructor() {
2202
+ super("quote hash cannot be zero");
2203
+ this.name = "ZeroQuoteHashError";
2204
+ }
2205
+ };
2206
+ exports2.ZeroQuoteHashError = ZeroQuoteHashError;
2207
+ var ZeroSourceAmountError = class extends EncodingError {
2208
+ constructor() {
2209
+ super("source amount cannot be zero");
2210
+ this.name = "ZeroSourceAmountError";
2211
+ }
2212
+ };
2213
+ exports2.ZeroSourceAmountError = ZeroSourceAmountError;
2214
+ var EmptyDestinationError = class extends EncodingError {
2215
+ constructor() {
2216
+ super("destination cannot be empty");
2217
+ this.name = "EmptyDestinationError";
2218
+ }
2219
+ };
2220
+ exports2.EmptyDestinationError = EmptyDestinationError;
2221
+ var DestinationTooLongError = class extends EncodingError {
2222
+ constructor() {
2223
+ super("destination exceeds the maximum length");
2224
+ this.name = "DestinationTooLongError";
2225
+ }
2226
+ };
2227
+ exports2.DestinationTooLongError = DestinationTooLongError;
2228
+ var InvalidEscrowDomainError = class extends EncodingError {
2229
+ constructor(message) {
2230
+ super(message);
2231
+ this.name = "InvalidEscrowDomainError";
2232
+ }
2233
+ };
2234
+ exports2.InvalidEscrowDomainError = InvalidEscrowDomainError;
1231
2235
  }
1232
2236
  });
1233
2237
 
@@ -1242,7 +2246,7 @@ var require_pubkey = __commonJS({
1242
2246
  exports2.Pubkey = void 0;
1243
2247
  var bs58_1 = __importDefault(require("bs58"));
1244
2248
  var errors_1 = require_errors2();
1245
- var Pubkey2 = class _Pubkey {
2249
+ var Pubkey = class _Pubkey {
1246
2250
  constructor(data) {
1247
2251
  if (data.length !== 32) {
1248
2252
  throw new errors_1.InvalidPubkeyLengthError();
@@ -1335,7 +2339,7 @@ var require_pubkey = __commonJS({
1335
2339
  return this.data.every((b, i) => b === other.data[i]);
1336
2340
  }
1337
2341
  };
1338
- exports2.Pubkey = Pubkey2;
2342
+ exports2.Pubkey = Pubkey;
1339
2343
  }
1340
2344
  });
1341
2345
 
@@ -1936,12 +2940,17 @@ var require_escrow_domain = __commonJS({
1936
2940
  "use strict";
1937
2941
  Object.defineProperty(exports2, "__esModule", { value: true });
1938
2942
  exports2.escrowDomainPrefixBytes = escrowDomainPrefixBytes;
2943
+ exports2.newEscrowDomain = newEscrowDomain;
2944
+ var errors_1 = require_errors2();
1939
2945
  function escrowDomainPrefixBytes(domain) {
1940
2946
  if (domain.clusterId.length !== 32) {
1941
- throw new Error(`EscrowDomain.clusterId must be 32 bytes, got ${domain.clusterId.length}`);
2947
+ throw new errors_1.InvalidEscrowDomainError(`EscrowDomain.clusterId must be 32 bytes, got ${domain.clusterId.length}`);
2948
+ }
2949
+ if (domain.programId.isZero()) {
2950
+ throw new errors_1.InvalidEscrowDomainError("EscrowDomain.programId cannot be zero");
1942
2951
  }
1943
2952
  if (!Number.isInteger(domain.signatureDomainVersion) || domain.signatureDomainVersion < 1 || domain.signatureDomainVersion > 255) {
1944
- throw new Error(`EscrowDomain.signatureDomainVersion must be an integer in 1..=255, got ${domain.signatureDomainVersion}`);
2953
+ throw new errors_1.InvalidEscrowDomainError(`EscrowDomain.signatureDomainVersion must be an integer in 1..=255, got ${domain.signatureDomainVersion}`);
1945
2954
  }
1946
2955
  return [
1947
2956
  new TextEncoder().encode("escrow"),
@@ -1950,6 +2959,25 @@ var require_escrow_domain = __commonJS({
1950
2959
  domain.programId.toBytes()
1951
2960
  ];
1952
2961
  }
2962
+ function newEscrowDomain(clusterName, signatureDomainVersion, programId) {
2963
+ const trimmed = clusterName.trim();
2964
+ if (trimmed.length === 0) {
2965
+ throw new errors_1.InvalidEscrowDomainError("EscrowDomain cluster name cannot be empty");
2966
+ }
2967
+ const encoded = new TextEncoder().encode(trimmed);
2968
+ if (encoded.length > 32) {
2969
+ throw new errors_1.InvalidEscrowDomainError(`EscrowDomain cluster name "${trimmed}" exceeds 32 bytes`);
2970
+ }
2971
+ if (!Number.isInteger(signatureDomainVersion) || signatureDomainVersion < 1 || signatureDomainVersion > 255) {
2972
+ throw new errors_1.InvalidEscrowDomainError(`EscrowDomain.signatureDomainVersion must be an integer in 1..=255, got ${signatureDomainVersion}`);
2973
+ }
2974
+ if (programId.isZero()) {
2975
+ throw new errors_1.InvalidEscrowDomainError("EscrowDomain.programId cannot be zero");
2976
+ }
2977
+ const clusterId = new Uint8Array(32);
2978
+ clusterId.set(encoded);
2979
+ return { clusterId, signatureDomainVersion, programId };
2980
+ }
1953
2981
  }
1954
2982
  });
1955
2983
 
@@ -1958,13 +2986,36 @@ var require_deposit_encoder3 = __commonJS({
1958
2986
  "../contracts/svm/escrow-encoding/typescript/dist/deposit-encoder.js"(exports2) {
1959
2987
  "use strict";
1960
2988
  Object.defineProperty(exports2, "__esModule", { value: true });
1961
- exports2.computeDepositHash = computeDepositHash2;
2989
+ exports2.MAX_DESTINATION_LEN = void 0;
2990
+ exports2.computeDepositHash = computeDepositHash;
2991
+ exports2.computeDestinationHash = computeDestinationHash;
2992
+ exports2.computeDepositHashV2 = computeDepositHashV2;
1962
2993
  var encoding_utils_1 = require_encoding_utils();
1963
2994
  var escrow_domain_1 = require_escrow_domain();
1964
2995
  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();
2996
+ function computeDepositHash(params, domain) {
2997
+ if (params.depositRequestHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositRequestHash)) {
2998
+ throw new errors_1.ZeroDepositRequestHashError();
2999
+ }
3000
+ if (params.depositor.isZero())
3001
+ throw new errors_1.ZeroDepositorError();
3002
+ if (params.mint.isZero())
3003
+ throw new errors_1.ZeroMintError();
3004
+ if (params.amount === 0n)
3005
+ throw new errors_1.ZeroAmountError();
3006
+ if (params.reserver.isZero())
3007
+ throw new errors_1.ZeroReserverError();
3008
+ if (params.releaser.isZero())
3009
+ throw new errors_1.ZeroReleaserError();
3010
+ 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));
3011
+ }
3012
+ exports2.MAX_DESTINATION_LEN = 256;
3013
+ function computeDestinationHash(destination) {
3014
+ return (0, encoding_utils_1.keccak256)((0, encoding_utils_1.stringToBytes)(destination));
3015
+ }
3016
+ function computeDepositHashV2(params, destination, domain) {
3017
+ if (params.depositRequestHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositRequestHash)) {
3018
+ throw new errors_1.ZeroDepositRequestHashError();
1968
3019
  }
1969
3020
  if (params.depositor.isZero())
1970
3021
  throw new errors_1.ZeroDepositorError();
@@ -1976,7 +3027,28 @@ var require_deposit_encoder3 = __commonJS({
1976
3027
  throw new errors_1.ZeroReserverError();
1977
3028
  if (params.releaser.isZero())
1978
3029
  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));
3030
+ if (destination.length === 0)
3031
+ throw new errors_1.EmptyDestinationError();
3032
+ if ((0, encoding_utils_1.stringToBytes)(destination).length > exports2.MAX_DESTINATION_LEN) {
3033
+ throw new errors_1.DestinationTooLongError();
3034
+ }
3035
+ return (0, encoding_utils_1.keccak256)(
3036
+ ...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain),
3037
+ (0, encoding_utils_1.stringToBytes)("deposit"),
3038
+ params.depositRequestHash,
3039
+ // Hash first: keccak256 concatenates without length prefixes, so injectivity depends on every
3040
+ // hashed field being fixed-width. Feeding the raw string would make it conditional on the
3041
+ // surrounding widths and diverge from the on-chain program, which hashes it too.
3042
+ computeDestinationHash(destination),
3043
+ params.depositor.toBytes(),
3044
+ params.mint.toBytes(),
3045
+ (0, encoding_utils_1.encodeU64LE)(params.amount),
3046
+ params.reserver.toBytes(),
3047
+ params.releaser.toBytes(),
3048
+ (0, encoding_utils_1.encodeU64LE)(params.nonce),
3049
+ (0, encoding_utils_1.encodeU64LE)(params.issuedAt),
3050
+ (0, encoding_utils_1.encodeU64LE)(params.deadline)
3051
+ );
1980
3052
  }
1981
3053
  }
1982
3054
  });
@@ -1987,6 +3059,8 @@ var require_reserve_encoder3 = __commonJS({
1987
3059
  "use strict";
1988
3060
  Object.defineProperty(exports2, "__esModule", { value: true });
1989
3061
  exports2.computeReserveHash = computeReserveHash;
3062
+ exports2.computeReserveHashV2 = computeReserveHashV2;
3063
+ exports2.computeReserveHashV3 = computeReserveHashV3;
1990
3064
  var encoding_utils_1 = require_encoding_utils();
1991
3065
  var escrow_domain_1 = require_escrow_domain();
1992
3066
  var errors_1 = require_errors2();
@@ -1998,15 +3072,38 @@ var require_reserve_encoder3 = __commonJS({
1998
3072
  throw new errors_1.ZeroRecipientError();
1999
3073
  return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("reserve"), params.recipient.toBytes(), params.depositHash);
2000
3074
  }
3075
+ function computeReserveHashV2(params, quoteHash, domain) {
3076
+ if (params.depositHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositHash)) {
3077
+ throw new errors_1.ZeroDepositHashError();
3078
+ }
3079
+ if (params.recipient.isZero())
3080
+ throw new errors_1.ZeroRecipientError();
3081
+ if (quoteHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(quoteHash))
3082
+ throw new errors_1.ZeroQuoteHashError();
3083
+ return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("reserve"), params.recipient.toBytes(), params.depositHash, quoteHash);
3084
+ }
3085
+ function computeReserveHashV3(params, quoteHash, sourceAmount, domain) {
3086
+ if (params.depositHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositHash)) {
3087
+ throw new errors_1.ZeroDepositHashError();
3088
+ }
3089
+ if (params.recipient.isZero())
3090
+ throw new errors_1.ZeroRecipientError();
3091
+ if (quoteHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(quoteHash))
3092
+ throw new errors_1.ZeroQuoteHashError();
3093
+ if (sourceAmount === 0n)
3094
+ throw new errors_1.ZeroSourceAmountError();
3095
+ 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));
3096
+ }
2001
3097
  }
2002
3098
  });
2003
3099
 
2004
3100
  // ../contracts/svm/escrow-encoding/typescript/dist/release-encoder.js
2005
- var require_release_encoder = __commonJS({
3101
+ var require_release_encoder3 = __commonJS({
2006
3102
  "../contracts/svm/escrow-encoding/typescript/dist/release-encoder.js"(exports2) {
2007
3103
  "use strict";
2008
3104
  Object.defineProperty(exports2, "__esModule", { value: true });
2009
3105
  exports2.computeReleaseHash = computeReleaseHash;
3106
+ exports2.computeReleaseHashV2 = computeReleaseHashV2;
2010
3107
  var encoding_utils_1 = require_encoding_utils();
2011
3108
  var escrow_domain_1 = require_escrow_domain();
2012
3109
  var errors_1 = require_errors2();
@@ -2016,15 +3113,22 @@ var require_release_encoder = __commonJS({
2016
3113
  }
2017
3114
  return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("release"), params.depositHash);
2018
3115
  }
3116
+ function computeReleaseHashV2(params, quoteHash, domain) {
3117
+ if (params.depositHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositHash)) {
3118
+ throw new errors_1.ZeroDepositHashError();
3119
+ }
3120
+ return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("release"), params.depositHash, quoteHash);
3121
+ }
2019
3122
  }
2020
3123
  });
2021
3124
 
2022
3125
  // ../contracts/svm/escrow-encoding/typescript/dist/refund-encoder.js
2023
- var require_refund_encoder = __commonJS({
3126
+ var require_refund_encoder3 = __commonJS({
2024
3127
  "../contracts/svm/escrow-encoding/typescript/dist/refund-encoder.js"(exports2) {
2025
3128
  "use strict";
2026
3129
  Object.defineProperty(exports2, "__esModule", { value: true });
2027
3130
  exports2.computeRefundHash = computeRefundHash;
3131
+ exports2.computeRefundHashV2 = computeRefundHashV2;
2028
3132
  var encoding_utils_1 = require_encoding_utils();
2029
3133
  var escrow_domain_1 = require_escrow_domain();
2030
3134
  var errors_1 = require_errors2();
@@ -2034,6 +3138,12 @@ var require_refund_encoder = __commonJS({
2034
3138
  }
2035
3139
  return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("refund"), params.depositHash);
2036
3140
  }
3141
+ function computeRefundHashV2(params, quoteHash, domain) {
3142
+ if (params.depositHash.length !== 32 || (0, encoding_utils_1.isZeroBytes32)(params.depositHash)) {
3143
+ throw new errors_1.ZeroDepositHashError();
3144
+ }
3145
+ return (0, encoding_utils_1.keccak256)(...(0, escrow_domain_1.escrowDomainPrefixBytes)(domain), (0, encoding_utils_1.stringToBytes)("refund"), params.depositHash, quoteHash);
3146
+ }
2037
3147
  }
2038
3148
  });
2039
3149
 
@@ -2042,16 +3152,16 @@ var require_nonce_generator2 = __commonJS({
2042
3152
  "../contracts/svm/escrow-encoding/typescript/dist/nonce-generator.js"(exports2) {
2043
3153
  "use strict";
2044
3154
  Object.defineProperty(exports2, "__esModule", { value: true });
2045
- exports2.MAX_VALID_SLOT = exports2.REPLAY_SLOTS = void 0;
3155
+ exports2.REPLAY_BUCKETS = exports2.MAX_VALID_SLOT = exports2.REPLAY_SLOTS = exports2.DEPOSIT_COMPUTE_UNIT_LIMIT = void 0;
2046
3156
  exports2.generateNonce = generateNonce2;
2047
3157
  var crypto_1 = require("crypto");
3158
+ exports2.DEPOSIT_COMPUTE_UNIT_LIMIT = 4e5;
2048
3159
  exports2.REPLAY_SLOTS = 235;
2049
3160
  exports2.MAX_VALID_SLOT = exports2.REPLAY_SLOTS - 1;
2050
- var NONCE_BUCKET_MASK = 131071;
3161
+ exports2.REPLAY_BUCKETS = 256;
2051
3162
  var NONCE_BUCKET_SHIFT = 32n;
2052
3163
  function generateNonce2() {
2053
- const bucketBytes = (0, crypto_1.randomBytes)(4);
2054
- const bucketID = bucketBytes.readUInt32LE(0) & NONCE_BUCKET_MASK;
3164
+ const bucketID = (0, crypto_1.randomBytes)(4).readUInt32LE(0) % exports2.REPLAY_BUCKETS;
2055
3165
  let slot;
2056
3166
  do {
2057
3167
  slot = (0, crypto_1.randomBytes)(1)[0];
@@ -2062,11 +3172,11 @@ var require_nonce_generator2 = __commonJS({
2062
3172
  });
2063
3173
 
2064
3174
  // ../contracts/svm/escrow-encoding/typescript/dist/index.js
2065
- var require_dist3 = __commonJS({
3175
+ var require_dist4 = __commonJS({
2066
3176
  "../contracts/svm/escrow-encoding/typescript/dist/index.js"(exports2) {
2067
3177
  "use strict";
2068
3178
  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;
3179
+ 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.InvalidEscrowDomainError = exports2.ZeroSourceAmountError = 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.newEscrowDomain = exports2.escrowDomainPrefixBytes = exports2.isZeroBytes32 = exports2.stringToBytes = exports2.keccak256 = exports2.encodeU64LE = exports2.Pubkey = void 0;
2070
3180
  var pubkey_1 = require_pubkey();
2071
3181
  Object.defineProperty(exports2, "Pubkey", { enumerable: true, get: function() {
2072
3182
  return pubkey_1.Pubkey;
@@ -2088,12 +3198,24 @@ var require_dist3 = __commonJS({
2088
3198
  Object.defineProperty(exports2, "escrowDomainPrefixBytes", { enumerable: true, get: function() {
2089
3199
  return escrow_domain_1.escrowDomainPrefixBytes;
2090
3200
  } });
3201
+ Object.defineProperty(exports2, "newEscrowDomain", { enumerable: true, get: function() {
3202
+ return escrow_domain_1.newEscrowDomain;
3203
+ } });
2091
3204
  var errors_1 = require_errors2();
2092
3205
  Object.defineProperty(exports2, "EncodingError", { enumerable: true, get: function() {
2093
3206
  return errors_1.EncodingError;
2094
3207
  } });
2095
- Object.defineProperty(exports2, "ZeroPaymentIdError", { enumerable: true, get: function() {
2096
- return errors_1.ZeroPaymentIdError;
3208
+ Object.defineProperty(exports2, "ZeroDepositRequestHashError", { enumerable: true, get: function() {
3209
+ return errors_1.ZeroDepositRequestHashError;
3210
+ } });
3211
+ Object.defineProperty(exports2, "ZeroQuoteHashError", { enumerable: true, get: function() {
3212
+ return errors_1.ZeroQuoteHashError;
3213
+ } });
3214
+ Object.defineProperty(exports2, "EmptyDestinationError", { enumerable: true, get: function() {
3215
+ return errors_1.EmptyDestinationError;
3216
+ } });
3217
+ Object.defineProperty(exports2, "DestinationTooLongError", { enumerable: true, get: function() {
3218
+ return errors_1.DestinationTooLongError;
2097
3219
  } });
2098
3220
  Object.defineProperty(exports2, "ZeroDepositorError", { enumerable: true, get: function() {
2099
3221
  return errors_1.ZeroDepositorError;
@@ -2116,6 +3238,12 @@ var require_dist3 = __commonJS({
2116
3238
  Object.defineProperty(exports2, "ZeroDepositHashError", { enumerable: true, get: function() {
2117
3239
  return errors_1.ZeroDepositHashError;
2118
3240
  } });
3241
+ Object.defineProperty(exports2, "ZeroSourceAmountError", { enumerable: true, get: function() {
3242
+ return errors_1.ZeroSourceAmountError;
3243
+ } });
3244
+ Object.defineProperty(exports2, "InvalidEscrowDomainError", { enumerable: true, get: function() {
3245
+ return errors_1.InvalidEscrowDomainError;
3246
+ } });
2119
3247
  Object.defineProperty(exports2, "InvalidPubkeyLengthError", { enumerable: true, get: function() {
2120
3248
  return errors_1.InvalidPubkeyLengthError;
2121
3249
  } });
@@ -2129,18 +3257,39 @@ var require_dist3 = __commonJS({
2129
3257
  Object.defineProperty(exports2, "computeDepositHash", { enumerable: true, get: function() {
2130
3258
  return deposit_encoder_1.computeDepositHash;
2131
3259
  } });
3260
+ Object.defineProperty(exports2, "computeDepositHashV2", { enumerable: true, get: function() {
3261
+ return deposit_encoder_1.computeDepositHashV2;
3262
+ } });
3263
+ Object.defineProperty(exports2, "computeDestinationHash", { enumerable: true, get: function() {
3264
+ return deposit_encoder_1.computeDestinationHash;
3265
+ } });
3266
+ Object.defineProperty(exports2, "MAX_DESTINATION_LEN", { enumerable: true, get: function() {
3267
+ return deposit_encoder_1.MAX_DESTINATION_LEN;
3268
+ } });
2132
3269
  var reserve_encoder_1 = require_reserve_encoder3();
2133
3270
  Object.defineProperty(exports2, "computeReserveHash", { enumerable: true, get: function() {
2134
3271
  return reserve_encoder_1.computeReserveHash;
2135
3272
  } });
2136
- var release_encoder_1 = require_release_encoder();
3273
+ Object.defineProperty(exports2, "computeReserveHashV2", { enumerable: true, get: function() {
3274
+ return reserve_encoder_1.computeReserveHashV2;
3275
+ } });
3276
+ Object.defineProperty(exports2, "computeReserveHashV3", { enumerable: true, get: function() {
3277
+ return reserve_encoder_1.computeReserveHashV3;
3278
+ } });
3279
+ var release_encoder_1 = require_release_encoder3();
2137
3280
  Object.defineProperty(exports2, "computeReleaseHash", { enumerable: true, get: function() {
2138
3281
  return release_encoder_1.computeReleaseHash;
2139
3282
  } });
2140
- var refund_encoder_1 = require_refund_encoder();
3283
+ Object.defineProperty(exports2, "computeReleaseHashV2", { enumerable: true, get: function() {
3284
+ return release_encoder_1.computeReleaseHashV2;
3285
+ } });
3286
+ var refund_encoder_1 = require_refund_encoder3();
2141
3287
  Object.defineProperty(exports2, "computeRefundHash", { enumerable: true, get: function() {
2142
3288
  return refund_encoder_1.computeRefundHash;
2143
3289
  } });
3290
+ Object.defineProperty(exports2, "computeRefundHashV2", { enumerable: true, get: function() {
3291
+ return refund_encoder_1.computeRefundHashV2;
3292
+ } });
2144
3293
  var nonce_generator_1 = require_nonce_generator2();
2145
3294
  Object.defineProperty(exports2, "generateNonce", { enumerable: true, get: function() {
2146
3295
  return nonce_generator_1.generateNonce;
@@ -2151,6 +3300,12 @@ var require_dist3 = __commonJS({
2151
3300
  Object.defineProperty(exports2, "MAX_VALID_SLOT", { enumerable: true, get: function() {
2152
3301
  return nonce_generator_1.MAX_VALID_SLOT;
2153
3302
  } });
3303
+ Object.defineProperty(exports2, "REPLAY_BUCKETS", { enumerable: true, get: function() {
3304
+ return nonce_generator_1.REPLAY_BUCKETS;
3305
+ } });
3306
+ Object.defineProperty(exports2, "DEPOSIT_COMPUTE_UNIT_LIMIT", { enumerable: true, get: function() {
3307
+ return nonce_generator_1.DEPOSIT_COMPUTE_UNIT_LIMIT;
3308
+ } });
2154
3309
  }
2155
3310
  });
2156
3311
 
@@ -2166,7 +3321,8 @@ var require_solana = __commonJS({
2166
3321
  var ethers_1 = require("ethers");
2167
3322
  var tweetnacl_1 = __importDefault(require("tweetnacl"));
2168
3323
  var bs58_1 = __importDefault(require("bs58"));
2169
- var solana_escrow_encoding_1 = require_dist3();
3324
+ var solana_escrow_encoding_1 = require_dist4();
3325
+ var destination_js_1 = require_destination();
2170
3326
  var utils_js_1 = require_utils();
2171
3327
  var errors_js_1 = require_errors();
2172
3328
  var chain_id_js_1 = require_chain_id2();
@@ -2176,7 +3332,8 @@ var require_solana = __commonJS({
2176
3332
  }
2177
3333
  function hashDeposit(prehash, domain) {
2178
3334
  return (0, ethers_1.hexlify)((0, solana_escrow_encoding_1.computeDepositHash)({
2179
- paymentId: (0, ethers_1.getBytes)(prehash.payment_id),
3335
+ // The encoder field was renamed for cross-VM parity; the prehash WIRE key stays payment_id.
3336
+ depositRequestHash: (0, ethers_1.getBytes)(prehash.payment_id),
2180
3337
  depositor: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.depositor),
2181
3338
  mint: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.mint),
2182
3339
  amount: BigInt(prehash.amount),
@@ -2187,6 +3344,26 @@ var require_solana = __commonJS({
2187
3344
  deadline: BigInt(prehash.deadline)
2188
3345
  }, domain));
2189
3346
  }
3347
+ var SVM_DESTINATION_COMMITMENT_VERSION = 4;
3348
+ function hashDepositV2(prehash, domain) {
3349
+ return (0, ethers_1.hexlify)((0, solana_escrow_encoding_1.computeDepositHashV2)(
3350
+ {
3351
+ depositRequestHash: (0, ethers_1.getBytes)(prehash.deposit_request_hash),
3352
+ depositor: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.depositor),
3353
+ mint: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.mint),
3354
+ amount: BigInt(prehash.amount),
3355
+ reserver: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.reserver),
3356
+ releaser: solana_escrow_encoding_1.Pubkey.fromBase58(prehash.releaser),
3357
+ nonce: BigInt(prehash.nonce),
3358
+ issuedAt: BigInt(prehash.issued_at),
3359
+ deadline: BigInt(prehash.deadline)
3360
+ },
3361
+ // Plaintext, NOT pre-hashed: the encoder hashes it, and hashing an already-hashed
3362
+ // destination yields a well-formed commitment no on-chain state can satisfy.
3363
+ prehash.destination,
3364
+ domain
3365
+ ));
3366
+ }
2190
3367
  function domainFrom(defaults) {
2191
3368
  if (!defaults.escrowContract) {
2192
3369
  throw new Error("sender_auth: Solana source requires escrowContract (escrow program id) for the deposit-hash domain");
@@ -2201,12 +3378,11 @@ var require_solana = __commonJS({
2201
3378
  };
2202
3379
  }
2203
3380
  exports2.solanaAdapter = {
2204
- async buildAuthMessage({ sourceAsset, depositor, maxSourceAmount, requestId, sourceDefaults, nonce, solanaClockReader }) {
3381
+ async buildAuthMessage({ sourceAsset, depositor, maxSourceAmount, requestId, sourceDefaults, destinationAsset, destinationAccount, nonce, solanaClockReader }) {
2205
3382
  if (!requestId) {
2206
3383
  throw new Error("sender_auth: request_id is required");
2207
3384
  }
2208
- const sourceChainId = sourceAsset.split("/")[0];
2209
- const tokenMint = sourceAsset.split("/")[1].split(":")[1];
3385
+ const { network: sourceChainId, asset: tokenMint } = (0, utils_js_1.parseSourceAsset)(sourceAsset);
2210
3386
  const depositNonce = nonce !== void 0 ? BigInt(nonce) : (0, solana_escrow_encoding_1.generateNonce)();
2211
3387
  if (nonce !== void 0) {
2212
3388
  if (depositNonce < 0n || depositNonce >= 1n << 64n) {
@@ -2219,8 +3395,8 @@ var require_solana = __commonJS({
2219
3395
  const issuedAt = solanaClockReader ? await solanaClockReader(sourceChainId) : BigInt(Math.floor(Date.now() / 1e3));
2220
3396
  const deadline = issuedAt + BigInt(utils_js_1.REPLAY_HORIZON_SECS - 8);
2221
3397
  const paymentId = generateSolanaPaymentIdV3(requestId);
2222
- const prehash = {
2223
- payment_id: paymentId,
3398
+ const domain = domainFrom(sourceDefaults);
3399
+ const common = {
2224
3400
  depositor,
2225
3401
  mint: tokenMint,
2226
3402
  amount: BigInt(maxSourceAmount).toString(),
@@ -2230,7 +3406,20 @@ var require_solana = __commonJS({
2230
3406
  issued_at: issuedAt.toString(),
2231
3407
  deadline: deadline.toString()
2232
3408
  };
2233
- const depositHash = hashDeposit(prehash, domainFrom(sourceDefaults));
3409
+ if (domain.signatureDomainVersion >= SVM_DESTINATION_COMMITMENT_VERSION) {
3410
+ const prehashV2 = {
3411
+ deposit_request_hash: paymentId,
3412
+ destination: (0, destination_js_1.buildEscrowDestination)(destinationAsset, destinationAccount),
3413
+ ...common
3414
+ };
3415
+ return {
3416
+ messageScheme: "SOLANA",
3417
+ messageHash: hashDepositV2(prehashV2, domain),
3418
+ messagePrehash: JSON.stringify(prehashV2)
3419
+ };
3420
+ }
3421
+ const prehash = { payment_id: paymentId, ...common };
3422
+ const depositHash = hashDeposit(prehash, domain);
2234
3423
  return { messageScheme: "SOLANA", messageHash: depositHash, messagePrehash: JSON.stringify(prehash) };
2235
3424
  },
2236
3425
  async sign(signedMessage, privateKey) {
@@ -2276,8 +3465,18 @@ var require_solana = __commonJS({
2276
3465
  let prehash;
2277
3466
  let canonicalHash;
2278
3467
  try {
2279
- prehash = JSON.parse(signed.message_prehash);
2280
- canonicalHash = hashDeposit(prehash, domainFrom(expected));
3468
+ const domain = domainFrom(expected);
3469
+ if (domain.signatureDomainVersion >= SVM_DESTINATION_COMMITMENT_VERSION) {
3470
+ const v2 = JSON.parse(signed.message_prehash);
3471
+ if (typeof v2.deposit_request_hash !== "string" || typeof v2.destination !== "string") {
3472
+ throw new Error("pre-widening V1 prehash on a destination-committing domain");
3473
+ }
3474
+ canonicalHash = hashDepositV2(v2, domain);
3475
+ prehash = { payment_id: v2.deposit_request_hash, ...v2 };
3476
+ } else {
3477
+ prehash = JSON.parse(signed.message_prehash);
3478
+ canonicalHash = hashDeposit(prehash, domain);
3479
+ }
2281
3480
  } catch {
2282
3481
  throw new errors_js_1.MalformedPrehashError();
2283
3482
  }
@@ -2369,14 +3568,7 @@ var require_verify = __commonJS({
2369
3568
  Object.defineProperty(exports2, "__esModule", { value: true });
2370
3569
  exports2.verifyPaymentRequest = verifyPaymentRequest;
2371
3570
  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
- }
3571
+ var utils_js_1 = require_utils();
2380
3572
  function verifyPaymentRequest(request2, expected = {}) {
2381
3573
  const senderAuth = request2.sender_auth;
2382
3574
  if (!senderAuth?.signed_messages?.length) {
@@ -2385,7 +3577,7 @@ var require_verify = __commonJS({
2385
3577
  if (!request2.source) {
2386
3578
  throw new Error("sender_auth: request has no source");
2387
3579
  }
2388
- const requestSource = parseSourceAsset(request2.source.asset_identifier);
3580
+ const requestSource = (0, utils_js_1.parseSourceAsset)(request2.source.asset_identifier);
2389
3581
  const { sourceAsset, network: networkOverride, maxSourceAmount: amountOverride, ...scheme } = expected;
2390
3582
  const network = networkOverride ?? requestSource.network;
2391
3583
  const asset = sourceAsset ?? requestSource.asset;
@@ -2420,7 +3612,7 @@ var require_signer = __commonJS({
2420
3612
  });
2421
3613
 
2422
3614
  // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/index.js
2423
- var require_dist4 = __commonJS({
3615
+ var require_dist5 = __commonJS({
2424
3616
  "../schemas/declarations/PaymentRequest/v1/bindings/typescript/sender-auth/dist/index.js"(exports2) {
2425
3617
  "use strict";
2426
3618
  var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
@@ -2440,32 +3632,427 @@ var require_dist4 = __commonJS({
2440
3632
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
2441
3633
  };
2442
3634
  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;
3635
+ 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;
3636
+ __exportStar(require_types(), exports2);
3637
+ __exportStar(require_utils(), exports2);
3638
+ __exportStar(require_chain_id2(), exports2);
3639
+ var index_js_1 = require_adapters();
3640
+ Object.defineProperty(exports2, "getChainAdapter", { enumerable: true, get: function() {
3641
+ return index_js_1.getChainAdapter;
3642
+ } });
3643
+ var destination_js_1 = require_destination();
3644
+ Object.defineProperty(exports2, "buildEscrowDestination", { enumerable: true, get: function() {
3645
+ return destination_js_1.buildEscrowDestination;
3646
+ } });
3647
+ Object.defineProperty(exports2, "deriveDepositRequestHash", { enumerable: true, get: function() {
3648
+ return destination_js_1.deriveDepositRequestHash;
3649
+ } });
3650
+ Object.defineProperty(exports2, "MAX_DESTINATION_BYTES", { enumerable: true, get: function() {
3651
+ return destination_js_1.MAX_DESTINATION_BYTES;
3652
+ } });
3653
+ Object.defineProperty(exports2, "usesDestinationCommitment", { enumerable: true, get: function() {
3654
+ return destination_js_1.usesDestinationCommitment;
3655
+ } });
3656
+ Object.defineProperty(exports2, "DESTINATION_COMMITMENT_WITNESS_VERSION", { enumerable: true, get: function() {
3657
+ return destination_js_1.DESTINATION_COMMITMENT_WITNESS_VERSION;
3658
+ } });
3659
+ var verify_js_1 = require_verify();
3660
+ Object.defineProperty(exports2, "verifyPaymentRequest", { enumerable: true, get: function() {
3661
+ return verify_js_1.verifyPaymentRequest;
3662
+ } });
3663
+ var errors_js_1 = require_errors();
3664
+ Object.defineProperty(exports2, "MalformedPrehashError", { enumerable: true, get: function() {
3665
+ return errors_js_1.MalformedPrehashError;
3666
+ } });
3667
+ Object.defineProperty(exports2, "RecoveryFailedError", { enumerable: true, get: function() {
3668
+ return errors_js_1.RecoveryFailedError;
3669
+ } });
3670
+ Object.defineProperty(exports2, "SignerMismatchError", { enumerable: true, get: function() {
3671
+ return errors_js_1.SignerMismatchError;
3672
+ } });
3673
+ var signer_js_1 = require_signer();
3674
+ Object.defineProperty(exports2, "localKeySigner", { enumerable: true, get: function() {
3675
+ return signer_js_1.localKeySigner;
3676
+ } });
3677
+ }
3678
+ });
3679
+
3680
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/allowance.js
3681
+ var require_allowance = __commonJS({
3682
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/allowance.js"(exports2) {
3683
+ "use strict";
3684
+ Object.defineProperty(exports2, "__esModule", { value: true });
3685
+ exports2.UNLIMITED_APPROVAL_FLOOR = exports2.UNLIMITED_APPROVAL = void 0;
3686
+ exports2.isAllowanceSufficient = isAllowanceSufficient;
3687
+ exports2.effectiveRequirement = effectiveRequirement;
3688
+ exports2.resolveApprovalAmount = resolveApprovalAmount;
3689
+ var ethers_1 = require("ethers");
3690
+ exports2.UNLIMITED_APPROVAL = ethers_1.MaxUint256;
3691
+ exports2.UNLIMITED_APPROVAL_FLOOR = ethers_1.MaxUint256 / 2n;
3692
+ function isAllowanceSufficient(current, requiredAllowance) {
3693
+ return requiredAllowance !== void 0 ? current >= requiredAllowance : current >= exports2.UNLIMITED_APPROVAL_FLOOR;
3694
+ }
3695
+ function effectiveRequirement(requiredAllowance, approvalAmount) {
3696
+ return requiredAllowance ?? approvalAmount;
3697
+ }
3698
+ function resolveApprovalAmount(approvalAmount, requiredAllowance) {
3699
+ if (approvalAmount === void 0)
3700
+ return exports2.UNLIMITED_APPROVAL;
3701
+ if (approvalAmount <= 0n) {
3702
+ throw new Error(`token_approval: approvalAmount must be positive, got ${approvalAmount}`);
3703
+ }
3704
+ if (requiredAllowance !== void 0 && approvalAmount < requiredAllowance) {
3705
+ 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`);
3706
+ }
3707
+ return approvalAmount;
3708
+ }
3709
+ }
3710
+ });
3711
+
3712
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/unconfirmed.js
3713
+ var require_unconfirmed = __commonJS({
3714
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/unconfirmed.js"(exports2) {
3715
+ "use strict";
3716
+ Object.defineProperty(exports2, "__esModule", { value: true });
3717
+ exports2.unconfirmed = unconfirmed;
3718
+ exports2.isUnconfirmed = isUnconfirmed2;
3719
+ function unconfirmed(message) {
3720
+ return Object.assign(new Error(message), { unconfirmed: true });
3721
+ }
3722
+ function isUnconfirmed2(error) {
3723
+ return error?.unconfirmed === true;
3724
+ }
3725
+ }
3726
+ });
3727
+
3728
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/evm.js
3729
+ var require_evm2 = __commonJS({
3730
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/evm.js"(exports2) {
3731
+ "use strict";
3732
+ Object.defineProperty(exports2, "__esModule", { value: true });
3733
+ exports2.evmAdapter = exports2.ERC20_ALLOWANCE_ABI = void 0;
3734
+ var ethers_1 = require("ethers");
3735
+ var evm_escrow_encoding_1 = require_dist3();
3736
+ var unconfirmed_js_1 = require_unconfirmed();
3737
+ exports2.ERC20_ALLOWANCE_ABI = [
3738
+ "function allowance(address owner, address spender) view returns (uint256)",
3739
+ "function approve(address spender, uint256 amount) returns (bool)"
3740
+ ];
3741
+ var DEFAULT_CONFIRMATION_TIMEOUT_MS = 6e4;
3742
+ function requireSigner(params) {
3743
+ if (!params.signer) {
3744
+ throw new Error(`token_approval: approving on ${params.network} needs an ethers signer connected to that chain (params.signer)`);
3745
+ }
3746
+ return params.signer;
3747
+ }
3748
+ function erc20(params) {
3749
+ return new ethers_1.Contract(params.token, exports2.ERC20_ALLOWANCE_ABI, requireSigner(params));
3750
+ }
3751
+ async function send(params, call, purpose) {
3752
+ const tx = await call;
3753
+ params.onSubmitted?.(tx.hash, purpose);
3754
+ const timeoutMs = params.confirmation?.timeoutMs ?? DEFAULT_CONFIRMATION_TIMEOUT_MS;
3755
+ try {
3756
+ await tx.wait(1, timeoutMs);
3757
+ } catch (error) {
3758
+ if (isTimeout(error)) {
3759
+ 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.`);
3760
+ }
3761
+ throw error;
3762
+ }
3763
+ return tx.hash;
3764
+ }
3765
+ function isTimeout(error) {
3766
+ return error?.code === "TIMEOUT";
3767
+ }
3768
+ exports2.evmAdapter = {
3769
+ applicable: true,
3770
+ resolveSpender(params) {
3771
+ return params.spender ?? evm_escrow_encoding_1.PERMIT2_CONTRACT_ADDRESS;
3772
+ },
3773
+ async senderAddress(params) {
3774
+ return await requireSigner(params).getAddress();
3775
+ },
3776
+ async readAllowance(params, spender) {
3777
+ return await erc20(params).allowance(params.owner, spender);
3778
+ },
3779
+ async approve(params, spender, amount, current) {
3780
+ const token = erc20(params);
3781
+ if (current !== 0n && await refusesOverwrite(params, token, spender, amount)) {
3782
+ const nonce = await requireSigner(params).getNonce("pending");
3783
+ const resetTxHash = await send(params, token.approve(spender, 0n, { nonce }), "reset");
3784
+ try {
3785
+ return {
3786
+ txHash: await send(params, token.approve(spender, amount, { nonce: nonce + 1 }), "approval"),
3787
+ resetTxHash
3788
+ };
3789
+ } catch (error) {
3790
+ const detail = error instanceof Error ? error.message : String(error);
3791
+ if ((0, unconfirmed_js_1.isUnconfirmed)(error)) {
3792
+ 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.`);
3793
+ }
3794
+ 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.`);
3795
+ }
3796
+ }
3797
+ return { txHash: await send(params, token.approve(spender, amount), "approval") };
3798
+ }
3799
+ };
3800
+ async function refusesOverwrite(params, token, spender, amount) {
3801
+ const data = token.interface.encodeFunctionData("approve", [spender, amount]);
3802
+ try {
3803
+ await requireSigner(params).call({ to: params.token, data });
3804
+ return false;
3805
+ } catch (error) {
3806
+ if (isRevert(error))
3807
+ return true;
3808
+ throw error;
3809
+ }
3810
+ }
3811
+ function isRevert(error) {
3812
+ return error?.code === "CALL_EXCEPTION";
3813
+ }
3814
+ }
3815
+ });
3816
+
3817
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/tron.js
3818
+ var require_tron2 = __commonJS({
3819
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/tron.js"(exports2) {
3820
+ "use strict";
3821
+ Object.defineProperty(exports2, "__esModule", { value: true });
3822
+ exports2.tronAdapter = exports2.TRC20_ALLOWANCE_ABI = void 0;
3823
+ var payment_request_sender_auth_1 = require_dist5();
3824
+ var unconfirmed_js_1 = require_unconfirmed();
3825
+ exports2.TRC20_ALLOWANCE_ABI = [
3826
+ {
3827
+ name: "allowance",
3828
+ type: "function",
3829
+ stateMutability: "View",
3830
+ inputs: [
3831
+ { name: "owner", type: "address" },
3832
+ { name: "spender", type: "address" }
3833
+ ],
3834
+ outputs: [{ type: "uint256" }]
3835
+ },
3836
+ {
3837
+ name: "approve",
3838
+ type: "function",
3839
+ stateMutability: "Nonpayable",
3840
+ inputs: [
3841
+ { name: "spender", type: "address" },
3842
+ { name: "amount", type: "uint256" }
3843
+ ],
3844
+ outputs: [{ type: "bool" }]
3845
+ }
3846
+ ];
3847
+ var DEFAULT_FEE_LIMIT = 1e8;
3848
+ var DEFAULT_CONFIRMATION_TIMEOUT_MS = 6e4;
3849
+ var DEFAULT_POLL_INTERVAL_MS2 = 1500;
3850
+ function requireTronWeb(params) {
3851
+ if (!params.tronWeb) {
3852
+ throw new Error(`token_approval: approving on ${params.network} needs a TronWeb instance configured for that chain (params.tronWeb)`);
3853
+ }
3854
+ return params.tronWeb;
3855
+ }
3856
+ function token(params) {
3857
+ return requireTronWeb(params).contract(exports2.TRC20_ALLOWANCE_ABI, params.token);
3858
+ }
3859
+ var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
3860
+ async function waitForConfirmation(tronWeb, txId, options) {
3861
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_CONFIRMATION_TIMEOUT_MS;
3862
+ const pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
3863
+ const deadline = Date.now() + timeoutMs;
3864
+ for (; ; ) {
3865
+ let result;
3866
+ try {
3867
+ result = (await tronWeb.trx.getTransactionInfo(txId))?.receipt?.result;
3868
+ } catch {
3869
+ }
3870
+ if (result === "SUCCESS")
3871
+ return;
3872
+ if (result !== void 0) {
3873
+ throw new Error(`token_approval: Tron approval ${txId} failed on-chain (${result})`);
3874
+ }
3875
+ if (Date.now() >= deadline) {
3876
+ 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.`);
3877
+ }
3878
+ await sleep(pollIntervalMs);
3879
+ }
3880
+ }
3881
+ async function send(params, contract, spender, amount, purpose) {
3882
+ const txId = await contract.approve(spender, amount.toString()).send({ feeLimit: params.confirmation?.feeLimit ?? DEFAULT_FEE_LIMIT });
3883
+ params.onSubmitted?.(txId, purpose);
3884
+ await waitForConfirmation(requireTronWeb(params), txId, params.confirmation);
3885
+ return txId;
3886
+ }
3887
+ exports2.tronAdapter = {
3888
+ applicable: true,
3889
+ resolveSpender(params) {
3890
+ return params.spender ?? (0, payment_request_sender_auth_1.resolveTronPermit2)(params.network);
3891
+ },
3892
+ async senderAddress(params) {
3893
+ return requireTronWeb(params).defaultAddress?.base58 || void 0;
3894
+ },
3895
+ async readAllowance(params, spender) {
3896
+ const raw = await token(params).allowance(params.owner, spender).call();
3897
+ return BigInt(String(raw));
3898
+ },
3899
+ async approve(params, spender, amount, current) {
3900
+ const contract = token(params);
3901
+ try {
3902
+ return { txHash: await send(params, contract, spender, amount, "approval") };
3903
+ } catch (error) {
3904
+ if (current === 0n || (0, unconfirmed_js_1.isUnconfirmed)(error))
3905
+ throw error;
3906
+ 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.`);
3907
+ }
3908
+ }
3909
+ };
3910
+ }
3911
+ });
3912
+
3913
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/solana.js
3914
+ var require_solana2 = __commonJS({
3915
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/solana.js"(exports2) {
3916
+ "use strict";
3917
+ Object.defineProperty(exports2, "__esModule", { value: true });
3918
+ exports2.solanaAdapter = void 0;
3919
+ exports2.solanaAdapter = {
3920
+ applicable: false,
3921
+ resolveSpender() {
3922
+ throw new Error("token_approval: Solana does not use a Permit2-style allowance");
3923
+ },
3924
+ async senderAddress() {
3925
+ throw new Error("token_approval: Solana does not use a Permit2-style allowance");
3926
+ },
3927
+ async readAllowance() {
3928
+ throw new Error("token_approval: Solana does not use a Permit2-style allowance");
3929
+ },
3930
+ async approve() {
3931
+ throw new Error("token_approval: Solana does not use a Permit2-style allowance");
3932
+ }
3933
+ };
3934
+ }
3935
+ });
3936
+
3937
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/index.js
3938
+ var require_adapters2 = __commonJS({
3939
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/adapters/index.js"(exports2) {
3940
+ "use strict";
3941
+ Object.defineProperty(exports2, "__esModule", { value: true });
3942
+ exports2.approvalAdapterFor = approvalAdapterFor;
3943
+ var payment_request_sender_auth_1 = require_dist5();
3944
+ var evm_js_1 = require_evm2();
3945
+ var tron_js_1 = require_tron2();
3946
+ var solana_js_1 = require_solana2();
3947
+ var ADAPTERS = {
3948
+ eip155: evm_js_1.evmAdapter,
3949
+ tron: tron_js_1.tronAdapter,
3950
+ solana: solana_js_1.solanaAdapter
3951
+ };
3952
+ function approvalAdapterFor(network) {
3953
+ const namespace = (0, payment_request_sender_auth_1.namespaceOf)(network);
3954
+ const adapter = Object.hasOwn(ADAPTERS, namespace) ? ADAPTERS[namespace] : void 0;
3955
+ if (!adapter) {
3956
+ throw new Error(`token_approval: no approval adapter for network '${network}'`);
3957
+ }
3958
+ return adapter;
3959
+ }
3960
+ }
3961
+ });
3962
+
3963
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/sender.js
3964
+ var require_sender = __commonJS({
3965
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/sender.js"(exports2) {
3966
+ "use strict";
3967
+ Object.defineProperty(exports2, "__esModule", { value: true });
3968
+ exports2.assertSenderIsOwner = assertSenderIsOwner;
3969
+ function assertSenderIsOwner(owner, sender) {
3970
+ if (sender === void 0 || sender.toLowerCase() === owner.toLowerCase())
3971
+ return;
3972
+ 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}.`);
3973
+ }
3974
+ }
3975
+ });
3976
+
3977
+ // ../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/index.js
3978
+ var require_dist6 = __commonJS({
3979
+ "../schemas/declarations/PaymentRequest/v1/bindings/typescript/token-approval/dist/index.js"(exports2) {
3980
+ "use strict";
3981
+ Object.defineProperty(exports2, "__esModule", { value: true });
3982
+ exports2.approvalAdapterFor = exports2.isUnconfirmed = exports2.assertSenderIsOwner = exports2.resolveApprovalAmount = exports2.isAllowanceSufficient = exports2.effectiveRequirement = exports2.UNLIMITED_APPROVAL_FLOOR = exports2.UNLIMITED_APPROVAL = void 0;
3983
+ exports2.needsSourceApproval = needsSourceApproval2;
3984
+ exports2.ensureSourceApproval = ensureSourceApproval2;
3985
+ var allowance_js_1 = require_allowance();
3986
+ var index_js_1 = require_adapters2();
3987
+ var sender_js_1 = require_sender();
3988
+ var allowance_js_2 = require_allowance();
3989
+ Object.defineProperty(exports2, "UNLIMITED_APPROVAL", { enumerable: true, get: function() {
3990
+ return allowance_js_2.UNLIMITED_APPROVAL;
2450
3991
  } });
2451
- var verify_js_1 = require_verify();
2452
- Object.defineProperty(exports2, "verifyPaymentRequest", { enumerable: true, get: function() {
2453
- return verify_js_1.verifyPaymentRequest;
3992
+ Object.defineProperty(exports2, "UNLIMITED_APPROVAL_FLOOR", { enumerable: true, get: function() {
3993
+ return allowance_js_2.UNLIMITED_APPROVAL_FLOOR;
2454
3994
  } });
2455
- var errors_js_1 = require_errors();
2456
- Object.defineProperty(exports2, "MalformedPrehashError", { enumerable: true, get: function() {
2457
- return errors_js_1.MalformedPrehashError;
3995
+ Object.defineProperty(exports2, "effectiveRequirement", { enumerable: true, get: function() {
3996
+ return allowance_js_2.effectiveRequirement;
2458
3997
  } });
2459
- Object.defineProperty(exports2, "RecoveryFailedError", { enumerable: true, get: function() {
2460
- return errors_js_1.RecoveryFailedError;
3998
+ Object.defineProperty(exports2, "isAllowanceSufficient", { enumerable: true, get: function() {
3999
+ return allowance_js_2.isAllowanceSufficient;
2461
4000
  } });
2462
- Object.defineProperty(exports2, "SignerMismatchError", { enumerable: true, get: function() {
2463
- return errors_js_1.SignerMismatchError;
4001
+ Object.defineProperty(exports2, "resolveApprovalAmount", { enumerable: true, get: function() {
4002
+ return allowance_js_2.resolveApprovalAmount;
2464
4003
  } });
2465
- var signer_js_1 = require_signer();
2466
- Object.defineProperty(exports2, "localKeySigner", { enumerable: true, get: function() {
2467
- return signer_js_1.localKeySigner;
4004
+ var sender_js_2 = require_sender();
4005
+ Object.defineProperty(exports2, "assertSenderIsOwner", { enumerable: true, get: function() {
4006
+ return sender_js_2.assertSenderIsOwner;
4007
+ } });
4008
+ var unconfirmed_js_1 = require_unconfirmed();
4009
+ Object.defineProperty(exports2, "isUnconfirmed", { enumerable: true, get: function() {
4010
+ return unconfirmed_js_1.isUnconfirmed;
2468
4011
  } });
4012
+ var index_js_2 = require_adapters2();
4013
+ Object.defineProperty(exports2, "approvalAdapterFor", { enumerable: true, get: function() {
4014
+ return index_js_2.approvalAdapterFor;
4015
+ } });
4016
+ async function needsSourceApproval2(params) {
4017
+ const adapter = (0, index_js_1.approvalAdapterFor)(params.network);
4018
+ if (!adapter.applicable)
4019
+ return false;
4020
+ const required = (0, allowance_js_1.effectiveRequirement)(params.requiredAllowance, params.approvalAmount);
4021
+ (0, allowance_js_1.resolveApprovalAmount)(params.approvalAmount, required);
4022
+ const spender = adapter.resolveSpender(params);
4023
+ const current = await adapter.readAllowance(params, spender);
4024
+ return !(0, allowance_js_1.isAllowanceSufficient)(current, required);
4025
+ }
4026
+ async function ensureSourceApproval2(params) {
4027
+ const adapter = (0, index_js_1.approvalAdapterFor)(params.network);
4028
+ if (!adapter.applicable)
4029
+ return { alreadySufficient: true };
4030
+ const required = (0, allowance_js_1.effectiveRequirement)(params.requiredAllowance, params.approvalAmount);
4031
+ const amount = (0, allowance_js_1.resolveApprovalAmount)(params.approvalAmount, required);
4032
+ const spender = adapter.resolveSpender(params);
4033
+ const current = await adapter.readAllowance(params, spender);
4034
+ if ((0, allowance_js_1.isAllowanceSufficient)(current, required)) {
4035
+ return { alreadySufficient: true };
4036
+ }
4037
+ (0, sender_js_1.assertSenderIsOwner)(params.owner, await adapter.senderAddress(params));
4038
+ return { alreadySufficient: false, ...await adapter.approve(params, spender, amount, current) };
4039
+ }
4040
+ }
4041
+ });
4042
+
4043
+ // src/signers/pinned-address.ts
4044
+ function requirePinnedSender(pinnedAddress) {
4045
+ if (pinnedAddress === null || pinnedAddress === void 0) return void 0;
4046
+ if (typeof pinnedAddress !== "string" || pinnedAddress.trim() === "") {
4047
+ throw new Error(
4048
+ "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."
4049
+ );
4050
+ }
4051
+ return pinnedAddress;
4052
+ }
4053
+ var init_pinned_address = __esm({
4054
+ "src/signers/pinned-address.ts"() {
4055
+ "use strict";
2469
4056
  }
2470
4057
  });
2471
4058
 
@@ -2566,7 +4153,7 @@ var require_policy = __commonJS({
2566
4153
  });
2567
4154
 
2568
4155
  // ../key-management/common/typescript/dist/index.js
2569
- var require_dist5 = __commonJS({
4156
+ var require_dist7 = __commonJS({
2570
4157
  "../key-management/common/typescript/dist/index.js"(exports2) {
2571
4158
  "use strict";
2572
4159
  var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
@@ -2708,7 +4295,7 @@ var require_client = __commonJS({
2708
4295
  Object.defineProperty(exports2, "__esModule", { value: true });
2709
4296
  exports2.TurnkeyClient = void 0;
2710
4297
  var promises_1 = require("timers/promises");
2711
- var km_core_1 = require_dist5();
4298
+ var km_core_1 = require_dist7();
2712
4299
  var constants_1 = require_constants();
2713
4300
  var logger_1 = require_logger();
2714
4301
  var meter_1 = require_meter();
@@ -2860,7 +4447,8 @@ var require_client = __commonJS({
2860
4447
  }
2861
4448
  if (activity?.status !== "ACTIVITY_STATUS_COMPLETED") {
2862
4449
  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)}`);
4450
+ const fp = activity?.fingerprint ? ` fingerprint=${activity.fingerprint}` : "";
4451
+ 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
4452
  }
2865
4453
  if (activity.result == null) {
2866
4454
  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 +4675,7 @@ var require_signer_base = __commonJS({
3087
4675
  Object.defineProperty(exports2, "__esModule", { value: true });
3088
4676
  exports2.resolveTurnkeyAccountAddress = resolveTurnkeyAccountAddress;
3089
4677
  var promises_1 = require("timers/promises");
3090
- var km_core_1 = require_dist5();
4678
+ var km_core_1 = require_dist7();
3091
4679
  var constants_1 = require_constants();
3092
4680
  var DISCOVERY_BACKOFF_MS = constants_1.TURNKEY_RETRY_BACKOFF_MS;
3093
4681
  async function resolveTurnkeyAccountAddress(deps, addressFormat) {
@@ -3146,7 +4734,7 @@ var require_secp256k1_helpers = __commonJS({
3146
4734
  exports2.signSecp256k1TypedDataAndVerify = signSecp256k1TypedDataAndVerify;
3147
4735
  exports2.bytesFromHexOrBytes = bytesFromHexOrBytes;
3148
4736
  var ethers_1 = require("ethers");
3149
- var km_core_1 = require_dist5();
4737
+ var km_core_1 = require_dist7();
3150
4738
  var EIP712_HASH_FUNCTION = "HASH_FUNCTION_NOT_APPLICABLE";
3151
4739
  async function signSecp256k1PreimageAndVerify(client, signWith, preimage, expectedEvmAddrLower) {
3152
4740
  const preimageHex = (0, ethers_1.hexlify)(preimage).slice(2);
@@ -3193,13 +4781,13 @@ var require_secp256k1_helpers = __commonJS({
3193
4781
  });
3194
4782
 
3195
4783
  // ../key-management/providers/turnkey/typescript/dist/chains/evm.js
3196
- var require_evm2 = __commonJS({
4784
+ var require_evm3 = __commonJS({
3197
4785
  "../key-management/providers/turnkey/typescript/dist/chains/evm.js"(exports2) {
3198
4786
  "use strict";
3199
4787
  Object.defineProperty(exports2, "__esModule", { value: true });
3200
4788
  exports2.TurnkeyEvmSigner = void 0;
3201
4789
  var ethers_1 = require("ethers");
3202
- var km_core_1 = require_dist5();
4790
+ var km_core_1 = require_dist7();
3203
4791
  var signer_base_1 = require_signer_base();
3204
4792
  var secp256k1_helpers_1 = require_secp256k1_helpers();
3205
4793
  var ADDRESS_FORMAT = "ADDRESS_FORMAT_ETHEREUM";
@@ -3315,7 +4903,7 @@ ${msgBytes.length}`);
3315
4903
  });
3316
4904
 
3317
4905
  // ../key-management/providers/turnkey/typescript/dist/chains/solana.js
3318
- var require_solana2 = __commonJS({
4906
+ var require_solana3 = __commonJS({
3319
4907
  "../key-management/providers/turnkey/typescript/dist/chains/solana.js"(exports2) {
3320
4908
  "use strict";
3321
4909
  var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
@@ -3363,7 +4951,7 @@ var require_solana2 = __commonJS({
3363
4951
  exports2.encodePayload = encodePayload;
3364
4952
  var web3_js_1 = require("@solana/web3.js");
3365
4953
  var bs58_1 = __importDefault(require("bs58"));
3366
- var km_core_1 = require_dist5();
4954
+ var km_core_1 = require_dist7();
3367
4955
  var signer_base_1 = require_signer_base();
3368
4956
  var ADDRESS_FORMAT = "ADDRESS_FORMAT_SOLANA";
3369
4957
  var TurnkeySolanaSigner2 = class {
@@ -3456,7 +5044,7 @@ var require_solana2 = __commonJS({
3456
5044
  });
3457
5045
 
3458
5046
  // ../key-management/providers/turnkey/typescript/dist/chains/tron.js
3459
- var require_tron2 = __commonJS({
5047
+ var require_tron3 = __commonJS({
3460
5048
  "../key-management/providers/turnkey/typescript/dist/chains/tron.js"(exports2) {
3461
5049
  "use strict";
3462
5050
  var __importDefault = exports2 && exports2.__importDefault || function(mod) {
@@ -3468,7 +5056,7 @@ var require_tron2 = __commonJS({
3468
5056
  var bs58_1 = __importDefault(require("bs58"));
3469
5057
  var ethers_1 = require("ethers");
3470
5058
  var node_crypto_1 = require("crypto");
3471
- var km_core_1 = require_dist5();
5059
+ var km_core_1 = require_dist7();
3472
5060
  var signer_base_1 = require_signer_base();
3473
5061
  var secp256k1_helpers_1 = require_secp256k1_helpers();
3474
5062
  var ADDRESS_FORMAT = "ADDRESS_FORMAT_TRON";
@@ -3690,6 +5278,200 @@ var require_users = __commonJS({
3690
5278
  }
3691
5279
  });
3692
5280
 
5281
+ // ../key-management/providers/turnkey/typescript/dist/admin/activities.js
5282
+ var require_activities = __commonJS({
5283
+ "../key-management/providers/turnkey/typescript/dist/admin/activities.js"(exports2) {
5284
+ "use strict";
5285
+ Object.defineProperty(exports2, "__esModule", { value: true });
5286
+ exports2.getRootQuorum = getRootQuorum;
5287
+ exports2.getActivity = getActivity;
5288
+ exports2.listPendingActivities = listPendingActivities;
5289
+ exports2.approvedVoterIds = approvedVoterIds;
5290
+ exports2.approveActivity = approveActivity;
5291
+ async function getRootQuorum(client, organizationId) {
5292
+ const r = await client.query("/public/v1/query/get_organization", { organizationId });
5293
+ const q = r.organizationData?.rootQuorum;
5294
+ if (typeof q?.threshold !== "number") {
5295
+ throw new Error(`get_organization on ${organizationId} returned no rootQuorum.threshold: ${JSON.stringify(r).slice(0, 200)}`);
5296
+ }
5297
+ return { threshold: q.threshold, userIds: q.userIds ?? [] };
5298
+ }
5299
+ async function getActivity(client, organizationId, activityId) {
5300
+ const r = await client.query("/public/v1/query/get_activity", {
5301
+ organizationId,
5302
+ activityId
5303
+ });
5304
+ if (!r.activity?.id) {
5305
+ throw new Error(`get_activity returned no activity for ${activityId} in ${organizationId}`);
5306
+ }
5307
+ return r.activity;
5308
+ }
5309
+ async function listPendingActivities(client, organizationId) {
5310
+ const r = await client.query("/public/v1/query/list_activities", { organizationId, filterByStatus: ["ACTIVITY_STATUS_CONSENSUS_NEEDED"] });
5311
+ return r.activities ?? [];
5312
+ }
5313
+ function approvedVoterIds(activity) {
5314
+ const ids = (activity.votes ?? []).filter((v) => v.selection === "VOTE_SELECTION_APPROVED").map((v) => v.userId).filter((id) => Boolean(id));
5315
+ return new Set(ids);
5316
+ }
5317
+ async function approveActivity(client, organizationId, fingerprint) {
5318
+ const r = await client.query("/public/v1/submit/approve_activity", {
5319
+ type: "ACTIVITY_TYPE_APPROVE_ACTIVITY",
5320
+ timestampMs: String(Date.now()),
5321
+ organizationId,
5322
+ parameters: { fingerprint }
5323
+ });
5324
+ if (!r.activity) {
5325
+ throw new Error(`approve_activity returned no activity for ${fingerprint}`);
5326
+ }
5327
+ return r.activity;
5328
+ }
5329
+ }
5330
+ });
5331
+
5332
+ // ../key-management/providers/turnkey/typescript/dist/admin/api-keys.js
5333
+ var require_api_keys = __commonJS({
5334
+ "../key-management/providers/turnkey/typescript/dist/admin/api-keys.js"(exports2) {
5335
+ "use strict";
5336
+ Object.defineProperty(exports2, "__esModule", { value: true });
5337
+ exports2.UnsafeRevocationError = exports2.MAX_API_KEYS_PER_USER = void 0;
5338
+ exports2.getUser = getUser;
5339
+ exports2.listUsers = listUsers;
5340
+ exports2.addApiKeys = addApiKeys;
5341
+ exports2.deleteApiKeys = deleteApiKeys;
5342
+ exports2.isDurableApiKey = isDurableApiKey;
5343
+ exports2.isExpiredApiKey = isExpiredApiKey;
5344
+ exports2.planRevocation = planRevocation;
5345
+ exports2.findApiKeyByPublicKey = findApiKeyByPublicKey;
5346
+ exports2.MAX_API_KEYS_PER_USER = 10;
5347
+ async function getUser(client, organizationId, userId) {
5348
+ const r = await client.query("/public/v1/query/get_user", {
5349
+ organizationId,
5350
+ userId
5351
+ });
5352
+ if (!r.user?.userId) {
5353
+ throw new Error(`get_user returned no user for ${userId} in ${organizationId}`);
5354
+ }
5355
+ return normalizeUser(r.user);
5356
+ }
5357
+ async function listUsers(client, organizationId) {
5358
+ const r = await client.query("/public/v1/query/list_users", {
5359
+ organizationId
5360
+ });
5361
+ return (r.users ?? []).map(normalizeUser);
5362
+ }
5363
+ async function addApiKeys(client, input) {
5364
+ if (input.apiKeys.length === 0)
5365
+ throw new Error("addApiKeys called with no keys");
5366
+ const result = await client.executeActivity("ACTIVITY_TYPE_CREATE_API_KEYS_V2", "create_api_keys", {
5367
+ userId: input.userId,
5368
+ apiKeys: input.apiKeys.map((k) => ({
5369
+ apiKeyName: k.apiKeyName,
5370
+ publicKey: k.publicKey,
5371
+ curveType: k.curveType ?? "API_KEY_CURVE_P256",
5372
+ ...k.expirationSeconds ? { expirationSeconds: k.expirationSeconds } : {}
5373
+ }))
5374
+ });
5375
+ const ids = result.createApiKeysResult?.apiKeyIds;
5376
+ if (!ids?.length) {
5377
+ throw new Error(`CREATE_API_KEYS_V2 returned no apiKeyIds for user ${input.userId}: ${JSON.stringify(result)}`);
5378
+ }
5379
+ return ids;
5380
+ }
5381
+ async function deleteApiKeys(client, input) {
5382
+ if (input.apiKeyIds.length === 0)
5383
+ throw new Error("deleteApiKeys called with no apiKeyIds");
5384
+ const result = await client.executeActivity("ACTIVITY_TYPE_DELETE_API_KEYS", "delete_api_keys", { userId: input.userId, apiKeyIds: [...input.apiKeyIds] });
5385
+ return result.deleteApiKeysResult?.apiKeyIds ?? [];
5386
+ }
5387
+ function isDurableApiKey(key) {
5388
+ return !key.expirationSeconds;
5389
+ }
5390
+ function isExpiredApiKey(key, nowSeconds) {
5391
+ if (!key.expirationSeconds)
5392
+ return false;
5393
+ const created = Number(key.createdAt?.seconds);
5394
+ const ttl = Number(key.expirationSeconds);
5395
+ if (!Number.isFinite(created) || !Number.isFinite(ttl))
5396
+ return false;
5397
+ return created + ttl <= nowSeconds;
5398
+ }
5399
+ var UnsafeRevocationError = class extends Error {
5400
+ code;
5401
+ constructor(code, message) {
5402
+ super(message);
5403
+ this.code = code;
5404
+ this.name = "UnsafeRevocationError";
5405
+ }
5406
+ };
5407
+ exports2.UnsafeRevocationError = UnsafeRevocationError;
5408
+ function planRevocation(input) {
5409
+ const { user, nowSeconds } = input;
5410
+ const stampingPub = input.stampingPublicKey.toLowerCase();
5411
+ const verifyPub = input.verifyPublicKey?.toLowerCase();
5412
+ const explicitIds = input.explicitIds;
5413
+ if (explicitIds.length === 0) {
5414
+ 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.`);
5415
+ }
5416
+ const byId = new Map(user.apiKeys.map((k) => [k.apiKeyId, k]));
5417
+ const unknown = explicitIds.filter((id) => !byId.has(id));
5418
+ if (unknown.length > 0) {
5419
+ 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.`);
5420
+ }
5421
+ const targets = [...new Set(explicitIds)].map((id) => byId.get(id));
5422
+ const revokedIds = new Set(targets.map((k) => k.apiKeyId));
5423
+ const survivors = user.apiKeys.filter((k) => !revokedIds.has(k.apiKeyId));
5424
+ const live = survivors.filter((k) => !isExpiredApiKey(k, nowSeconds));
5425
+ const durableSurvivors = live.filter(isDurableApiKey);
5426
+ const hasPasskey = user.authenticators.length > 0;
5427
+ const stampingKey = user.apiKeys.find((k) => k.credential?.publicKey?.toLowerCase() === stampingPub);
5428
+ if (input.selfRotation && !stampingKey) {
5429
+ 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.`);
5430
+ }
5431
+ const suicidal = targets.find((k) => k.credential?.publicKey?.toLowerCase() === stampingPub);
5432
+ if (suicidal) {
5433
+ 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.`);
5434
+ }
5435
+ if (verifyPub) {
5436
+ const survivor = user.apiKeys.find((k) => k.credential?.publicKey?.toLowerCase() === verifyPub);
5437
+ if (!survivor) {
5438
+ 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.`);
5439
+ }
5440
+ if (revokedIds.has(survivor.apiKeyId)) {
5441
+ 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.`);
5442
+ }
5443
+ }
5444
+ const stampedAt = Number(stampingKey?.createdAt?.seconds);
5445
+ if (!input.force && Number.isFinite(stampedAt)) {
5446
+ const newer = targets.filter((k) => {
5447
+ const created = Number(k.createdAt?.seconds);
5448
+ return Number.isFinite(created) && created > stampedAt;
5449
+ });
5450
+ if (newer.length > 0) {
5451
+ const list = newer.map((k) => `${k.apiKeyId} ("${k.apiKeyName}")`).join(", ");
5452
+ 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.`);
5453
+ }
5454
+ }
5455
+ if (live.length === 0 && !hasPasskey) {
5456
+ const expiredNote = survivors.length > 0 ? " (the remaining key(s) have already expired)" : "";
5457
+ 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.`);
5458
+ }
5459
+ if (durableSurvivors.length === 0 && !hasPasskey && !input.force) {
5460
+ const deadlines = live.map((k) => `${k.apiKeyId} ("${k.apiKeyName}") expires ${k.expirationSeconds}s after creation`).join("; ");
5461
+ 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.`);
5462
+ }
5463
+ return { targets, survivors, durableSurvivors };
5464
+ }
5465
+ function findApiKeyByPublicKey(user, publicKey) {
5466
+ const want = publicKey.toLowerCase();
5467
+ return user.apiKeys.find((k) => k.credential?.publicKey?.toLowerCase() === want);
5468
+ }
5469
+ function normalizeUser(user) {
5470
+ return { ...user, apiKeys: user.apiKeys ?? [], authenticators: user.authenticators ?? [] };
5471
+ }
5472
+ }
5473
+ });
5474
+
3693
5475
  // ../key-management/providers/turnkey/typescript/dist/admin/wallets.js
3694
5476
  var require_wallets = __commonJS({
3695
5477
  "../key-management/providers/turnkey/typescript/dist/admin/wallets.js"(exports2) {
@@ -3742,6 +5524,7 @@ var require_policies = __commonJS({
3742
5524
  exports2.buildDenyApproveToNonAllowedSpenderTron = buildDenyApproveToNonAllowedSpenderTron;
3743
5525
  exports2.listPolicies = listPolicies;
3744
5526
  exports2.deletePolicy = deletePolicy;
5527
+ exports2.planPolicyChanges = planPolicyChanges;
3745
5528
  exports2.applyPolicies = applyPolicies;
3746
5529
  function derivePoliciesFromAllowlist(policy, chain, context) {
3747
5530
  const policies = [];
@@ -3929,26 +5712,54 @@ var require_policies = __commonJS({
3929
5712
  policyId
3930
5713
  });
3931
5714
  }
5715
+ function planPolicyChanges(existing, policies) {
5716
+ const existingByName = new Map(existing.map((p) => [p.policyName, p]));
5717
+ const drifted = [];
5718
+ for (const p of policies) {
5719
+ const prev = existingByName.get(p.policyName);
5720
+ if (!prev)
5721
+ continue;
5722
+ const matches = prev.effect === p.effect && prev.condition === p.condition && (prev.consensus ?? "") === (p.consensus ?? "");
5723
+ if (!matches)
5724
+ drifted.push({ name: p.policyName, diff: formatPolicyDiff(prev, p) });
5725
+ }
5726
+ const emittedNames = new Set(policies.map((p) => p.policyName));
5727
+ const stale = existing.filter((p) => !emittedNames.has(p.policyName));
5728
+ const seen = /* @__PURE__ */ new Set();
5729
+ const duplicateNames = [
5730
+ ...new Set(existing.filter((p) => !(seen.size === seen.add(p.policyName).size)).map((p) => p.policyName))
5731
+ ];
5732
+ return { drifted, stale, duplicateNames };
5733
+ }
3932
5734
  async function applyPolicies(client, policies, options) {
3933
5735
  const existing = await listPolicies(client, options.organizationId);
3934
5736
  const existingByName = new Map(existing.map((p) => [p.policyName, p]));
3935
5737
  const created = [];
3936
5738
  const skippedUnchanged = [];
3937
- const drifted = [];
3938
5739
  const replaced = [];
5740
+ const pruned = [];
5741
+ const { drifted, stale } = planPolicyChanges(existing, policies);
5742
+ if (stale.length > 0 && !options.prune) {
5743
+ const detail = stale.map((p) => ` - ${p.policyName} [${p.effect}] (${p.policyId})`).join("\n");
5744
+ throw new Error(`${stale.length} live polic${stale.length === 1 ? "y is" : "ies are"} absent from the emitted set:
5745
+ ${detail}
5746
+
5747
+ A retired ALLOW left live keeps granting what it always granted, so a narrower replacement does not take effect until it is gone. Re-run with --prune to delete them, or reconcile the config if they are policies this set should still emit.`);
5748
+ }
5749
+ if (drifted.length > 0 && !options.update) {
5750
+ const detail = drifted.map((d) => ` - ${d.name}:
5751
+ ${indent(d.diff, " ")}`).join("\n");
5752
+ throw new Error(`Content drift detected on ${drifted.length} polic${drifted.length === 1 ? "y" : "ies"}. Re-run with --update to delete-and-recreate, or fix the existing policy in the Turnkey console.
5753
+ ${detail}`);
5754
+ }
5755
+ const driftedNames = new Set(drifted.map((d) => d.name));
3939
5756
  for (const p of policies) {
3940
5757
  const prev = existingByName.get(p.policyName);
3941
5758
  if (prev) {
3942
- const matches = prev.effect === p.effect && prev.condition === p.condition && (prev.consensus ?? "") === (p.consensus ?? "");
3943
- if (matches) {
5759
+ if (!driftedNames.has(p.policyName)) {
3944
5760
  skippedUnchanged.push(p.policyName);
3945
5761
  continue;
3946
5762
  }
3947
- const diff = formatPolicyDiff(prev, p);
3948
- if (!options.update) {
3949
- drifted.push({ name: p.policyName, diff });
3950
- continue;
3951
- }
3952
5763
  await deletePolicy(client, prev.policyId);
3953
5764
  const newId = await createPolicyRaw(client, p);
3954
5765
  replaced.push({ name: p.policyName, oldPolicyId: prev.policyId, newPolicyId: newId });
@@ -3958,13 +5769,11 @@ var require_policies = __commonJS({
3958
5769
  const id = await createPolicyRaw(client, p);
3959
5770
  created.push(id);
3960
5771
  }
3961
- if (drifted.length > 0) {
3962
- const detail = drifted.map((d) => ` - ${d.name}:
3963
- ${indent(d.diff, " ")}`).join("\n");
3964
- throw new Error(`Content drift detected on ${drifted.length} polic${drifted.length === 1 ? "y" : "ies"}. Re-run with --update to delete-and-recreate, or fix the existing policy in the Turnkey console.
3965
- ${detail}`);
5772
+ for (const p of stale) {
5773
+ await deletePolicy(client, p.policyId);
5774
+ pruned.push({ name: p.policyName, policyId: p.policyId });
3966
5775
  }
3967
- return { created, skippedUnchanged, replaced };
5776
+ return { created, skippedUnchanged, replaced, pruned };
3968
5777
  }
3969
5778
  async function createPolicyRaw(client, p) {
3970
5779
  const result = await client.executeActivity("ACTIVITY_TYPE_CREATE_POLICY_V3", "create_policy", {
@@ -4010,6 +5819,8 @@ var require_sender_policies = __commonJS({
4010
5819
  "use strict";
4011
5820
  Object.defineProperty(exports2, "__esModule", { value: true });
4012
5821
  exports2.TRON_PERMIT2 = exports2.EVM_PERMIT2 = void 0;
5822
+ exports2.tronTip712ChainId = tronTip712ChainId;
5823
+ exports2.toTronEvmHex = toTronEvmHex;
4013
5824
  exports2.buildSenderPolicies = buildSenderPolicies;
4014
5825
  exports2.tronBase58ToEvmHex = tronBase58ToEvmHex;
4015
5826
  var node_crypto_1 = require("crypto");
@@ -4019,6 +5830,57 @@ var require_sender_policies = __commonJS({
4019
5830
  shasta: "TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp"
4020
5831
  };
4021
5832
  var APPROVE_SELECTOR = "0x095ea7b3";
5833
+ var PERMIT2_PRIMARY_TYPE = "PermitWitnessTransferFrom";
5834
+ var PERMIT2_DOMAIN_NAME = "Permit2";
5835
+ var TRON_TIP712_CHAIN_IDS = {
5836
+ mainnet: 728126428,
5837
+ shasta: 2494104990
5838
+ };
5839
+ function tronTip712ChainId(caip2) {
5840
+ const cluster = caip2.split(":")[1] ?? "";
5841
+ const id = Object.hasOwn(TRON_TIP712_CHAIN_IDS, cluster) ? TRON_TIP712_CHAIN_IDS[cluster] : void 0;
5842
+ if (id === void 0) {
5843
+ throw new Error(`Sender extras: unsupported Tron network "${caip2}". Known clusters: ${Object.keys(TRON_TIP712_CHAIN_IDS).join(", ")}.`);
5844
+ }
5845
+ return (id & 4294967295) >>> 0;
5846
+ }
5847
+ function evmNumericChainId(caip2) {
5848
+ const id = Number.parseInt(caip2.split(":")[1] ?? "", 10);
5849
+ if (!Number.isSafeInteger(id) || id <= 0) {
5850
+ throw new Error(`Sender extras: chain id "${caip2}" is not a usable eip155 CAIP-2 identifier.`);
5851
+ }
5852
+ return id;
5853
+ }
5854
+ var lower = (a) => a.toLowerCase();
5855
+ function assertEvmAddress(address, chainKey) {
5856
+ if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {
5857
+ throw new Error(`Sender extras: ${JSON.stringify(address)} on chain "${chainKey}" is not a 20-byte 0x hex address. A malformed literal matches nothing, which denies every payment on this chain.`);
5858
+ }
5859
+ return address;
5860
+ }
5861
+ function toTronEvmHex(address) {
5862
+ if (address.startsWith("T"))
5863
+ return `0x${tronBase58ToEvmHex(address)}`;
5864
+ if (/^0x[0-9a-fA-F]{40}$/.test(address))
5865
+ return lower(address);
5866
+ throw new Error(`Sender extras: Tron address ${JSON.stringify(address)} is neither a base58 (T\u2026) address nor a 20-byte 0x hex address, so its TIP-712 message form cannot be derived.`);
5867
+ }
5868
+ var quotedLower = (xs) => xs.map((x) => `'${lower(x)}'`).join(", ");
5869
+ function quotedExact(xs, chainKey) {
5870
+ for (const x of xs) {
5871
+ if (x.includes("'") || x.includes("\\")) {
5872
+ throw new Error(`Sender extras: destination ${JSON.stringify(x)} on chain "${chainKey}" contains a quote or backslash, which cannot appear in a policy condition literal.`);
5873
+ }
5874
+ if (x.length === 0 || !x.includes("@")) {
5875
+ throw new Error(`Sender extras: destination ${JSON.stringify(x)} on chain "${chainKey}" is not a composed destination (<caip19-asset>@<account>). Build it with buildEscrowDestination.`);
5876
+ }
5877
+ if (Buffer.byteLength(x, "utf8") > MAX_DESTINATION_BYTES) {
5878
+ throw new Error(`Sender extras: destination ${JSON.stringify(x)} on chain "${chainKey}" is longer than ${MAX_DESTINATION_BYTES} bytes, which the escrow rejects as DestinationTooLong, so no deposit could ever carry it.`);
5879
+ }
5880
+ }
5881
+ return xs.map((x) => `'${x}'`).join(", ");
5882
+ }
5883
+ var MAX_DESTINATION_BYTES = 256;
4022
5884
  var SOLANA_STANDARD_PROGRAMS = [
4023
5885
  "11111111111111111111111111111111",
4024
5886
  // System
@@ -4033,14 +5895,35 @@ var require_sender_policies = __commonJS({
4033
5895
  "Ed25519SigVerify111111111111111111111111111"
4034
5896
  // Ed25519 (inner signature verification)
4035
5897
  ];
5898
+ function solanaEscrowPrograms(value) {
5899
+ const raw = value === void 0 ? [] : typeof value === "string" ? [value] : value;
5900
+ const seen = /* @__PURE__ */ new Set();
5901
+ const out = [];
5902
+ for (const entry of raw) {
5903
+ const id = typeof entry === "string" ? entry.trim() : "";
5904
+ if (!id || seen.has(id))
5905
+ continue;
5906
+ seen.add(id);
5907
+ out.push(id);
5908
+ }
5909
+ return out;
5910
+ }
4036
5911
  function buildSenderPolicies(extras, chains) {
4037
5912
  const policies = [];
4038
- policies.push({
4039
- policyName: "allowSignRawPayload",
4040
- effect: "EFFECT_ALLOW",
4041
- condition: `activity.type in ['ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2', 'ACTIVITY_TYPE_SIGN_RAW_PAYLOADS'] && activity.params.hash_function in ['HASH_FUNCTION_KECCAK256', 'HASH_FUNCTION_NOT_APPLICABLE']`,
4042
- notes: "Allows Permit2 EIP-712 (secp256k1 KECCAK256) and Solana inner-signature (ed25519) signing."
4043
- });
5913
+ const permit2Evm = lower(extras.permit2 ?? exports2.EVM_PERMIT2);
5914
+ for (const chain of chains) {
5915
+ if (chain.kind !== "evm" && chain.kind !== "tron")
5916
+ continue;
5917
+ policies.push(permit2TypedDataAllow(chain, extras, permit2Evm));
5918
+ }
5919
+ if (chains.some((c) => c.kind === "solana")) {
5920
+ policies.push({
5921
+ policyName: "allowEd25519RawPayload",
5922
+ effect: "EFFECT_ALLOW",
5923
+ condition: `activity.type == 'ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2' && activity.params.encoding in ['PAYLOAD_ENCODING_HEXADECIMAL', 'PAYLOAD_ENCODING_TEXT_UTF8'] && activity.params.hash_function == 'HASH_FUNCTION_NOT_APPLICABLE'`,
5924
+ notes: "Solana deposit inner signature (ed25519 over the deposit digest). Legal on secp256k1 only with EIP712, which the API enforces, so this stays an ed25519-only path."
5925
+ });
5926
+ }
4044
5927
  for (const chain of chains) {
4045
5928
  if (chain.kind === "evm") {
4046
5929
  const evmChainId = parseInt(chain.chainId.split(":")[1], 10);
@@ -4049,7 +5932,7 @@ var require_sender_policies = __commonJS({
4049
5932
  throw new Error(`Sender extras: chain "${chain.key}" has no allowedTokens. Add at least one ERC-20 contract address the sender's wallet is permitted to approve, or remove this chain.`);
4050
5933
  }
4051
5934
  const tokenList = tokens.map((t) => `'${t}'`).join(", ");
4052
- const permit2Lower = exports2.EVM_PERMIT2.replace(/^0x/, "");
5935
+ const permit2Lower = permit2Evm.replace(/^0x/, "");
4053
5936
  policies.push({
4054
5937
  policyName: `allowApproveToPermit2 (${chain.chainId})`,
4055
5938
  effect: "EFFECT_ALLOW",
@@ -4111,10 +5994,11 @@ var require_sender_policies = __commonJS({
4111
5994
  }
4112
5995
  }
4113
5996
  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.`);
5997
+ const escrowPrograms = solanaEscrowPrograms(extras.solanaEscrowProgramId);
5998
+ if (escrowPrograms.length === 0) {
5999
+ 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
6000
  }
4117
- const allowed = [...SOLANA_STANDARD_PROGRAMS, extras.solanaEscrowProgramId];
6001
+ const allowed = [...SOLANA_STANDARD_PROGRAMS, ...escrowPrograms];
4118
6002
  const list = allowed.map((p) => `'${p}'`).join(", ");
4119
6003
  policies.push({
4120
6004
  policyName: `allowedPrograms (${chain.chainId})`,
@@ -4138,13 +6022,70 @@ var require_sender_policies = __commonJS({
4138
6022
  }
4139
6023
  }
4140
6024
  policies.push({
4141
- policyName: "denyNoOpHash",
6025
+ policyName: "denyNonTypedDataHashFunctions",
6026
+ effect: "EFFECT_DENY",
6027
+ condition: `activity.type in ['ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2', 'ACTIVITY_TYPE_SIGN_RAW_PAYLOADS'] && activity.params.hash_function in ['HASH_FUNCTION_NO_OP', 'HASH_FUNCTION_SHA256', 'HASH_FUNCTION_KECCAK256']`,
6028
+ notes: "NO_OP signs a caller-chosen digest as-is; KECCAK256 signs a caller-chosen preimage, which reproduces any EIP-712 digest and bypasses every typed-data condition."
6029
+ });
6030
+ policies.push({
6031
+ policyName: "denyAccountDelegationEncoding",
6032
+ effect: "EFFECT_DENY",
6033
+ condition: `activity.type in ['ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2', 'ACTIVITY_TYPE_SIGN_RAW_PAYLOADS'] && activity.params.encoding == 'PAYLOAD_ENCODING_EIP7702_AUTHORIZATION'`,
6034
+ notes: "One signature would delegate the sender EOA to an attacker contract."
6035
+ });
6036
+ policies.push({
6037
+ policyName: "denyBatchRawPayloads",
4142
6038
  effect: "EFFECT_DENY",
4143
- condition: `activity.type in ['ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2', 'ACTIVITY_TYPE_SIGN_RAW_PAYLOADS'] && activity.params.hash_function == 'HASH_FUNCTION_NO_OP'`,
4144
- notes: "Sender never uses NO_OP; NOT_APPLICABLE is the only allowed raw-payload hash mode."
6039
+ condition: `activity.type == 'ACTIVITY_TYPE_SIGN_RAW_PAYLOADS'`,
6040
+ notes: "Message conditions bind one payload of a batch, so a second could ride along unbound."
4145
6041
  });
4146
6042
  return policies;
4147
6043
  }
6044
+ function permit2TypedDataAllow(chain, extras, permit2Evm) {
6045
+ const escrowsRaw = extras.escrows?.[chain.key] ?? [];
6046
+ if (escrowsRaw.length === 0) {
6047
+ throw new Error(`Sender extras: chain "${chain.key}" has no escrows. Permit2 leaves the transfer recipient out of the signed struct, so the escrow named as \`spender\` IS the funds destination \u2014 without it a stolen key can authorize a pull to anywhere. Read it from payment-gw /v1/defaults?chain_id=${chain.chainId} (escrow_contract).`);
6048
+ }
6049
+ const isTron = chain.kind === "tron";
6050
+ const tronCluster = isTron ? chain.chainId.split(":")[1] ?? "" : "";
6051
+ if (isTron) {
6052
+ const expected = extras.network === "mainnet" ? "mainnet" : "shasta";
6053
+ if (tronCluster !== expected) {
6054
+ throw new Error(`Sender extras: network "${extras.network}" selects the ${expected} Permit2 deployment, but chain "${chain.key}" is "${chain.chainId}". The domain would carry one cluster's Permit2 with another's chain id, which matches no signature the runtime produces.`);
6055
+ }
6056
+ }
6057
+ const permit2 = isTron ? `0x${tronBase58ToEvmHex(exports2.TRON_PERMIT2[tronCluster])}` : permit2Evm;
6058
+ const chainIdValue = isTron ? tronTip712ChainId(chain.chainId) : evmNumericChainId(chain.chainId);
6059
+ const addr = (xs) => quotedLower(xs.map((x) => isTron ? toTronEvmHex(x) : assertEvmAddress(x, chain.key)));
6060
+ const tokens = extras.allowedTokens[chain.key] ?? [];
6061
+ if (tokens.length === 0) {
6062
+ throw new Error(`Sender extras: chain "${chain.key}" has no allowedTokens, so the typed-data allow would not bind which token the permit moves.`);
6063
+ }
6064
+ const tokenClause = ` && eth.eip_712.message['permitted']['token'] in [${addr(tokens)}]`;
6065
+ const reservers = extras.reservers?.[chain.key] ?? [];
6066
+ const releasers = extras.releasers?.[chain.key] ?? [];
6067
+ for (const [role, vals, field] of [
6068
+ ["reservers", reservers, "quote_selector"],
6069
+ ["releasers", releasers, "fulfillment_verifier.account"]
6070
+ ]) {
6071
+ if (vals.length === 0) {
6072
+ throw new Error(`Sender extras: chain "${chain.key}" has no ${role}. Either witness role can divert funds at settlement and the payer pins neither client-side, so leaving this unset is a hole this policy set is meant to close. Read it from payment-gw /v1/defaults?chain_id=${chain.chainId} (${field}).`);
6073
+ }
6074
+ }
6075
+ const reserverClause = ` && eth.eip_712.message['witness']['reserver'] in [${addr(reservers)}]`;
6076
+ const releaserClause = ` && eth.eip_712.message['witness']['releaser'] in [${addr(releasers)}]`;
6077
+ const destinations = extras.allowedDestinations?.[chain.key] ?? [];
6078
+ if (destinations.length === 0) {
6079
+ throw new Error(`Sender extras: chain "${chain.key}" has no allowedDestinations. Without them a stolen key can authorize a deposit whose payout instruction names the attacker, which is the hole this policy set exists to close. Compose each entry with buildEscrowDestination, or remove the chain.`);
6080
+ }
6081
+ const destinationClause = ` && eth.eip_712.message['witness']['destination'] in [${quotedExact(destinations, chain.key)}]`;
6082
+ return {
6083
+ policyName: `allowPermit2DepositTypedData (${chain.chainId})`,
6084
+ effect: "EFFECT_ALLOW",
6085
+ condition: `activity.type == 'ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2' && activity.params.encoding == 'PAYLOAD_ENCODING_EIP712' && activity.params.hash_function == 'HASH_FUNCTION_NOT_APPLICABLE' && eth.eip_712.primary_type == '${PERMIT2_PRIMARY_TYPE}' && eth.eip_712.domain.name == '${PERMIT2_DOMAIN_NAME}' && eth.eip_712.domain.verifying_contract == '${permit2}' && eth.eip_712.domain.chain_id == ${chainIdValue} && eth.eip_712.message['spender'] in [${addr(escrowsRaw)}]` + tokenClause + reserverClause + releaserClause + destinationClause,
6086
+ notes: "The sender's only fund-moving signature: a Permit2 deposit authorization into an allowlisted escrow, for an allowlisted token, committing to an allowlisted destination."
6087
+ };
6088
+ }
4148
6089
  function tronBase58ToEvmHex(b58) {
4149
6090
  const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
4150
6091
  let bn = 0n;
@@ -4229,7 +6170,7 @@ var require_extras_policies = __commonJS({
4229
6170
  var sender_policies_1 = require_sender_policies();
4230
6171
  var SPL_TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
4231
6172
  var ASSOCIATED_TOKEN_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
4232
- var EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
6173
+ var EVM_ADDRESS2 = /^0x[0-9a-fA-F]{40}$/;
4233
6174
  var TRON_ADDRESS = /^T[1-9A-HJ-NP-Za-km-z]{33}$/;
4234
6175
  var ALLOWED_EXTRAS_KEYS = [
4235
6176
  "allowedErc20Recipients",
@@ -4249,7 +6190,7 @@ var require_extras_policies = __commonJS({
4249
6190
  }
4250
6191
  }
4251
6192
  if (obj.allowedErc20Recipients != null) {
4252
- validateAddressMap(obj.allowedErc20Recipients, "allowedErc20Recipients", EVM_ADDRESS, source);
6193
+ validateAddressMap(obj.allowedErc20Recipients, "allowedErc20Recipients", EVM_ADDRESS2, source);
4253
6194
  }
4254
6195
  if (obj.allowedTrc20Recipients != null) {
4255
6196
  validateAddressMap(obj.allowedTrc20Recipients, "allowedTrc20Recipients", TRON_ADDRESS, source);
@@ -4448,7 +6389,7 @@ var require_admin = __commonJS({
4448
6389
  "../key-management/providers/turnkey/typescript/dist/admin/index.js"(exports2) {
4449
6390
  "use strict";
4450
6391
  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;
6392
+ exports2.validateExtras = exports2.buildExtrasPolicies = exports2.tronTip712ChainId = exports2.tronBase58ToEvmHex = exports2.toTronEvmHex = exports2.TRON_PERMIT2 = exports2.EVM_PERMIT2 = exports2.buildSenderPolicies = exports2.planPolicyChanges = 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
6393
  var sub_organizations_1 = require_sub_organizations();
4453
6394
  Object.defineProperty(exports2, "createSubOrganization", { enumerable: true, get: function() {
4454
6395
  return sub_organizations_1.createSubOrganization;
@@ -4465,6 +6406,53 @@ var require_admin = __commonJS({
4465
6406
  Object.defineProperty(exports2, "provisionAgentUser", { enumerable: true, get: function() {
4466
6407
  return users_1.provisionAgentUser;
4467
6408
  } });
6409
+ var activities_1 = require_activities();
6410
+ Object.defineProperty(exports2, "approveActivity", { enumerable: true, get: function() {
6411
+ return activities_1.approveActivity;
6412
+ } });
6413
+ Object.defineProperty(exports2, "approvedVoterIds", { enumerable: true, get: function() {
6414
+ return activities_1.approvedVoterIds;
6415
+ } });
6416
+ Object.defineProperty(exports2, "getActivity", { enumerable: true, get: function() {
6417
+ return activities_1.getActivity;
6418
+ } });
6419
+ Object.defineProperty(exports2, "getRootQuorum", { enumerable: true, get: function() {
6420
+ return activities_1.getRootQuorum;
6421
+ } });
6422
+ Object.defineProperty(exports2, "listPendingActivities", { enumerable: true, get: function() {
6423
+ return activities_1.listPendingActivities;
6424
+ } });
6425
+ var api_keys_1 = require_api_keys();
6426
+ Object.defineProperty(exports2, "MAX_API_KEYS_PER_USER", { enumerable: true, get: function() {
6427
+ return api_keys_1.MAX_API_KEYS_PER_USER;
6428
+ } });
6429
+ Object.defineProperty(exports2, "UnsafeRevocationError", { enumerable: true, get: function() {
6430
+ return api_keys_1.UnsafeRevocationError;
6431
+ } });
6432
+ Object.defineProperty(exports2, "addApiKeys", { enumerable: true, get: function() {
6433
+ return api_keys_1.addApiKeys;
6434
+ } });
6435
+ Object.defineProperty(exports2, "deleteApiKeys", { enumerable: true, get: function() {
6436
+ return api_keys_1.deleteApiKeys;
6437
+ } });
6438
+ Object.defineProperty(exports2, "findApiKeyByPublicKey", { enumerable: true, get: function() {
6439
+ return api_keys_1.findApiKeyByPublicKey;
6440
+ } });
6441
+ Object.defineProperty(exports2, "getUser", { enumerable: true, get: function() {
6442
+ return api_keys_1.getUser;
6443
+ } });
6444
+ Object.defineProperty(exports2, "isDurableApiKey", { enumerable: true, get: function() {
6445
+ return api_keys_1.isDurableApiKey;
6446
+ } });
6447
+ Object.defineProperty(exports2, "isExpiredApiKey", { enumerable: true, get: function() {
6448
+ return api_keys_1.isExpiredApiKey;
6449
+ } });
6450
+ Object.defineProperty(exports2, "listUsers", { enumerable: true, get: function() {
6451
+ return api_keys_1.listUsers;
6452
+ } });
6453
+ Object.defineProperty(exports2, "planRevocation", { enumerable: true, get: function() {
6454
+ return api_keys_1.planRevocation;
6455
+ } });
4468
6456
  var wallets_1 = require_wallets();
4469
6457
  Object.defineProperty(exports2, "createWalletWithChainAccounts", { enumerable: true, get: function() {
4470
6458
  return wallets_1.createWalletWithChainAccounts;
@@ -4491,6 +6479,9 @@ var require_admin = __commonJS({
4491
6479
  Object.defineProperty(exports2, "listPolicies", { enumerable: true, get: function() {
4492
6480
  return policies_1.listPolicies;
4493
6481
  } });
6482
+ Object.defineProperty(exports2, "planPolicyChanges", { enumerable: true, get: function() {
6483
+ return policies_1.planPolicyChanges;
6484
+ } });
4494
6485
  var sender_policies_1 = require_sender_policies();
4495
6486
  Object.defineProperty(exports2, "buildSenderPolicies", { enumerable: true, get: function() {
4496
6487
  return sender_policies_1.buildSenderPolicies;
@@ -4501,9 +6492,15 @@ var require_admin = __commonJS({
4501
6492
  Object.defineProperty(exports2, "TRON_PERMIT2", { enumerable: true, get: function() {
4502
6493
  return sender_policies_1.TRON_PERMIT2;
4503
6494
  } });
6495
+ Object.defineProperty(exports2, "toTronEvmHex", { enumerable: true, get: function() {
6496
+ return sender_policies_1.toTronEvmHex;
6497
+ } });
4504
6498
  Object.defineProperty(exports2, "tronBase58ToEvmHex", { enumerable: true, get: function() {
4505
6499
  return sender_policies_1.tronBase58ToEvmHex;
4506
6500
  } });
6501
+ Object.defineProperty(exports2, "tronTip712ChainId", { enumerable: true, get: function() {
6502
+ return sender_policies_1.tronTip712ChainId;
6503
+ } });
4507
6504
  var extras_policies_1 = require_extras_policies();
4508
6505
  Object.defineProperty(exports2, "buildExtrasPolicies", { enumerable: true, get: function() {
4509
6506
  return extras_policies_1.buildExtrasPolicies;
@@ -4515,7 +6512,7 @@ var require_admin = __commonJS({
4515
6512
  });
4516
6513
 
4517
6514
  // ../key-management/providers/turnkey/typescript/dist/index.js
4518
- var require_dist6 = __commonJS({
6515
+ var require_dist8 = __commonJS({
4519
6516
  "../key-management/providers/turnkey/typescript/dist/index.js"(exports2) {
4520
6517
  "use strict";
4521
6518
  var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
@@ -4570,18 +6567,18 @@ var require_dist6 = __commonJS({
4570
6567
  Object.defineProperty(exports2, "noopMeter", { enumerable: true, get: function() {
4571
6568
  return meter_1.noopMeter;
4572
6569
  } });
4573
- var evm_1 = require_evm2();
6570
+ var evm_1 = require_evm3();
4574
6571
  Object.defineProperty(exports2, "TurnkeyEvmSigner", { enumerable: true, get: function() {
4575
6572
  return evm_1.TurnkeyEvmSigner;
4576
6573
  } });
4577
- var solana_1 = require_solana2();
6574
+ var solana_1 = require_solana3();
4578
6575
  Object.defineProperty(exports2, "TurnkeySolanaSigner", { enumerable: true, get: function() {
4579
6576
  return solana_1.TurnkeySolanaSigner;
4580
6577
  } });
4581
6578
  Object.defineProperty(exports2, "encodePayload", { enumerable: true, get: function() {
4582
6579
  return solana_1.encodePayload;
4583
6580
  } });
4584
- var tron_1 = require_tron2();
6581
+ var tron_1 = require_tron3();
4585
6582
  Object.defineProperty(exports2, "TurnkeyTronSigner", { enumerable: true, get: function() {
4586
6583
  return tron_1.TurnkeyTronSigner;
4587
6584
  } });
@@ -4634,11 +6631,12 @@ async function resolveSenderAddresses(cfg) {
4634
6631
  return accounts.map((a) => ({ address: a.address, addressFormat: a.addressFormat }));
4635
6632
  }
4636
6633
  async function signWithTurnkeyClient(client, chainPrefix, cfg, message, messagePrehash) {
6634
+ const pinnedAddress = requirePinnedSender(cfg.pinnedAddress);
4637
6635
  const deps = {
4638
6636
  walletId: cfg.walletId,
4639
6637
  log: cfg.logger ?? import_turnkey_signer.noopLogger,
4640
6638
  discoveryTimeoutMs: cfg.discoveryTimeoutMs ?? DEFAULTS.discoveryTimeoutMs,
4641
- ...cfg.pinnedAddress ? { pinnedAddress: cfg.pinnedAddress } : {}
6639
+ ...pinnedAddress ? { pinnedAddress } : {}
4642
6640
  };
4643
6641
  switch (chainPrefix) {
4644
6642
  case "eip155": {
@@ -4648,7 +6646,11 @@ async function signWithTurnkeyClient(client, chainPrefix, cfg, message, messageP
4648
6646
  return { signature: await signer.signTypedData(domain, types, typedMessage) };
4649
6647
  }
4650
6648
  case "tron": {
4651
- const { domain, types, message: typedMessage } = parsePrehash(messagePrehash, "Tron", message);
6649
+ const {
6650
+ domain,
6651
+ types,
6652
+ message: typedMessage
6653
+ } = parsePrehash(messagePrehash, "Tron", message);
4652
6654
  const signer = new import_turnkey_signer.TurnkeyTronSigner(client, deps);
4653
6655
  await signer.initialize();
4654
6656
  return { signature: await signer.signTypedData(domain, types, typedMessage) };
@@ -4688,23 +6690,29 @@ function parsePrehash(messagePrehash, label, advertisedDigest) {
4688
6690
  }
4689
6691
  const isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
4690
6692
  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`);
6693
+ throw new Error(
6694
+ `Turnkey ${label} signing: message_prehash must be a JSON object with domain, types and message`
6695
+ );
4692
6696
  }
4693
6697
  const { EIP712Domain: _derived, ...structTypes } = parsed.types;
4694
- const prehashDigest = import_ethers5.TypedDataEncoder.hash(parsed.domain, structTypes, parsed.message);
6698
+ const domain = parsed.domain;
6699
+ const types = structTypes;
6700
+ const message = parsed.message;
6701
+ const prehashDigest = import_ethers6.TypedDataEncoder.hash(domain, types, message);
4695
6702
  if (prehashDigest.toLowerCase() !== advertisedDigest.toLowerCase()) {
4696
6703
  throw new Error(
4697
6704
  `Turnkey ${label} signing: message_prehash implies digest ${prehashDigest} but message is ${advertisedDigest}`
4698
6705
  );
4699
6706
  }
4700
- return { domain: parsed.domain, types: structTypes, message: parsed.message };
6707
+ return { domain, types, message };
4701
6708
  }
4702
- var import_turnkey_signer, import_ethers5, TURNKEY_API_URL, DEFAULTS;
6709
+ var import_turnkey_signer, import_ethers6, TURNKEY_API_URL, DEFAULTS;
4703
6710
  var init_turnkey_impl = __esm({
4704
6711
  "src/signers/turnkey-impl.ts"() {
4705
6712
  "use strict";
4706
- import_turnkey_signer = __toESM(require_dist6());
4707
- import_ethers5 = require("ethers");
6713
+ import_turnkey_signer = __toESM(require_dist8());
6714
+ import_ethers6 = require("ethers");
6715
+ init_pinned_address();
4708
6716
  TURNKEY_API_URL = "https://api.turnkey.com";
4709
6717
  DEFAULTS = {
4710
6718
  concurrencyLimit: 10,
@@ -4716,6 +6724,7 @@ var init_turnkey_impl = __esm({
4716
6724
 
4717
6725
  // src/cli/send-payment.ts
4718
6726
  var import_commander = require("commander");
6727
+ var import_fs = require("fs");
4719
6728
 
4720
6729
  // src/generated/core/OpenAPI.ts
4721
6730
  var Interceptors = class {
@@ -5192,7 +7201,7 @@ payment.
5192
7201
  `,
5193
7202
  413: "Payment request too large to process",
5194
7203
  500: "Internal server error",
5195
- 503: "A dependency is temporarily unavailable"
7204
+ 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
7205
  }
5197
7206
  });
5198
7207
  }
@@ -5277,6 +7286,9 @@ payment.
5277
7286
  *
5278
7287
  * The response includes everything needed to sign and submit a payment, except the signature itself.
5279
7288
  *
7289
+ * Not available on every gateway or every source chain; where it is not, this
7290
+ * returns `501`. Sign the returned request and submit it to `POST /v1/payments`.
7291
+ *
5280
7292
  * @param data The data for the request.
5281
7293
  * @param data.requestBody
5282
7294
  * @returns PreparePaymentResponse Payment request prepared successfully
@@ -5323,11 +7335,30 @@ var AuthorizationsService = class {
5323
7335
  body: data.requestBody,
5324
7336
  mediaType: "application/json",
5325
7337
  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)"
7338
+ 400: `The request was rejected before authorization was attempted, so no
7339
+ authorization outcome exists.
7340
+ `,
7341
+ 401: `The counterparty's proof was rejected (\`PROOF_INVALID\` or \`PROOF_STALE\`).
7342
+ This is an authorization outcome, so the body is an \`AuthorizationResult\`
7343
+ with \`status: error\`.
7344
+ `,
7345
+ 404: `Counterparty not found (no registration for the resolved DID). An
7346
+ authorization outcome, so the body is an \`AuthorizationResult\` with
7347
+ \`status: error\` and \`error_code: COUNTERPARTY_NOT_FOUND\`.
7348
+ `,
7349
+ 500: `Either shape, depending on where the failure happened. A failure before
7350
+ authorization was attempted returns \`ErrorResponse\`. A failure carrying an
7351
+ authorization outcome returns \`AuthorizationResult\` with \`status: error\`.
7352
+ `,
7353
+ 502: `Counterparty webhook error (HTTP error or connection failure). An
7354
+ authorization outcome, so the body is an \`AuthorizationResult\` with
7355
+ \`status: error\` and \`error_code: WEBHOOK_ERROR\` or
7356
+ \`WEBHOOK_CONNECTION_ERROR\`.
7357
+ `,
7358
+ 504: `Authorization timed out (the counterparty did not respond). An
7359
+ authorization outcome, so the body is an \`AuthorizationResult\` with
7360
+ \`status: timeout\`.
7361
+ `
5331
7362
  }
5332
7363
  });
5333
7364
  }
@@ -5354,6 +7385,31 @@ var QuoteRequestsService = class {
5354
7385
  * Collection continues server-side until the quote deadline regardless of the HTTP
5355
7386
  * connection, so quotes remain retrievable via the status endpoint in either mode.
5356
7387
  *
7388
+ * **Idempotency.** `request_id` is the idempotency key, scoped to the source account
7389
+ * and originator — the same key, and the same contract, as POST /v1/payments.
7390
+ * Submitting the same `request_id` again returns the ORIGINAL batch instead of opening
7391
+ * a second one, so a client whose request timed out or failed in transit can safely
7392
+ * re-submit and recover its `quote_request_id`.
7393
+ *
7394
+ * Because a re-submission must be admissible on its own, some fields legitimately
7395
+ * differ between attempts and are excluded from the comparison: `quote_deadline` and
7396
+ * `fulfillment_deadline` (both must be in the future, so a later attempt has to move
7397
+ * them) and the `proof` that covers them. An expired `quote_deadline` on a
7398
+ * re-submission is NOT an error — the request is resolved onto the batch that already
7399
+ * exists rather than used to open one. There is no `sender_auth` to re-sign here: this
7400
+ * endpoint rejects it, because the spend authorization belongs to the award call.
7401
+ *
7402
+ * The collection window belongs to the BATCH, not to the request. Asking again with a
7403
+ * later `quote_deadline` does not extend a window already open; `quote_deadline` in the
7404
+ * response is the batch's own, and `status` says whether collection is still running.
7405
+ *
7406
+ * What must NOT differ is the corridor's economics — source account and asset,
7407
+ * destination accounts and assets, `fulfillment_amount`, and `max_source_amount`.
7408
+ * Re-using one `request_id` for a genuinely different corridor is a client bug that
7409
+ * would otherwise be silently collapsed onto the first batch, returning quotes for a
7410
+ * corridor that was never requested. It is rejected with `409` and
7411
+ * `IDEMPOTENCY_TERMS_MISMATCH`. Use a distinct `request_id` per quote-request.
7412
+ *
5357
7413
  * @param data The data for the request.
5358
7414
  * @param data.requestBody
5359
7415
  * @param data.wait Return a handle immediately (`false`, default) or hold the connection for collected quotes (`true`).
@@ -5373,8 +7429,19 @@ var QuoteRequestsService = class {
5373
7429
  body: data.requestBody,
5374
7430
  mediaType: "application/json",
5375
7431
  errors: {
5376
- 400: "Invalid request",
5377
- 500: "Internal server error"
7432
+ 400: `Invalid request. \`QUOTE_DEADLINE_NOT_FUTURE\` is the one worth planning for: a NEW
7433
+ quote-request whose \`quote_deadline\` has already passed is refused, because there is
7434
+ no window left to collect quotes in. It does not apply to a re-submission \u2014 an
7435
+ already-used \`request_id\` resolves onto the batch that exists and its expired
7436
+ deadline is ignored, which is what makes a retry recoverable.
7437
+ `,
7438
+ 409: `The \`request_id\` has already been used for a quote-request with different
7439
+ economics (\`IDEMPOTENCY_TERMS_MISMATCH\`). Re-submitting one \`request_id\` is how a
7440
+ retry is made safe, so it must identify one batch; use a distinct \`request_id\`
7441
+ per quote-request.
7442
+ `,
7443
+ 500: "Internal server error",
7444
+ 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
7445
  }
5379
7446
  });
5380
7447
  }
@@ -5457,6 +7524,43 @@ var QuoteRequestsService = class {
5457
7524
  });
5458
7525
  }
5459
7526
  };
7527
+ var ChainDefaultsService = class {
7528
+ constructor(httpRequest) {
7529
+ this.httpRequest = httpRequest;
7530
+ }
7531
+ /**
7532
+ * Get chain defaults
7533
+ * The addresses needed to build a payment on a chain: the escrow, the accounts named
7534
+ * in the deposit authorization, and the fulfillment verifier. Fetch these rather than
7535
+ * hardcoding them - they change when a chain's contracts are redeployed.
7536
+ *
7537
+ * With `chain_id`, returns that chain. Without it, or with an empty value, returns
7538
+ * every chain the gateway serves, keyed by CAIP-2 chain id.
7539
+ *
7540
+ * A chain that is not fully configured is still returned when asked for by
7541
+ * `chain_id`, with the missing address empty, but is left out of the full listing.
7542
+ * Treat an empty address as a chain you cannot pay on.
7543
+ *
7544
+ * @param data The data for the request.
7545
+ * @param data.chainId CAIP-2 chain identifier. Omit it, or send it empty, to receive every chain the gateway serves, keyed by chain id.
7546
+ * @returns GetDefaultsResult Chain defaults. A single object when `chain_id` was supplied, otherwise an object keyed by CAIP-2 chain id.
7547
+ * @throws ApiError
7548
+ */
7549
+ getDefaults(data = {}) {
7550
+ return this.httpRequest.request({
7551
+ method: "GET",
7552
+ url: "/v1/defaults",
7553
+ query: {
7554
+ chain_id: data.chainId
7555
+ },
7556
+ errors: {
7557
+ 400: "The `chain_id` is not a valid CAIP-2 chain identifier",
7558
+ 404: "The requested chain is not served by this gateway, or - when `chain_id` was omitted - no chain could be resolved at all",
7559
+ 503: "A dependency is temporarily unavailable"
7560
+ }
7561
+ });
7562
+ }
7563
+ };
5460
7564
  var HealthService = class {
5461
7565
  constructor(httpRequest) {
5462
7566
  this.httpRequest = httpRequest;
@@ -5494,19 +7598,140 @@ var PaymentGatewayClient = class {
5494
7598
  }
5495
7599
  });
5496
7600
  this.authorizations = new AuthorizationsService(this.request);
7601
+ this.chainDefaults = new ChainDefaultsService(this.request);
5497
7602
  this.health = new HealthService(this.request);
5498
7603
  this.payments = new PaymentsService(this.request);
5499
7604
  this.quoteRequests = new QuoteRequestsService(this.request);
5500
7605
  }
5501
7606
  };
5502
7607
 
7608
+ // src/timeout-http-request.ts
7609
+ var import_axios2 = __toESM(require("axios"));
7610
+
7611
+ // src/errors.ts
7612
+ var GatewayTimeoutError = class extends Error {
7613
+ constructor(baseUrl, timeoutMs) {
7614
+ super(
7615
+ `Gateway at ${baseUrl || "(same origin)"} did not respond within ${formatSeconds(timeoutMs)}`
7616
+ );
7617
+ this.baseUrl = baseUrl;
7618
+ this.timeoutMs = timeoutMs;
7619
+ this.name = "GatewayTimeoutError";
7620
+ }
7621
+ };
7622
+ function formatSeconds(ms) {
7623
+ const seconds = ms / 1e3;
7624
+ return `${Number.isInteger(seconds) ? seconds : seconds.toFixed(1)}s`;
7625
+ }
7626
+ function isGatewayTimeoutError(err) {
7627
+ return err instanceof GatewayTimeoutError;
7628
+ }
7629
+ function isApiError(err) {
7630
+ return err instanceof ApiError;
7631
+ }
7632
+
7633
+ // src/request-timeout.ts
7634
+ var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
7635
+ var DEFAULT_SYNC_WAIT_TIMEOUT_MS = 12e4;
7636
+ var SYNC_HOLD_PATHS = ["/v1/payments", "/v1/payments/awards"];
7637
+ function pathOf(url) {
7638
+ if (!url) return "";
7639
+ const path = url.split("?")[0];
7640
+ const scheme = path.indexOf("://");
7641
+ if (scheme === -1) return path;
7642
+ const host = path.indexOf("/", scheme + 3);
7643
+ return host === -1 ? "" : path.slice(host);
7644
+ }
7645
+ function hasWaitTrueQuery(url) {
7646
+ const query = url?.indexOf("?") ?? -1;
7647
+ if (query === -1) return false;
7648
+ return new URLSearchParams(url.slice(query + 1)).get("wait") === "true";
7649
+ }
7650
+ function isSyncWaitRequest({ method, url, wait }) {
7651
+ if (wait === true || wait === "true" || hasWaitTrueQuery(url)) return true;
7652
+ if (method?.toUpperCase() !== "POST") return false;
7653
+ const path = pathOf(url);
7654
+ return SYNC_HOLD_PATHS.some((held) => path === held || path.endsWith(held));
7655
+ }
7656
+ function ordinaryTimeout(timeouts = {}) {
7657
+ return timeouts.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
7658
+ }
7659
+ function timeoutForRequest(request2, timeouts = {}) {
7660
+ return isSyncWaitRequest(request2) ? timeouts.syncWaitTimeoutMs ?? DEFAULT_SYNC_WAIT_TIMEOUT_MS : ordinaryTimeout(timeouts);
7661
+ }
7662
+ function applyRequestTimeout(timeouts = {}) {
7663
+ return (config2) => ({
7664
+ ...config2,
7665
+ timeout: config2.timeout ?? timeoutForRequest({ method: config2.method, url: config2.url }, timeouts)
7666
+ });
7667
+ }
7668
+ function isAxiosTimeout(error) {
7669
+ const failure = error;
7670
+ if (!failure) return false;
7671
+ if (failure.code === "ECONNABORTED" || failure.code === "ETIMEDOUT") return true;
7672
+ return failure.code === "ERR_BAD_RESPONSE" && /stream has been aborted/i.test(failure.message ?? "");
7673
+ }
7674
+ function dropPartialResponseOnTimeout(error) {
7675
+ if (isAxiosTimeout(error) && error !== null && typeof error === "object" && "response" in error) {
7676
+ delete error.response;
7677
+ }
7678
+ return error;
7679
+ }
7680
+ function translateTimeout(error, baseUrl, fallbackTimeoutMs) {
7681
+ if (!isAxiosTimeout(error)) return error;
7682
+ const configured = error.config?.timeout;
7683
+ return new GatewayTimeoutError(baseUrl, configured ?? fallbackTimeoutMs);
7684
+ }
7685
+
7686
+ // src/timeout-http-request.ts
7687
+ var timeoutAxios = import_axios2.default.create();
7688
+ timeoutAxios.interceptors.response.use(
7689
+ void 0,
7690
+ (error) => Promise.reject(dropPartialResponseOnTimeout(error))
7691
+ );
7692
+ function withRequestTimeout(config2, timeouts) {
7693
+ const request2 = new Interceptors();
7694
+ for (const fn of config2?.interceptors?.request?._fns ?? []) request2.use(fn);
7695
+ request2.use(applyRequestTimeout(timeouts));
7696
+ return {
7697
+ interceptors: { request: request2, response: config2?.interceptors?.response ?? new Interceptors() }
7698
+ };
7699
+ }
7700
+ var TimeoutHttpRequest = class extends AxiosHttpRequest {
7701
+ constructor(config2, timeouts = {}) {
7702
+ super(config2);
7703
+ this.timeouts = timeouts;
7704
+ }
7705
+ request(options) {
7706
+ return new CancelablePromise((resolve2, reject, onCancel) => {
7707
+ const pending = request(this.config, options, timeoutAxios);
7708
+ onCancel(() => pending.cancel());
7709
+ pending.then(resolve2, (error) => {
7710
+ const request2 = { method: options.method, url: options.url, wait: options.query?.wait };
7711
+ reject(
7712
+ translateTimeout(error, this.config.BASE, timeoutForRequest(request2, this.timeouts))
7713
+ );
7714
+ });
7715
+ });
7716
+ }
7717
+ };
7718
+ function timeoutHttpRequest(timeouts) {
7719
+ return class extends TimeoutHttpRequest {
7720
+ constructor(config2) {
7721
+ super(config2, timeouts);
7722
+ }
7723
+ };
7724
+ }
7725
+
5503
7726
  // src/chain-adapters/evm.ts
5504
7727
  var import_ethers = require("ethers");
5505
7728
 
5506
7729
  // src/chain-adapters/types.ts
5507
7730
  function assertKeyMatchesSender(matches, sender, derived) {
5508
7731
  if (!matches) {
5509
- throw new Error(`The private key derives ${derived}, which does not match the sender address ${sender}`);
7732
+ throw new Error(
7733
+ `The private key derives ${derived}, which does not match the sender address ${sender}`
7734
+ );
5510
7735
  }
5511
7736
  }
5512
7737
 
@@ -5558,10 +7783,9 @@ var tronAdapter = {
5558
7783
  throw new Error("Invalid private key");
5559
7784
  }
5560
7785
  },
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.
7786
+ // Tron addresses are the same secp256k1-derived 20 bytes as EVM. The derived
7787
+ // address is already canonical 20-byte hex, so only the sender side — which
7788
+ // arrives in whichever spelling the caller chose — needs normalizing.
5565
7789
  verifyAddressMatchesKey(privateKey, address) {
5566
7790
  const key = privateKey.startsWith("0x") ? privateKey : "0x" + privateKey;
5567
7791
  const derived = new import_ethers2.ethers.Wallet(key).address;
@@ -5600,22 +7824,133 @@ function secretKeyFromPrivate(privateKey) {
5600
7824
  if (decoded.length === 32) {
5601
7825
  return import_tweetnacl.default.sign.keyPair.fromSeed(decoded).secretKey;
5602
7826
  }
5603
- throw new Error(`Invalid Solana private key length: expected 32 or 64 bytes, got ${decoded.length}`);
7827
+ throw new Error(
7828
+ `Invalid Solana private key length: expected 32 or 64 bytes, got ${decoded.length}`
7829
+ );
5604
7830
  }
5605
7831
 
5606
7832
  // src/chain-adapters/index.ts
5607
7833
  var adapters = {
5608
- "eip155": evmAdapter,
5609
- "tron": tronAdapter,
5610
- "solana": solanaAdapter
7834
+ eip155: evmAdapter,
7835
+ tron: tronAdapter,
7836
+ solana: solanaAdapter
5611
7837
  };
5612
7838
  function getChainAdapter(sourceChainId) {
5613
- const prefix = sourceChainId.split(":")[0];
7839
+ const prefix = sourceChainId.split(":")[0]?.toLowerCase() ?? "";
5614
7840
  const adapter = adapters[prefix];
5615
7841
  if (!adapter) throw new Error(`Unsupported source chain: ${sourceChainId}`);
5616
7842
  return adapter;
5617
7843
  }
5618
7844
 
7845
+ // src/asset-identifier.ts
7846
+ var import_ethers3 = require("ethers");
7847
+ var SHAPE_EXAMPLE = "eip155:421614/erc20:0x...";
7848
+ var NAMESPACE = /^[a-z0-9]+$/;
7849
+ var CHAIN_REFERENCE = /^[a-zA-Z0-9_-]+$/;
7850
+ var ASSET_NAMESPACE = /^[a-z0-9-]{3,8}$/;
7851
+ var ASSET_REFERENCE = /^[-.%a-zA-Z0-9]{1,128}$/;
7852
+ var TOKEN_ID = /^[-.%a-zA-Z0-9]{1,78}$/;
7853
+ var EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
7854
+ var EIP155_REFERENCE = /^[0-9]+$/;
7855
+ var HEX_REFERENCE = /^0[xX][0-9a-fA-F]{1,16}$/;
7856
+ var MAX_ECHO = 120;
7857
+ var MAX_REFERENCE_ECHO = 32;
7858
+ function parseAssetIdentifier(value) {
7859
+ if (typeof value !== "string" || value === "") {
7860
+ throw new Error(shapeError(value));
7861
+ }
7862
+ const firstSlash = value.indexOf("/");
7863
+ if (firstSlash === -1) {
7864
+ throw new Error(shapeError(value));
7865
+ }
7866
+ const chainSegments = value.slice(0, firstSlash).split(":");
7867
+ if (chainSegments.length !== 2) {
7868
+ throw new Error(shapeError(value));
7869
+ }
7870
+ const namespace = chainSegments[0].toLowerCase();
7871
+ const reference = namespace === "tron" ? chainSegments[1].toLowerCase() : chainSegments[1];
7872
+ if (!NAMESPACE.test(namespace) || !CHAIN_REFERENCE.test(reference)) {
7873
+ throw new Error(shapeError(value));
7874
+ }
7875
+ if (namespace === "eip155" && !EIP155_REFERENCE.test(reference)) {
7876
+ throw new Error(eip155ReferenceError(reference, value));
7877
+ }
7878
+ const assetPart = value.slice(firstSlash + 1);
7879
+ const separator = assetPart.indexOf(":");
7880
+ if (separator === -1) {
7881
+ throw new Error(tokenAddressError(value));
7882
+ }
7883
+ const assetNamespace = assetPart.slice(0, separator).toLowerCase();
7884
+ const rest = assetPart.slice(separator + 1);
7885
+ const referenceSlash = rest.indexOf("/");
7886
+ const tokenAddress = referenceSlash === -1 ? rest : rest.slice(0, referenceSlash);
7887
+ const tokenId = referenceSlash === -1 ? void 0 : rest.slice(referenceSlash + 1);
7888
+ if (!ASSET_NAMESPACE.test(assetNamespace)) {
7889
+ throw new Error(tokenAddressError(value));
7890
+ }
7891
+ if (assetNamespace === "slip44") {
7892
+ throw new Error(nativeAssetError(value));
7893
+ }
7894
+ if (!ASSET_REFERENCE.test(tokenAddress)) {
7895
+ throw new Error(tokenAddressError(value));
7896
+ }
7897
+ if (tokenId !== void 0 && !TOKEN_ID.test(tokenId)) {
7898
+ throw new Error(tokenAddressError(value));
7899
+ }
7900
+ assertTokenAddress(namespace, tokenAddress, value);
7901
+ const chainId = `${namespace}:${reference}`;
7902
+ return {
7903
+ chainId,
7904
+ namespace,
7905
+ reference,
7906
+ assetNamespace,
7907
+ tokenAddress,
7908
+ ...tokenId === void 0 ? {} : { tokenId },
7909
+ normalized: `${chainId}/${assetNamespace}:${tokenAddress}${tokenId === void 0 ? "" : `/${tokenId}`}`
7910
+ };
7911
+ }
7912
+ function assetChainId(value) {
7913
+ return parseAssetIdentifier(value).chainId;
7914
+ }
7915
+ function echo(value, limit = MAX_ECHO) {
7916
+ const shown = typeof value === "string" ? value : String(value);
7917
+ return shown.length > limit ? `${shown.slice(0, limit)}\u2026` : shown;
7918
+ }
7919
+ function shapeError(value) {
7920
+ return `Invalid asset identifier "${echo(value)}": expected CAIP-19 "<chain>/<type>:<address>", e.g. ${SHAPE_EXAMPLE}`;
7921
+ }
7922
+ function tokenAddressError(value) {
7923
+ return `Invalid token address in asset "${echo(value)}".`;
7924
+ }
7925
+ function eip155ReferenceError(reference, value) {
7926
+ const prefix = `Invalid eip155 chain id "${echo(reference, MAX_REFERENCE_ECHO)}" in asset "${echo(value)}"`;
7927
+ if (HEX_REFERENCE.test(reference)) {
7928
+ return `${prefix}: use the decimal chain id (${BigInt(reference)}), not hex.`;
7929
+ }
7930
+ return `${prefix}: an eip155 chain id is decimal, e.g. 421614.`;
7931
+ }
7932
+ function nativeAssetError(value) {
7933
+ return `Asset "${echo(value)}" is a native asset (slip44) and has no contract to deposit. Use the wrapped token's erc20 identifier.`;
7934
+ }
7935
+ function assertTokenAddress(namespace, tokenAddress, value) {
7936
+ if (namespace !== "eip155") return;
7937
+ if (!EVM_ADDRESS.test(tokenAddress)) {
7938
+ throw new Error(tokenAddressError(value));
7939
+ }
7940
+ const body = tokenAddress.slice(2);
7941
+ if (body === body.toLowerCase() || body === body.toUpperCase()) return;
7942
+ try {
7943
+ (0, import_ethers3.getAddress)(tokenAddress);
7944
+ } catch {
7945
+ throw new Error(
7946
+ `Token address "${tokenAddress}" has an invalid checksum. Fix the capitalization or use the all-lowercase form.`
7947
+ );
7948
+ }
7949
+ }
7950
+
7951
+ // src/index.ts
7952
+ var import_chain_address = __toESM(require_dist2());
7953
+
5619
7954
  // src/chain-adapters/solana-clock.ts
5620
7955
  var DEFAULT_SOLANA_RPC_URLS = {
5621
7956
  "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp": "https://api.mainnet-beta.solana.com",
@@ -5684,19 +8019,84 @@ async function resolveSolanaIssuedAt(opts) {
5684
8019
  }
5685
8020
 
5686
8021
  // src/index.ts
5687
- var import_payment_request_sender_auth2 = __toESM(require_dist4());
8022
+ var import_payment_request_sender_auth2 = __toESM(require_dist5());
8023
+ var import_chain_address2 = __toESM(require_dist2());
8024
+
8025
+ // src/payment-tracking.ts
8026
+ function isTerminalStatus(status) {
8027
+ return status === "completed" || status === "failed";
8028
+ }
8029
+ var DEFAULT_WAIT_SECONDS = 60;
8030
+ var DEFAULT_WAIT_BUDGET_MS = DEFAULT_WAIT_SECONDS * 1e3;
8031
+ var DEFAULT_POLL_INTERVAL_MS = 2e3;
8032
+ async function waitForTerminalStatus(params) {
8033
+ const {
8034
+ fetchStatus,
8035
+ budgetMs = DEFAULT_WAIT_BUDGET_MS,
8036
+ intervalMs = DEFAULT_POLL_INTERVAL_MS,
8037
+ now = () => Date.now(),
8038
+ signal,
8039
+ // Closes over `signal` so the default wakes on abort instead of sleeping out the interval.
8040
+ sleep = (ms) => defaultSleep(ms, signal),
8041
+ onError
8042
+ } = params;
8043
+ const deadline = now() + budgetMs;
8044
+ let snapshot;
8045
+ let errorCount = 0;
8046
+ while (now() < deadline) {
8047
+ if (signal?.aborted) {
8048
+ return { snapshot, timedOut: true, aborted: true, errorCount };
8049
+ }
8050
+ const remaining = deadline - now();
8051
+ await sleep(Math.min(intervalMs, remaining));
8052
+ if (signal?.aborted) {
8053
+ return { snapshot, timedOut: true, aborted: true, errorCount };
8054
+ }
8055
+ try {
8056
+ snapshot = await fetchStatus();
8057
+ } catch (error) {
8058
+ errorCount += 1;
8059
+ onError?.(error);
8060
+ continue;
8061
+ }
8062
+ if (isTerminalStatus(snapshot.status)) {
8063
+ return { snapshot, timedOut: false, aborted: false, errorCount };
8064
+ }
8065
+ }
8066
+ return { snapshot, timedOut: true, aborted: false, errorCount };
8067
+ }
8068
+ function defaultSleep(ms, signal) {
8069
+ if (!signal) {
8070
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
8071
+ }
8072
+ return new Promise((resolve2) => {
8073
+ const done = () => {
8074
+ clearTimeout(timer);
8075
+ signal.removeEventListener("abort", done);
8076
+ resolve2();
8077
+ };
8078
+ const timer = setTimeout(done, ms);
8079
+ signal.addEventListener("abort", done, { once: true });
8080
+ });
8081
+ }
8082
+
8083
+ // src/index.ts
8084
+ var import_payment_request_token_approval = __toESM(require_dist6());
5688
8085
 
5689
8086
  // src/sender_auth_schemes/evm_permit2.ts
5690
- var import_ethers3 = require("ethers");
5691
- var import_evm_escrow_encoding = __toESM(require_dist2());
8087
+ var import_ethers4 = require("ethers");
8088
+ var import_evm_escrow_encoding = __toESM(require_dist3());
5692
8089
 
5693
8090
  // src/sender_auth_schemes/solana.ts
5694
- var import_ethers4 = require("ethers");
8091
+ var import_ethers5 = require("ethers");
5695
8092
  var import_bs582 = __toESM(require("bs58"));
5696
- var import_solana_escrow_encoding = __toESM(require_dist3());
8093
+ var import_solana_escrow_encoding = __toESM(require_dist4());
8094
+
8095
+ // src/signers/index.ts
8096
+ init_pinned_address();
5697
8097
 
5698
8098
  // src/signers/raw.ts
5699
- var import_payment_request_sender_auth = __toESM(require_dist4());
8099
+ var import_payment_request_sender_auth = __toESM(require_dist5());
5700
8100
  var RawSenderSigner = class {
5701
8101
  constructor(network, privateKey) {
5702
8102
  const adapter = getChainAdapter(network);
@@ -5709,6 +8109,7 @@ var RawSenderSigner = class {
5709
8109
  };
5710
8110
 
5711
8111
  // src/signers/turnkey.ts
8112
+ init_pinned_address();
5712
8113
  async function loadImpl() {
5713
8114
  return Promise.resolve().then(() => (init_turnkey_impl(), turnkey_impl_exports));
5714
8115
  }
@@ -5717,6 +8118,7 @@ var TurnkeySenderSigner = class {
5717
8118
  this.chainPrefix = chainPrefix;
5718
8119
  this.cfg = cfg;
5719
8120
  this.loader = loader;
8121
+ this.pinnedAddress = requirePinnedSender(cfg.pinnedAddress);
5720
8122
  }
5721
8123
  async sign(signedMessage) {
5722
8124
  const impl = await this.loader();
@@ -5727,7 +8129,7 @@ var TurnkeySenderSigner = class {
5727
8129
  walletId: this.cfg.walletId,
5728
8130
  apiPublicKey: this.cfg.apiPublicKey,
5729
8131
  apiPrivateKey: this.cfg.apiPrivateKey,
5730
- ...this.cfg.pinnedAddress ? { pinnedAddress: this.cfg.pinnedAddress } : {},
8132
+ ...this.pinnedAddress ? { pinnedAddress: this.pinnedAddress } : {},
5731
8133
  ...this.cfg.logger ? { logger: this.cfg.logger } : {},
5732
8134
  ...this.cfg.meter ? { meter: this.cfg.meter } : {}
5733
8135
  },
@@ -5739,24 +8141,30 @@ var TurnkeySenderSigner = class {
5739
8141
 
5740
8142
  // src/signers/index.ts
5741
8143
  function createSenderSigner(sourceChainId, opts) {
5742
- const chainPrefix = sourceChainId.split(":")[0];
8144
+ const chainPrefix = sourceChainId.split(":")[0]?.toLowerCase() ?? "";
5743
8145
  if (opts.provider === "turnkey") {
5744
8146
  return new TurnkeySenderSigner(chainPrefix, opts);
5745
8147
  }
8148
+ const pinnedAddress = requirePinnedSender(opts.pinnedAddress);
5746
8149
  const adapter = getChainAdapter(sourceChainId);
5747
8150
  const privateKey = adapter.formatPrivateKey(opts.privateKey);
5748
8151
  adapter.validatePrivateKey?.(opts.privateKey);
5749
- if (opts.pinnedAddress) {
8152
+ if (pinnedAddress) {
5750
8153
  if (!adapter.verifyAddressMatchesKey) {
5751
- throw new Error(`pinnedAddress was provided but the ${sourceChainId} adapter cannot verify the key derives it`);
8154
+ throw new Error(
8155
+ `pinnedAddress was provided but the ${sourceChainId} adapter cannot verify the key derives it`
8156
+ );
5752
8157
  }
5753
- adapter.verifyAddressMatchesKey(privateKey, opts.pinnedAddress);
8158
+ adapter.verifyAddressMatchesKey(privateKey, pinnedAddress);
5754
8159
  }
5755
8160
  return new RawSenderSigner(sourceChainId, opts.privateKey);
5756
8161
  }
5757
8162
 
5758
8163
  // src/index.ts
5759
8164
  var PAYMENT_REQUEST_VERSION = "1.0";
8165
+ function assertPayableAccount(assetIdentifier, account) {
8166
+ (0, import_chain_address.validate)(assetChainId(assetIdentifier), account);
8167
+ }
5760
8168
  var defaultGateway = "https://payment-gw.production-testnet.atum.xyz";
5761
8169
  var OpenAPI2 = { ...OpenAPI, BASE: defaultGateway };
5762
8170
  var DEFAULT_QUOTE_DEADLINE_SECONDS = 5;
@@ -5773,10 +8181,14 @@ function resolveDeadlines(params, defaultQuoteSeconds) {
5773
8181
  const quoteDeadlineSeconds = params.quoteDeadlineSeconds ?? defaultQuoteSeconds;
5774
8182
  const fulfillmentDeadlineSeconds = params.fulfillmentDeadlineSeconds ?? DEFAULT_FULFILLMENT_DEADLINE_SECONDS;
5775
8183
  if (!Number.isFinite(quoteDeadlineSeconds) || !Number.isFinite(fulfillmentDeadlineSeconds)) {
5776
- throw new Error("quoteDeadlineSeconds and fulfillmentDeadlineSeconds must be finite numbers of seconds.");
8184
+ throw new Error(
8185
+ "quoteDeadlineSeconds and fulfillmentDeadlineSeconds must be finite numbers of seconds."
8186
+ );
5777
8187
  }
5778
8188
  if (quoteDeadlineSeconds <= 0 || fulfillmentDeadlineSeconds <= 0) {
5779
- throw new Error("quoteDeadlineSeconds and fulfillmentDeadlineSeconds must be positive numbers of seconds.");
8189
+ throw new Error(
8190
+ "quoteDeadlineSeconds and fulfillmentDeadlineSeconds must be positive numbers of seconds."
8191
+ );
5780
8192
  }
5781
8193
  if (quoteDeadlineSeconds >= fulfillmentDeadlineSeconds) {
5782
8194
  throw new Error(
@@ -5789,18 +8201,67 @@ function resolveDeadlines(params, defaultQuoteSeconds) {
5789
8201
  fulfillment_deadline: new Date(now + fulfillmentDeadlineSeconds * 1e3).toISOString()
5790
8202
  };
5791
8203
  }
8204
+ function defaultsErrorDetail(error) {
8205
+ if (!isApiError(error)) {
8206
+ return error instanceof Error ? error.message : String(error);
8207
+ }
8208
+ const body = error.body;
8209
+ const parts = [];
8210
+ if (typeof body?.code === "string" && body.code.trim() !== "") parts.push(body.code);
8211
+ if (typeof body?.message === "string" && body.message.trim() !== "") parts.push(body.message);
8212
+ const requestId = typeof body?.request_id === "string" && body.request_id.trim() !== "" ? body.request_id : "";
8213
+ if (parts.length > 0) {
8214
+ return `${parts.join(": ")}${requestId === "" ? "" : ` (request_id=${requestId})`}`;
8215
+ }
8216
+ return error.statusText || `HTTP ${error.status}`;
8217
+ }
8218
+ function singleChainOf(response, chainId) {
8219
+ if (typeof response !== "object" || response === null) {
8220
+ throw new Error(
8221
+ `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.`
8222
+ );
8223
+ }
8224
+ const single = response;
8225
+ if (typeof single.chain_id !== "string") {
8226
+ throw new Error(
8227
+ `Failed to fetch defaults for chain ${chainId}: the gateway answered with defaults for every chain rather than the one requested`
8228
+ );
8229
+ }
8230
+ if (single.chain_id.toLowerCase() !== chainId.toLowerCase()) {
8231
+ throw new Error(
8232
+ `Failed to fetch defaults for chain ${chainId}: the gateway answered with defaults for ` + single.chain_id
8233
+ );
8234
+ }
8235
+ return single;
8236
+ }
5792
8237
  async function assemblePaymentRequest(params) {
5793
- const sourceChainId = params.sourceAsset.split("/")[0];
5794
- const namespace = sourceChainId.split(":")[0];
8238
+ const source = parseAssetIdentifier(params.sourceAsset);
8239
+ const destination = parseAssetIdentifier(params.destinationAsset);
8240
+ const { chainId: sourceChainId, namespace } = source;
5795
8241
  const adapter = getChainAdapter(sourceChainId);
5796
8242
  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
8243
  const auth = await (0, import_payment_request_sender_auth2.getChainAdapter)(sourceChainId).buildAuthMessage({
5798
- sourceAsset: params.sourceAsset,
8244
+ // Canonicalized: the Tron adapter resolves its Permit2 address by exact chain-id key, so an
8245
+ // uppercase namespace would miss the lookup and fail inside the SDK.
8246
+ sourceAsset: source.normalized,
5799
8247
  depositor: params.depositor,
5800
8248
  // The gateway pins the signed deposit amount to max_source_amount (the cap).
5801
8249
  maxSourceAmount: params.maxSourceAmount,
5802
8250
  requestId: params.requestId,
5803
8251
  sourceDefaults: params.sourceDefaults,
8252
+ // The payee the deposit commits to. Passed as CAIP components, not a composed string:
8253
+ // the adapter composes it through the shared buildEscrowDestination so this producer
8254
+ // and the release signer cannot disagree by a byte. These are the SAME two values that
8255
+ // become paymentRequest.destination[0] below, so the signed commitment and the request
8256
+ // body cannot describe different payees.
8257
+ // Canonicalized for the same reason `sourceAsset` is, and additionally because the claim
8258
+ // three lines up has to be TRUE: destination[0] below carries `destination.normalized`, so
8259
+ // passing the raw string here would sign a commitment over different bytes than the request
8260
+ // body names whenever a caller supplies a non-canonical namespace (e.g. "EIP155:42220").
8261
+ // `normalized` lowercases only the namespaces and the asset namespace — the chain reference
8262
+ // and token address keep their case, so base58 (Solana genesis reference, SPL mint) survives.
8263
+ destinationAsset: destination.normalized,
8264
+ destinationAccount: params.destinationAccount,
5804
8265
  deadline: params.deadline,
5805
8266
  nonce,
5806
8267
  ...namespace === "solana" ? {
@@ -5816,13 +8277,15 @@ async function assemblePaymentRequest(params) {
5816
8277
  version: params.version ?? PAYMENT_REQUEST_VERSION,
5817
8278
  request_id: params.requestId,
5818
8279
  source: {
5819
- asset_identifier: params.sourceAsset,
8280
+ asset_identifier: source.normalized,
5820
8281
  account: params.depositor
5821
8282
  },
5822
- destination: [{
5823
- asset_identifier: params.destinationAsset,
5824
- account: params.destinationAccount
5825
- }],
8283
+ destination: [
8284
+ {
8285
+ asset_identifier: destination.normalized,
8286
+ account: params.destinationAccount
8287
+ }
8288
+ ],
5826
8289
  fulfillment_amount: params.fulfillmentAmount,
5827
8290
  max_source_amount: params.maxSourceAmount,
5828
8291
  quote_deadline: params.quoteDeadline,
@@ -5837,43 +8300,58 @@ async function assemblePaymentRequest(params) {
5837
8300
  ...params.settlerRequirements ? { settler_requirements: params.settlerRequirements } : {},
5838
8301
  sender_auth: {
5839
8302
  message_scheme: auth.messageScheme,
5840
- signed_messages: [{
5841
- message: auth.messageHash,
5842
- message_prehash: auth.messagePrehash,
5843
- signature: ""
5844
- }]
8303
+ signed_messages: [
8304
+ {
8305
+ message: auth.messageHash,
8306
+ message_prehash: auth.messagePrehash,
8307
+ signature: ""
8308
+ }
8309
+ ]
5845
8310
  }
5846
8311
  };
5847
8312
  }
5848
8313
  var PaymentGatewayClient2 = class extends PaymentGatewayClient {
5849
- constructor(config2, HttpRequest = AxiosHttpRequest) {
8314
+ constructor(config2, HttpRequest) {
5850
8315
  const envBase = (typeof process !== "undefined" ? process.env.GATEWAY_URL : void 0)?.trim();
5851
8316
  const base = config2?.BASE ?? (envBase || defaultGateway);
5852
- super({ ...config2, BASE: base }, HttpRequest);
5853
- this.baseUrl = base;
8317
+ const timeouts = {
8318
+ timeoutMs: config2?.timeoutMs,
8319
+ syncWaitTimeoutMs: config2?.syncWaitTimeoutMs
8320
+ };
8321
+ super(
8322
+ { ...config2, BASE: base, ...withRequestTimeout(config2, timeouts) },
8323
+ HttpRequest ?? timeoutHttpRequest(timeouts)
8324
+ );
5854
8325
  }
5855
8326
  /**
5856
8327
  * Fetches chain defaults from the payment gateway.
5857
- *
8328
+ *
8329
+ * Goes through the generated typed client, so the request shares the payment calls'
8330
+ * transport: one base URL, one timeout policy, and `/v1/defaults` is described by the
8331
+ * OpenAPI contract rather than assembled by hand here.
8332
+ *
5858
8333
  * @param chainId The CAIP-2 chain identifier (e.g., "eip155:42161")
5859
8334
  * @returns The chain defaults including escrow, quote selector, and fulfillment verifier
5860
8335
  */
5861
8336
  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();
8337
+ if (chainId.trim() === "") {
8338
+ throw new Error(
8339
+ 'payment-gateway-client: fetchChainDefaults requires a CAIP-2 chain id, for example "eip155:8453"'
8340
+ );
8341
+ }
8342
+ let response;
8343
+ try {
8344
+ response = await this.chainDefaults.getDefaults({ chainId });
8345
+ } catch (error) {
8346
+ if (isGatewayTimeoutError(error)) throw error;
8347
+ throw new Error(
8348
+ `Failed to fetch defaults for chain ${chainId}: ${defaultsErrorDetail(error)}`,
8349
+ {
8350
+ cause: error
5869
8351
  }
5870
- } catch {
5871
- }
5872
- const error = new Error(`Failed to fetch defaults for chain ${chainId}: ${response.statusText}`);
5873
- error.availableDefaults = availableDefaults;
5874
- throw error;
8352
+ );
5875
8353
  }
5876
- const data = await response.json();
8354
+ const data = singleChainOf(response, chainId);
5877
8355
  if (!data.escrow_contract) {
5878
8356
  throw new Error("defaults missing escrow_contract");
5879
8357
  }
@@ -5892,23 +8370,34 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
5892
8370
  if (!data.fulfillment_verifier.endpoint) {
5893
8371
  throw new Error("defaults missing fulfillment_verifier.endpoint");
5894
8372
  }
8373
+ if (typeof data.permit2_contract === "string" && data.permit2_contract.trim() === "") {
8374
+ throw new Error("defaults returned an empty permit2_contract");
8375
+ }
5895
8376
  return {
5896
8377
  escrowContract: data.escrow_contract,
5897
8378
  quoteSelector: data.quote_selector,
5898
8379
  fulfillmentVerifierAccount: data.fulfillment_verifier.account,
5899
8380
  fulfillmentVerifierEndpoint: data.fulfillment_verifier.endpoint,
5900
8381
  fulfillmentProxy: data.fulfillment_proxy,
5901
- permit2Contract: data.permit2_contract,
8382
+ // `?? undefined` normalises a JSON null at the boundary. The declared type is
8383
+ // `string | undefined`, and a consumer testing `!== undefined` or `in` - both
8384
+ // reasonable against that type - would otherwise build an EIP-712 domain around a
8385
+ // null verifyingContract.
8386
+ permit2Contract: data.permit2_contract ?? void 0,
8387
+ // Which deposit witness the escrow on this chain pins. Absent means the
8388
+ // four-member witness — see ChainDefaults.depositWitnessVersion for why
8389
+ // absence is the permissive default. EVM/Tron only; Solana uses the svm_* fields below.
8390
+ depositWitnessVersion: data.deposit_witness_version ?? void 0,
5902
8391
  // V3 Solana escrow domain separation. Present only for Solana
5903
8392
  // 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
8393
+ svmSignatureClusterId: data.svm_signature_cluster_id ?? void 0,
8394
+ svmSignatureDomainVersion: data.svm_signature_domain_version ?? void 0
5906
8395
  };
5907
8396
  }
5908
8397
  /**
5909
8398
  * Prepares a payment request with defaults, ready for signing.
5910
8399
  *
5911
- * By default this resolves the corridor addresses from the gateway `/defaults`
8400
+ * By default this resolves the corridor addresses from the gateway `/v1/defaults`
5912
8401
  * endpoint. It reaches the gateway only for what the caller has NOT already
5913
8402
  * supplied via `resolvedDefaults`: supply `resolvedDefaults.source` to skip the
5914
8403
  * source-chain fetch and `resolvedDefaults.destination` to skip the destination
@@ -5938,10 +8427,14 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
5938
8427
  * @returns A complete PaymentRequest object without the signature
5939
8428
  */
5940
8429
  async preparePaymentRequest(params) {
8430
+ assertPayableAccount(params.destinationAsset, params.destinationAccount);
5941
8431
  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];
8432
+ const { quote_deadline, fulfillment_deadline } = resolveDeadlines(
8433
+ { ...params, now: () => now },
8434
+ DEFAULT_PAYMENT_QUOTE_DEADLINE_SECONDS
8435
+ );
8436
+ const sourceChainId = assetChainId(params.sourceAsset);
8437
+ const destChainId = assetChainId(params.destinationAsset);
5945
8438
  const [sourceDefaults, fulfillmentProxy] = await Promise.all([
5946
8439
  params.resolvedDefaults?.source ?? this.fetchChainDefaults(sourceChainId),
5947
8440
  params.resolvedDefaults?.destination?.fulfillmentProxy ?? this.fetchChainDefaults(destChainId).then((d) => d.fulfillmentProxy)
@@ -6011,7 +8504,7 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
6011
8504
  * defaults and populates the SAME contract fields (`escrow_contract_address`,
6012
8505
  * `quote_selector`, `fulfillment_verifier`, `fulfillment_proxy`). These are not
6013
8506
  * optional in practice: the gateway requires `fulfillment_verifier` to build the
6014
- * QuoteRequested event it broadcasts to settlers, so the quote-request body
8507
+ * request event it broadcasts to settlers, so the quote-request body
6015
8508
  * must carry the identical contract fields the payment flow does. The ONLY
6016
8509
  * field this drops relative to `preparePaymentRequest` is `sender_auth`, which
6017
8510
  * is supplied at award time (quote-time is unauthenticated — no signing, no
@@ -6021,26 +8514,38 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
6021
8514
  * @returns A complete `CreateQuoteRequest` body (no signature step needed)
6022
8515
  */
6023
8516
  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];
8517
+ assertPayableAccount(params.destinationAsset, params.destinationAccount);
8518
+ if (!params.requestId) {
8519
+ throw new Error(
8520
+ "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"
8521
+ );
8522
+ }
8523
+ const { quote_deadline, fulfillment_deadline } = resolveDeadlines(
8524
+ params,
8525
+ DEFAULT_QUOTE_DEADLINE_SECONDS
8526
+ );
8527
+ const source = parseAssetIdentifier(params.sourceAsset);
8528
+ const destination = parseAssetIdentifier(params.destinationAsset);
8529
+ const sourceChainId = source.chainId;
8530
+ const destChainId = destination.chainId;
6027
8531
  const [sourceDefaults, destDefaults] = await Promise.all([
6028
8532
  this.fetchChainDefaults(sourceChainId),
6029
8533
  this.fetchChainDefaults(destChainId)
6030
8534
  ]);
6031
8535
  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
8536
  return {
6034
8537
  version: PAYMENT_REQUEST_VERSION,
6035
- request_id: requestId,
8538
+ request_id: params.requestId,
6036
8539
  source: {
6037
- asset_identifier: params.sourceAsset,
8540
+ asset_identifier: source.normalized,
6038
8541
  account: params.depositor
6039
8542
  },
6040
- destination: [{
6041
- asset_identifier: params.destinationAsset,
6042
- account: params.destinationAccount
6043
- }],
8543
+ destination: [
8544
+ {
8545
+ asset_identifier: destination.normalized,
8546
+ account: params.destinationAccount
8547
+ }
8548
+ ],
6044
8549
  fulfillment_amount: params.fulfillmentAmount,
6045
8550
  max_source_amount: params.maxSourceAmount ?? defaultMaxSourceAmount(params.fulfillmentAmount),
6046
8551
  // Required + originator-supplied: the gateway injects no default and never
@@ -6065,27 +8570,43 @@ var PaymentGatewayClient2 = class extends PaymentGatewayClient {
6065
8570
  }
6066
8571
  };
6067
8572
 
8573
+ // src/cli/cli-input-error.ts
8574
+ var CliInputError = class extends Error {
8575
+ constructor(message) {
8576
+ super(message);
8577
+ this.name = "CliInputError";
8578
+ }
8579
+ };
8580
+
6068
8581
  // src/cli/parse-seconds.ts
6069
8582
  function parseSeconds(optionName) {
6070
8583
  return (value) => {
6071
8584
  if (!/^-?\d+$/.test(value.trim())) {
6072
- throw new Error(`${optionName} must be an integer number of seconds`);
8585
+ throw new CliInputError(`${optionName} must be an integer number of seconds`);
6073
8586
  }
6074
8587
  return Number(value);
6075
8588
  };
6076
8589
  }
6077
8590
 
8591
+ // src/cli/run-cli.ts
8592
+ function runCli(program2, ...parseArgs) {
8593
+ try {
8594
+ program2.parse(...parseArgs);
8595
+ } catch (error) {
8596
+ if (!(error instanceof CliInputError)) throw error;
8597
+ console.error("\n\u274C Error:", error.message);
8598
+ process.exit(1);
8599
+ }
8600
+ }
8601
+
6078
8602
  // src/version.ts
6079
- var PACKAGE_VERSION = true ? "2.2.0" : "0.0.0-dev";
8603
+ var PACKAGE_VERSION = true ? "3.0.1" : "0.0.0-dev";
6080
8604
 
6081
8605
  // src/cli/payment-outcome.ts
6082
8606
  var EXIT_COMPLETED = 0;
6083
8607
  var EXIT_ERROR = 1;
6084
8608
  var EXIT_PENDING = 2;
6085
8609
  var EXIT_TERMINAL_FAILURE = 3;
6086
- function isTerminalStatus(status) {
6087
- return status === "completed" || status === "failed" || status === "cancelled";
6088
- }
6089
8610
  function describePaymentOutcome(input) {
6090
8611
  const { status, paymentId, requestId, idempotentReplay, errorCode } = input;
6091
8612
  const payment = paymentId ? `payment ${paymentId}` : "the payment";
@@ -6096,7 +8617,7 @@ function describePaymentOutcome(input) {
6096
8617
  summary: `completed: ${payment} settled.${replay}`
6097
8618
  };
6098
8619
  }
6099
- if (status === "failed" || status === "cancelled") {
8620
+ if (status === "failed") {
6100
8621
  const reason = errorCode ? ` (${errorCode})` : "";
6101
8622
  return {
6102
8623
  exitCode: EXIT_TERMINAL_FAILURE,
@@ -6110,43 +8631,98 @@ function describePaymentOutcome(input) {
6110
8631
  };
6111
8632
  }
6112
8633
 
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) {
8634
+ // src/cli/submit-and-report.ts
8635
+ async function submitAndReport(params) {
6117
8636
  const {
6118
- fetchStatus,
6119
- budgetMs,
6120
- intervalMs = DEFAULT_POLL_INTERVAL_MS,
6121
- now = () => Date.now(),
6122
- sleep = defaultSleep,
6123
- onError
8637
+ client,
8638
+ paymentRequest,
8639
+ requestId,
8640
+ wait = false,
8641
+ waitSeconds = DEFAULT_WAIT_SECONDS,
8642
+ pollIntervalMs,
8643
+ writeOut = (line) => console.log(line),
8644
+ writeErr = (line) => console.error(line)
6124
8645
  } = 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 };
8646
+ const response = await client.payments.submitPayment({ requestBody: paymentRequest });
8647
+ let reported = response;
8648
+ if (wait && response.payment_id && !isTerminalStatus(response.status)) {
8649
+ writeErr(`waiting up to ${waitSeconds}s for ${response.payment_id} to settle...`);
8650
+ const paymentId = response.payment_id;
8651
+ const waited = await waitForTerminalStatus({
8652
+ budgetMs: waitSeconds * 1e3,
8653
+ intervalMs: pollIntervalMs,
8654
+ fetchStatus: () => client.payments.getPaymentStatus({ paymentId }),
8655
+ // A blip mid-settlement is the worst moment to give up, so report and keep checking.
8656
+ onError: (err) => writeErr(
8657
+ `status check failed, still waiting: ${err instanceof Error ? err.message : String(err)}`
8658
+ )
8659
+ });
8660
+ if (waited.snapshot) {
8661
+ reported = { ...reported, ...waited.snapshot };
8662
+ }
8663
+ if (waited.timedOut) {
8664
+ writeErr(`still not settled after ${waitSeconds}s \u2014 reporting it as pending.`);
8665
+ }
8666
+ }
8667
+ writeOut(JSON.stringify(reported, null, 2));
8668
+ const outcome = {
8669
+ status: reported.status,
8670
+ paymentId: reported.payment_id,
8671
+ requestId,
8672
+ idempotentReplay: reported.idempotent_replay,
8673
+ // Present when the gateway has recorded a reason — which includes the case where this
8674
+ // submission was deduplicated onto a payment that had already failed.
8675
+ errorCode: reported.error?.code
8676
+ };
8677
+ const { exitCode, summary } = describePaymentOutcome(outcome);
8678
+ writeErr(summary);
8679
+ return exitCode;
6143
8680
  }
6144
- function defaultSleep(ms) {
6145
- return new Promise((resolve2) => setTimeout(resolve2, ms));
8681
+
8682
+ // src/cli/option-groups.ts
8683
+ var BUILD_ONLY_OPTIONS = [
8684
+ "--request-id",
8685
+ "--request-id-prefix",
8686
+ "--quote-deadline-seconds",
8687
+ "--fulfillment-deadline-seconds",
8688
+ "--whitelistSettler",
8689
+ "--provider",
8690
+ "--solana-rpc-url"
8691
+ ];
8692
+ function attributeNameOf(flag) {
8693
+ return flag.replace(/^--/, "").replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
6146
8694
  }
6147
8695
 
6148
8696
  // src/cli/send-payment.ts
8697
+ init_pinned_address();
8698
+
8699
+ // src/cli/prompt-private-key.ts
6149
8700
  var readline = __toESM(require("readline"));
8701
+ async function promptPrivateKey() {
8702
+ const rl = readline.createInterface({
8703
+ input: process.stdin,
8704
+ output: process.stdout,
8705
+ terminal: true
8706
+ });
8707
+ return new Promise((resolve2) => {
8708
+ process.stderr.write("Enter private key (input hidden): ");
8709
+ const originalWrite = process.stdout.write;
8710
+ process.stdout.write = function(chunk, _encoding, _callback) {
8711
+ if (chunk === "\n" || chunk === "\r\n") {
8712
+ return originalWrite.apply(process.stdout, arguments);
8713
+ }
8714
+ return true;
8715
+ };
8716
+ rl.question("", (answer) => {
8717
+ process.stdout.write = originalWrite;
8718
+ process.stderr.write("\n");
8719
+ rl.close();
8720
+ resolve2(answer);
8721
+ });
8722
+ rl._writeToOutput = function() {
8723
+ };
8724
+ });
8725
+ }
6150
8726
 
6151
8727
  // src/cli/load-env.ts
6152
8728
  var import_dotenv = require("dotenv");
@@ -6175,7 +8751,64 @@ function loadTurnkeyConfigFromEnv() {
6175
8751
  };
6176
8752
  }
6177
8753
  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", `
8754
+ program.name("send-payment").description(
8755
+ [
8756
+ "Send a cross-chain payment through Atum Payment Gateway.",
8757
+ "",
8758
+ " Normally this prepares, signs and submits in one step. To have the payment",
8759
+ " approved before it is sent, split it in two: --prepare-only writes the signed",
8760
+ " request out, --submit sends one back in.",
8761
+ "",
8762
+ " PREREQUISITE: paying from an EVM or Tron chain needs a one-off ERC-20/TRC-20",
8763
+ " approval of the source token for the Permit2 contract, made by the sender",
8764
+ " before this runs. Without it the payment is built and signed correctly and",
8765
+ " still fails to settle. Run `approve-permit2` to grant it; contract addresses",
8766
+ " are at the end of this help."
8767
+ ].join("\n")
8768
+ ).usage(
8769
+ "[options] <sender> <amount> <sourceAsset> <receiver> <destinationAsset>\n or: send-payment --submit <file> [options]"
8770
+ ).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(
8771
+ "--gateway <url>",
8772
+ "Payment gateway URL (overrides GATEWAY_URL env; default: production-testnet)"
8773
+ ).option(
8774
+ "--request-id <id>",
8775
+ "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)."
8776
+ ).option("--request-id-prefix <prefix>", "Custom request ID prefix (default: pmt-gw-cli)").option(
8777
+ "--quote-deadline-seconds <n>",
8778
+ `Quote collection window in seconds (default: ${DEFAULT_PAYMENT_QUOTE_DEADLINE_SECONDS})`,
8779
+ parseSeconds("--quote-deadline-seconds")
8780
+ ).option(
8781
+ "--fulfillment-deadline-seconds <n>",
8782
+ `Settlement horizon in seconds (default: ${DEFAULT_FULFILLMENT_DEADLINE_SECONDS})`,
8783
+ parseSeconds("--fulfillment-deadline-seconds")
8784
+ ).option(
8785
+ "--whitelistSettler <did>",
8786
+ "Settler DID to whitelist (can be specified multiple times)",
8787
+ collect,
8788
+ []
8789
+ ).option("--provider <raw|turnkey>", "Sender signing provider", "raw").option(
8790
+ "--wait",
8791
+ "After submitting, keep checking the payment until it settles or fails instead of reporting it as still pending"
8792
+ ).option(
8793
+ "--wait-seconds <n>",
8794
+ `How long --wait keeps checking (default: ${DEFAULT_WAIT_SECONDS}). A convenience bound only \u2014 giving up does not affect the payment`,
8795
+ parseSeconds("--wait-seconds")
8796
+ ).option(
8797
+ "--solana-rpc-url <url>",
8798
+ "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)"
8799
+ ).addOption(
8800
+ new import_commander.Option(
8801
+ "--prepare-only",
8802
+ "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"
8803
+ ).conflicts(["wait", "waitSeconds"])
8804
+ ).addOption(
8805
+ new import_commander.Option(
8806
+ "--submit <file>",
8807
+ "Submit a request built earlier by --prepare-only, instead of building one. Signs nothing and needs no private key. Use - to read stdin"
8808
+ ).conflicts(["prepareOnly", ...BUILD_ONLY_OPTIONS.map(attributeNameOf)])
8809
+ ).addHelpText(
8810
+ "after",
8811
+ `
6179
8812
  CAIP-19 Examples:
6180
8813
  EVM ERC20: eip155:42161/erc20:0xaf88d065e77c8cC2239327C5EDb3A432268e5831
6181
8814
  Tron TRC20: tron:shasta/trc20:TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs
@@ -6195,6 +8828,34 @@ Output:
6195
8828
  With --wait the JSON is printed once the wait ends, reporting the payment's state
6196
8829
  as of the last check rather than as of the submit.
6197
8830
 
8831
+ --prepare-only:
8832
+ Builds and signs the request, prints it to stdout, and stops. Nothing is
8833
+ submitted and no payment exists. The document printed is exactly what would
8834
+ have been POSTed, so you can inspect it, have it reviewed, then send it with
8835
+ \`send-payment --submit <file>\` (or pipe it:
8836
+ \`send-payment --prepare-only ... | send-payment --submit -\`).
8837
+
8838
+ It still contacts the gateway, which is where the corridor addresses come from,
8839
+ so it is not an offline mode.
8840
+
8841
+ The file it writes is a signed authorization, not a draft. Anyone holding it can
8842
+ send it with --submit, which needs no key. Treat it like a signed cheque: keep it
8843
+ where you would keep a credential, and delete it once the payment is sent or the
8844
+ request is abandoned.
8845
+
8846
+ Re-preparing with the same --request-id targets the same payment: the deposit nonce
8847
+ comes from the id, so it cannot pay twice. It does not reproduce the same bytes \u2014
8848
+ the deadlines are stamped from the clock and the signature covers them.
8849
+
8850
+ Intending to submit later? The document is only submittable while its quote
8851
+ window is open, and the default is ${DEFAULT_PAYMENT_QUOTE_DEADLINE_SECONDS}s, so widen it with
8852
+ --quote-deadline-seconds to leave room to read it.
8853
+
8854
+ Widen it by tens of seconds, not minutes. The window is also the auction: the
8855
+ gateway waits it out before choosing a settler, and settler quotes expire on
8856
+ their own, so an over-long window ends in QUOTES_EXPIRED \u2014 which is terminal,
8857
+ and a fresh attempt then needs a NEW --request-id.
8858
+
6198
8859
  Exit codes:
6199
8860
  0 completed \u2014 settled
6200
8861
  2 pending \u2014 accepted, no result yet; follow it with payment-status <payment_id>,
@@ -6204,20 +8865,55 @@ Exit codes:
6204
8865
 
6205
8866
  So \`send-payment ... && <next step>\` runs the next step only for a settled payment.
6206
8867
 
8868
+ The table above describes a SUBMITTED payment, so it does not apply to
8869
+ --prepare-only: there, 0 means the request was built and signed, not that anything
8870
+ was paid. Do not chain a payment-conditional step off a --prepare-only run.
8871
+
6207
8872
  Exit 1 means unknown, not "nothing happened" \u2014 a request that timed out may still
6208
8873
  have been accepted, and you may have no payment_id to look up. Re-run with the same
6209
8874
  --request-id, which resolves to the payment if one was created and creates it if not.
6210
8875
 
6211
8876
  After submission, you can check payment status at eg http://PAYMENT_GW/v1/payments/PAYMENT_ID/status
6212
8877
 
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) => {
8878
+ Permit2 contract addresses, for the approval named under PREREQUISITE above:
8879
+ EVM: 0x000000000022D473030F116dDEE9F6B43aC78BA3 (virtually all chains)
8880
+ Tron mainnet: TJhMXTHQHeQyMD7TcKQFqAePNgG4b31H9m
8881
+ Tron Shasta: TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp`
8882
+ ).action(async (sender, amount, sourceAsset, receiver, destinationAsset, options) => {
6218
8883
  let requestId;
8884
+ let submittedRequest;
6219
8885
  try {
6220
- const sourceChainId = sourceAsset.split("/")[0];
8886
+ const corridor = [sender, amount, sourceAsset, receiver, destinationAsset];
8887
+ const supplied = corridor.filter((value) => value !== void 0).length;
8888
+ if (options.submit && supplied > 0) {
8889
+ throw new Error(
8890
+ "--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."
8891
+ );
8892
+ }
8893
+ if (!options.submit && supplied < corridor.length) {
8894
+ throw new Error(
8895
+ `send-payment needs five arguments (sender, amount, sourceAsset, receiver, destinationAsset), or --submit <file> to send a request prepared earlier. Got ${supplied}.`
8896
+ );
8897
+ }
8898
+ if (options.submit) {
8899
+ const prepared = await readPaymentRequest(options.submit);
8900
+ submittedRequest = prepared;
8901
+ requestId = prepared.request_id;
8902
+ warnIfQuoteWindowClosed(prepared);
8903
+ console.error(
8904
+ `submitting request_id ${requestId} (quote_deadline ${prepared.quote_deadline})`
8905
+ );
8906
+ const submittedCode = await submitAndReport({
8907
+ client: new PaymentGatewayClient2({ BASE: options.gateway }),
8908
+ paymentRequest: prepared,
8909
+ requestId,
8910
+ wait: options.wait,
8911
+ waitSeconds: options.waitSeconds
8912
+ });
8913
+ process.exit(submittedCode);
8914
+ }
8915
+ requirePinnedSender(sender);
8916
+ const sourceChainId = assetChainId(sourceAsset);
6221
8917
  let privateKey = "";
6222
8918
  let signer;
6223
8919
  if (options.provider === "turnkey") {
@@ -6228,7 +8924,11 @@ TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp on Shasta)`).action(async (sender, amount, so
6228
8924
  });
6229
8925
  } else if (options.provider === "raw") {
6230
8926
  privateKey = process.env.PRIVATE_KEY || await promptPrivateKey();
6231
- signer = createSenderSigner(sourceChainId, { provider: "raw", privateKey, pinnedAddress: sender });
8927
+ signer = createSenderSigner(sourceChainId, {
8928
+ provider: "raw",
8929
+ privateKey,
8930
+ pinnedAddress: sender
8931
+ });
6232
8932
  } else {
6233
8933
  throw new Error(`Unknown --provider '${options.provider}' (expected 'raw' or 'turnkey')`);
6234
8934
  }
@@ -6256,84 +8956,103 @@ TPUqJPASUn1zLvbLBgRZ5pBYrx7WSe5ahp on Shasta)`).action(async (sender, amount, so
6256
8956
  delegate_signer: delegateSigner
6257
8957
  };
6258
8958
  }
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
- }
8959
+ if (options.prepareOnly) {
8960
+ console.log(JSON.stringify(paymentRequest, null, 2));
8961
+ console.error(
8962
+ `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)`
8963
+ );
8964
+ console.error(
8965
+ `quote_deadline: ${paymentRequest.quote_deadline} (the gateway refuses this document after that instant; pass --quote-deadline-seconds to widen it)`
8966
+ );
8967
+ console.error(
8968
+ "prepared: nothing was submitted and no payment exists. Send it with `send-payment --submit <file>`."
8969
+ );
8970
+ console.error(
8971
+ "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."
8972
+ );
8973
+ process.exit(EXIT_COMPLETED);
6281
8974
  }
6282
- console.log(JSON.stringify(reported, null, 2));
6283
- const outcome = {
6284
- status: reported.status,
6285
- paymentId: reported.payment_id,
8975
+ console.error(JSON.stringify(paymentRequest, null, 2));
8976
+ console.error(
8977
+ `request_id: ${requestId} (re-run with --request-id ${requestId} to retry this same payment)`
8978
+ );
8979
+ const exitCode = await submitAndReport({
8980
+ client,
8981
+ paymentRequest,
6286
8982
  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);
8983
+ wait: options.wait,
8984
+ waitSeconds: options.waitSeconds
8985
+ });
6294
8986
  process.exit(exitCode);
6295
8987
  } catch (error) {
6296
8988
  if (error instanceof ApiError && error.body) {
6297
8989
  console.log(JSON.stringify(error.body, null, 2));
6298
8990
  } else {
6299
8991
  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
8992
  }
6305
8993
  if (requestId) {
6306
- console.error(`request_id: ${requestId} (re-run with --request-id ${requestId} to retry this same payment)`);
8994
+ const windowStillOpen = submittedRequest !== void 0 && quoteWindowOpen(submittedRequest);
8995
+ console.error(
8996
+ 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)`
8997
+ );
6307
8998
  }
6308
8999
  process.exit(EXIT_ERROR);
6309
9000
  }
6310
9001
  });
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
- });
9002
+ async function readPaymentRequest(file) {
9003
+ if (file === "-" && process.stdin.isTTY) {
9004
+ throw new Error("--submit - reads stdin, but nothing is piped in. Pass a file path instead");
9005
+ }
9006
+ const raw = file === "-" ? await readStdin() : (0, import_fs.readFileSync)(file, "utf8");
9007
+ if (raw.trim() === "") {
9008
+ throw new Error(
9009
+ file === "-" ? "nothing arrived on stdin. Pipe a prepared request in, or pass a file path instead" : `${file} is empty`
9010
+ );
9011
+ }
9012
+ let parsed;
9013
+ try {
9014
+ parsed = JSON.parse(raw);
9015
+ } catch (error) {
9016
+ throw new Error(
9017
+ `${file === "-" ? "stdin" : file} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
9018
+ { cause: error }
9019
+ );
9020
+ }
9021
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
9022
+ throw new Error(`${file === "-" ? "stdin" : file} does not hold a PaymentRequest object`);
9023
+ }
9024
+ const request2 = parsed;
9025
+ if (!request2.request_id) {
9026
+ throw new Error(
9027
+ "this does not look like a PaymentRequest: no request_id. Produce one with `send-payment --prepare-only`"
9028
+ );
9029
+ }
9030
+ const signature = request2.sender_auth?.signed_messages?.[0]?.signature;
9031
+ if (!signature) {
9032
+ throw new Error(
9033
+ "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"
9034
+ );
9035
+ }
9036
+ return request2;
9037
+ }
9038
+ async function readStdin() {
9039
+ const chunks = [];
9040
+ for await (const chunk of process.stdin) {
9041
+ chunks.push(chunk);
9042
+ }
9043
+ return Buffer.concat(chunks).toString("utf8");
9044
+ }
9045
+ function quoteWindowOpen(request2) {
9046
+ const deadline = Date.parse(request2.quote_deadline ?? "");
9047
+ return Number.isNaN(deadline) || deadline > Date.now();
9048
+ }
9049
+ function warnIfQuoteWindowClosed(request2) {
9050
+ if (quoteWindowOpen(request2)) return;
9051
+ console.error(
9052
+ `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.`
9053
+ );
6335
9054
  }
6336
- program.parse();
9055
+ runCli(program);
6337
9056
  /*! Bundled license information:
6338
9057
 
6339
9058
  @noble/hashes/utils.js: