@atumlabs/payment-gateway-client 2.1.0 → 3.0.0

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