@zkp2p/cash 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -237,10 +237,12 @@ function deriveCashOrder(depositId, intents, options = {}) {
237
237
  const total = options.totalAmount ?? remaining + outstanding + taken + withdrawn;
238
238
  const status = options.status;
239
239
  const isTerminal = status === "CLOSED" || status === "WITHDRAWN";
240
- const hasLiveFunds = remaining > DUST_THRESHOLD || outstanding > 0n;
240
+ const hasLiveFunds = remaining >= DUST_THRESHOLD || outstanding > 0n;
241
241
  let state;
242
242
  if (outstanding > 0n) {
243
243
  state = taken > 0n ? "delivering" : "matched";
244
+ } else if (!hasLiveFunds && withdrawn > 0n) {
245
+ state = "returned";
244
246
  } else if (taken > 0n && !hasLiveFunds) {
245
247
  state = "delivered";
246
248
  } else if (taken > 0n && hasLiveFunds) {
@@ -282,7 +284,7 @@ function deriveCashOrder(depositId, intents, options = {}) {
282
284
  ...options.payouts !== void 0 ? { payouts: options.payouts } : {},
283
285
  ...options.successRateBps !== void 0 ? { successRateBps: options.successRateBps } : {},
284
286
  isInFlight,
285
- withdrawn: isTerminal
287
+ withdrawn: state === "returned" && withdrawn > 0n
286
288
  });
287
289
  }
288
290
  var ORACLE_KINDS = /* @__PURE__ */ new Set(["oracle_chainlink", "oracle_pyth"]);
@@ -392,12 +394,14 @@ function resolveCashDepositId(params) {
392
394
  }
393
395
  function parseCompositeDepositId(compositeId) {
394
396
  const idx = compositeId.lastIndexOf("_");
395
- if (idx === -1) {
396
- return { escrowAddress: "", onchainDepositId: BigInt(compositeId) };
397
- }
398
397
  const escrowAddress = compositeId.slice(0, idx);
399
- const onchainDepositId = BigInt(compositeId.slice(idx + 1) || "0");
400
- return { escrowAddress, onchainDepositId };
398
+ const rawDepositId = compositeId.slice(idx + 1);
399
+ if (idx <= 0 || compositeId.indexOf("_") !== idx || !viem.isAddress(escrowAddress, { strict: false }) || !/^\d+$/.test(rawDepositId)) {
400
+ throw new Error(`Invalid deposit id: '${compositeId}'`);
401
+ }
402
+ const canonicalEscrowAddress = escrowAddress.toLowerCase();
403
+ const onchainDepositId = BigInt(rawDepositId);
404
+ return { escrowAddress: canonicalEscrowAddress, onchainDepositId };
401
405
  }
402
406
  var MIN_CASHOUT_AMOUNT = 10000n;
403
407
  var RECOMMENDED_MIN_CASHOUT_AMOUNT = 1000000n;
@@ -415,9 +419,6 @@ var PAYEE_HINTS = {
415
419
  n26: "MoneyBeam email or phone number"
416
420
  };
417
421
  var IDENTITY_ATTESTATION_PLATFORMS = /* @__PURE__ */ new Set(["wise", "paypal"]);
418
- function platformRequiresIdentityAttestation(platform) {
419
- return IDENTITY_ATTESTATION_PLATFORMS.has(platform);
420
- }
421
422
  function buildCapabilities(environment) {
422
423
  const catalog = sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment);
423
424
  const platforms = Object.entries(catalog).map(([platform, entry]) => {
@@ -451,12 +452,14 @@ var CashError = class extends Error {
451
452
  code;
452
453
  retryable;
453
454
  remediation;
455
+ recovery;
454
456
  constructor(shape, options) {
455
457
  super(shape.message, options);
456
458
  this.name = "CashError";
457
459
  this.code = shape.code;
458
460
  this.retryable = shape.retryable;
459
461
  this.remediation = shape.remediation;
462
+ if (shape.recovery) this.recovery = shape.recovery;
460
463
  }
461
464
  /** Serializable view (for tool results and logs). */
462
465
  toJSON() {
@@ -464,7 +467,8 @@ var CashError = class extends Error {
464
467
  code: this.code,
465
468
  message: this.message,
466
469
  retryable: this.retryable,
467
- remediation: this.remediation
470
+ remediation: this.remediation,
471
+ ...this.recovery ? { recovery: this.recovery } : {}
468
472
  };
469
473
  }
470
474
  };
@@ -478,18 +482,39 @@ var errors = {
478
482
  retryable: false,
479
483
  remediation: `Pick a currency listed in capabilities() - each one is priced by a live oracle feed.`
480
484
  }),
485
+ oracleReadFailed: (currency, cause) => new CashError(
486
+ {
487
+ code: "ORACLE_READ_FAILED",
488
+ message: `The ${currency} market-rate oracle could not be read.`,
489
+ retryable: true,
490
+ remediation: `Retry the estimate shortly or use another healthy Base RPC. Do not present a cached value as a live market rate.`
491
+ },
492
+ { cause }
493
+ ),
481
494
  unsupportedPlatform: (platform) => new CashError({
482
495
  code: "UNSUPPORTED_PLATFORM",
483
496
  message: `'${platform}' is not a supported payout platform in this environment.`,
484
497
  retryable: false,
485
498
  remediation: `Pick a platform listed in capabilities().`
486
499
  }),
500
+ unsupportedPlatformCurrency: (platform, currency) => new CashError({
501
+ code: "UNSUPPORTED_PLATFORM_CURRENCY",
502
+ message: `${platform} cannot receive ${currency} in this environment.`,
503
+ retryable: false,
504
+ remediation: `Pick one of the currencies listed for ${platform} in capabilities().`
505
+ }),
487
506
  amountBelowMinimum: (amount, min) => new CashError({
488
507
  code: "AMOUNT_BELOW_MINIMUM",
489
508
  message: `Amount ${amount} is below the minimum cash-out of ${min} USDC base units.`,
490
509
  retryable: false,
491
510
  remediation: `Increase the amount to at least ${min} base units (${Number(min) / 1e6} USDC).`
492
511
  }),
512
+ invalidIntentAmountRange: (amount, min, max) => new CashError({
513
+ code: "INVALID_INTENT_AMOUNT_RANGE",
514
+ message: `Intent amount range ${min}-${max} is invalid for a ${amount} base-unit cash-out.`,
515
+ retryable: false,
516
+ remediation: `Use a positive minimum no greater than the maximum, and a maximum no greater than the cash-out amount.`
517
+ }),
493
518
  activeIntentBlocksWithdrawal: (depositId) => new CashError({
494
519
  code: "ACTIVE_INTENT_BLOCKS_WITHDRAWAL",
495
520
  message: `Order ${depositId} has a live buyer intent; escrow blocks withdrawal while a buyer may still deliver.`,
@@ -502,12 +527,27 @@ var errors = {
502
527
  retryable: true,
503
528
  remediation: `Withdraw at most the available (unlocked) amount, or omit the amount to close the order fully once no buyer intent is live.`
504
529
  }),
530
+ insufficientTokenBalance: (requiredAmount) => new CashError({
531
+ code: "INSUFFICIENT_TOKEN_BALANCE",
532
+ message: requiredAmount === void 0 ? `The wallet does not hold enough of the source token for this transaction.` : `The wallet does not hold the ${requiredAmount} base units required for this transaction.`,
533
+ retryable: false,
534
+ remediation: requiredAmount === void 0 ? `Fund the wallet with the required token amount, then retry.` : `Fund the wallet to at least ${requiredAmount} token base units, then retry.`
535
+ }),
505
536
  orderNotActive: (depositId) => new CashError({
506
537
  code: "ORDER_NOT_ACTIVE",
507
538
  message: `Order ${depositId} is closed (delivered or returned); it cannot be topped up.`,
508
539
  retryable: false,
509
540
  remediation: `Start a new cash-out with cashout() instead.`
510
541
  }),
542
+ invalidDepositId: (depositId, cause) => new CashError(
543
+ {
544
+ code: "INVALID_DEPOSIT_ID",
545
+ message: `'${depositId}' is not a valid Peer Cash deposit id.`,
546
+ retryable: false,
547
+ remediation: `Use the depositId returned by cashout() (escrowAddress_onchainDepositId) without modifying it.`
548
+ },
549
+ { cause }
550
+ ),
511
551
  nothingToWithdraw: (depositId) => new CashError({
512
552
  code: "NOTHING_TO_WITHDRAW",
513
553
  message: `Order ${depositId} holds no withdrawable funds (already delivered or returned).`,
@@ -526,6 +566,15 @@ var errors = {
526
566
  retryable: true,
527
567
  remediation: `Verify the composite depositId (escrow_onchainId). If the deposit was created seconds ago this is indexer lag - retry shortly.`
528
568
  }),
569
+ indexerUnavailable: (operation, cause) => new CashError(
570
+ {
571
+ code: "INDEXER_UNAVAILABLE",
572
+ message: `The protocol indexer could not complete the ${operation} query.`,
573
+ retryable: true,
574
+ remediation: `Retry shortly. Keep the composite depositId or owner address so the read can resume without repeating an on-chain transaction.`
575
+ },
576
+ { cause }
577
+ ),
529
578
  payeeRegistrationFailed: (cause) => new CashError(
530
579
  {
531
580
  code: "PAYEE_REGISTRATION_FAILED",
@@ -556,12 +605,109 @@ var errors = {
556
605
  retryable: false,
557
606
  remediation: `For one-call source cashout, deliver Relay output to the depositor address. For a different recipient, bridge first and then cash out from that recipient's signer.`
558
607
  }),
559
- allowanceNotVisible: (amount) => new CashError({
560
- code: "ALLOWANCE_NOT_VISIBLE",
561
- message: `USDC approval for ${amount} base units did not become visible on the read path in time.`,
562
- retryable: true,
563
- remediation: `The approve transaction mined but a load-balanced RPC is serving stale state. Retry the same call in a few seconds.`
564
- }),
608
+ sourceCapabilitiesFailed: (cause) => new CashError(
609
+ {
610
+ code: "SOURCE_CAPABILITIES_FAILED",
611
+ message: `Relay source-chain discovery failed.`,
612
+ retryable: true,
613
+ remediation: `Retry sourceCapabilities() shortly, or use the default Base USDC path.`
614
+ },
615
+ { cause }
616
+ ),
617
+ sourceQuoteFailed: (cause) => new CashError(
618
+ {
619
+ code: "SOURCE_QUOTE_FAILED",
620
+ message: `Relay did not return a valid route to canonical Base USDC.`,
621
+ retryable: true,
622
+ remediation: `Refresh source capabilities and request a new quote. Do not submit transactions from this response.`
623
+ },
624
+ { cause }
625
+ ),
626
+ sourceExecutionFailed: (cause, evidence) => new CashError(
627
+ {
628
+ code: "SOURCE_EXECUTION_FAILED",
629
+ message: `Relay source-route execution did not complete successfully.`,
630
+ retryable: false,
631
+ remediation: `Inspect the wallet transactions and Relay request status before retrying so the source transfer is never submitted twice.`,
632
+ ...evidence && (evidence.requestId !== void 0 || evidence.txHashes.length > 0) ? {
633
+ recovery: {
634
+ kind: "inspect-relay-route",
635
+ ...evidence.requestId ? { requestId: evidence.requestId } : {},
636
+ txHashes: evidence.txHashes,
637
+ ...evidence.transactions ? { transactions: evidence.transactions } : {}
638
+ }
639
+ } : {}
640
+ },
641
+ { cause }
642
+ ),
643
+ sourceStatusFailed: (requestId, cause) => new CashError(
644
+ {
645
+ code: "SOURCE_STATUS_FAILED",
646
+ message: `Relay status is unavailable for request ${requestId}.`,
647
+ retryable: true,
648
+ remediation: `Retry relayStatus(requestId) shortly; keep the request id and transaction hashes for recovery.`
649
+ },
650
+ { cause }
651
+ ),
652
+ sourceRouteCompletedCashoutFailed: (source, cause) => new CashError(
653
+ {
654
+ code: "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED",
655
+ message: `Relay completed, but the Base USDC cash-out transaction was not created.`,
656
+ retryable: false,
657
+ remediation: `Do not repeat the Relay route. Retry cashout() without source using the recovery amount already delivered on Base.`,
658
+ recovery: {
659
+ kind: "retry-base-usdc-cashout",
660
+ amount: source.amount.toString(),
661
+ ...source.requestId ? { requestId: source.requestId } : {},
662
+ txHashes: source.txHashes,
663
+ ...source.transactions ? { transactions: source.transactions } : {}
664
+ }
665
+ },
666
+ { cause }
667
+ ),
668
+ sourceCashoutSubmissionUnknown: (source, depositor, cause) => new CashError(
669
+ {
670
+ code: "SOURCE_CASHOUT_SUBMISSION_UNKNOWN",
671
+ message: `Relay completed, but the Base cash-out submission did not return a transaction hash.`,
672
+ retryable: false,
673
+ remediation: `Do not repeat Relay or submit another cash-out yet. Inspect recent Base transactions and orders(${depositor}) to prove no deposit was broadcast; only then retry Base-USDC-only with the recovery amount.`,
674
+ recovery: {
675
+ kind: "inspect-base-cashout-submission",
676
+ amount: source.amount.toString(),
677
+ ...source.requestId ? { requestId: source.requestId } : {},
678
+ txHashes: source.txHashes,
679
+ ...source.transactions ? { transactions: source.transactions } : {},
680
+ depositor
681
+ }
682
+ },
683
+ { cause }
684
+ ),
685
+ sourceCashoutStatusUnknown: (source, depositTxHash, cause) => new CashError(
686
+ {
687
+ code: "SOURCE_CASHOUT_STATUS_UNKNOWN",
688
+ message: `Relay completed and Base cash-out transaction ${depositTxHash} was submitted, but its receipt could not be confirmed.`,
689
+ retryable: false,
690
+ remediation: `Do not repeat the Relay route or submit another cash-out. Inspect the Base transaction; if it succeeded, recover the depositId from its DepositReceived log, and if it reverted, retry a Base-USDC-only cashout with the recovery amount.`,
691
+ recovery: {
692
+ kind: "inspect-base-cashout-transaction",
693
+ amount: source.amount.toString(),
694
+ ...source.requestId ? { requestId: source.requestId } : {},
695
+ txHashes: source.txHashes,
696
+ ...source.transactions ? { transactions: source.transactions } : {},
697
+ depositTxHash
698
+ }
699
+ },
700
+ { cause }
701
+ ),
702
+ allowanceNotVisible: (amount, cause) => new CashError(
703
+ {
704
+ code: "ALLOWANCE_NOT_VISIBLE",
705
+ message: `USDC approval for ${amount} base units did not become visible on the read path in time.`,
706
+ retryable: true,
707
+ remediation: `The approve transaction mined but the RPC read path is stale or unavailable. Retry the same call in a few seconds.`
708
+ },
709
+ { cause }
710
+ ),
565
711
  depositResolutionFailed: (txHash) => new CashError({
566
712
  code: "DEPOSIT_RESOLUTION_FAILED",
567
713
  message: `Deposit transaction ${txHash} succeeded but no DepositReceived event was found in the receipt.`,
@@ -574,6 +720,21 @@ var errors = {
574
720
  retryable: false,
575
721
  remediation: `Pass { signer } (a viem WalletClient with an account), or use prepare() and submit the returned txs with your own signing infrastructure.`
576
722
  }),
723
+ signerChainMismatch: (verb, expectedChainId, actualChainId) => new CashError({
724
+ code: "SIGNER_CHAIN_MISMATCH",
725
+ message: `${verb} requires chain ${expectedChainId}, but the signer is connected to chain ${actualChainId}.`,
726
+ retryable: false,
727
+ remediation: `Switch the wallet to chain ${expectedChainId}, obtain a fresh quote if Relay is involved, and retry before submitting any transaction.`
728
+ }),
729
+ signerChainUnavailable: (verb, expectedChainId, cause) => new CashError(
730
+ {
731
+ code: "SIGNER_CHAIN_UNAVAILABLE",
732
+ message: `${verb} could not verify that the signer is connected to chain ${expectedChainId}.`,
733
+ retryable: true,
734
+ remediation: `Reconnect the wallet, switch it to chain ${expectedChainId}, and retry before submitting any transaction.`
735
+ },
736
+ { cause }
737
+ ),
577
738
  watchTimeout: (depositId, timeoutMs) => new CashError({
578
739
  code: "WATCH_TIMEOUT",
579
740
  message: `watch(${depositId}) exceeded ${timeoutMs}ms without reaching a terminal state.`,
@@ -589,6 +750,30 @@ var errors = {
589
750
  },
590
751
  { cause }
591
752
  ),
753
+ transactionSubmissionUnknown: (operation, cause, recovery) => new CashError(
754
+ {
755
+ code: "TRANSACTION_SUBMISSION_UNKNOWN",
756
+ message: `The Base ${operation} submission did not return a transaction hash.`,
757
+ retryable: false,
758
+ remediation: `Do not submit the operation again until you inspect recent Base wallet activity and protocol state; the first transaction may already exist.`,
759
+ ...recovery ? { recovery } : {}
760
+ },
761
+ { cause }
762
+ ),
763
+ transactionStatusUnknown: (txHash, cause, operation = "transaction") => new CashError(
764
+ {
765
+ code: "TRANSACTION_STATUS_UNKNOWN",
766
+ message: `Transaction ${txHash} was submitted, but its receipt could not be confirmed.`,
767
+ retryable: false,
768
+ remediation: `Do not resubmit the operation until you inspect ${txHash} on Base or successfully fetch its receipt; the transaction may already have succeeded.`,
769
+ recovery: {
770
+ kind: "inspect-base-transaction",
771
+ transactionHash: txHash,
772
+ operation
773
+ }
774
+ },
775
+ { cause }
776
+ ),
592
777
  escrowPaused: () => new CashError({
593
778
  code: "ESCROW_PAUSED",
594
779
  message: `The escrow contract is paused; deposits are temporarily disabled.`,
@@ -606,12 +791,15 @@ var errors = {
606
791
  { cause }
607
792
  )
608
793
  };
609
- function mapChainError(verb, err) {
794
+ function mapChainError(verb, err, context = {}) {
610
795
  if (isCashError(err)) return err;
611
796
  const message = err instanceof Error ? err.message : String(err);
612
797
  if (/\bpaused\b/i.test(message)) return errors.escrowPaused();
613
- if (/exceeds allowance|insufficient allowance|transfer amount exceeds/i.test(message)) {
614
- return errors.allowanceNotVisible(0n);
798
+ if (/exceeds balance|insufficient token balance/i.test(message)) {
799
+ return errors.insufficientTokenBalance(context.requiredAmount);
800
+ }
801
+ if (/exceeds allowance|insufficient allowance/i.test(message)) {
802
+ return errors.allowanceNotVisible(context.requiredAmount ?? 0n);
615
803
  }
616
804
  return errors.chainCallFailed(verb, err);
617
805
  }
@@ -777,20 +965,175 @@ function normalizeChain(chain) {
777
965
  function isSupportedEvmChain(chain) {
778
966
  return chain.vmType === void 0 || chain.vmType === "evm";
779
967
  }
968
+ function isExecutableSourceChain(chain) {
969
+ return isSupportedEvmChain(chain) && !chain.disabled && chain.depositEnabled && !chain.blockProductionLagging;
970
+ }
780
971
  function quoteRequestId(quote) {
781
972
  return quote.steps.map((step) => step.requestId).find((id) => id !== void 0);
782
973
  }
974
+ function collectRelayTransactions(steps, sourceChainId) {
975
+ const origin = [];
976
+ const destination = [];
977
+ const record = (tx) => {
978
+ (tx.chainId === sourceChainId ? origin : destination).push(tx);
979
+ };
980
+ for (const step of steps) {
981
+ for (const item of step.items) {
982
+ for (const tx of item.internalTxHashes ?? []) {
983
+ record({ hash: tx.txHash, chainId: tx.chainId });
984
+ }
985
+ for (const tx of item.txHashes ?? []) {
986
+ record({ hash: tx.txHash, chainId: tx.chainId });
987
+ }
988
+ }
989
+ }
990
+ const dedupe = (txs) => [
991
+ ...new Map(txs.map((tx) => [`${tx.chainId}:${tx.hash.toLowerCase()}`, tx])).values()
992
+ ];
993
+ return { origin: dedupe(origin), destination: dedupe(destination) };
994
+ }
995
+ function relayTransactionHashes(transactions) {
996
+ return [
997
+ ...new Set([...transactions.origin, ...transactions.destination].map(({ hash }) => hash))
998
+ ];
999
+ }
783
1000
  function quoteSourceChainId(quote) {
784
1001
  const details = asRecord(quote.details);
785
1002
  const currencyIn = asRecord(details.currencyIn);
786
1003
  const sourceCurrency = asRecord(currencyIn.currency);
787
1004
  return asNumber(sourceCurrency.chainId);
788
1005
  }
1006
+ function assertCanonicalRelayDestination(quote) {
1007
+ const details = asRecord(quote.details);
1008
+ const currencyOut = asRecord(details.currencyOut);
1009
+ const destination = asRecord(currencyOut.currency);
1010
+ if (asNumber(destination.chainId) !== BASE_CHAIN_ID || asString(destination.address)?.toLowerCase() !== BASE_USDC_ADDRESS.toLowerCase()) {
1011
+ throw new Error("Relay quote destination is not canonical Base USDC");
1012
+ }
1013
+ }
1014
+ async function assertWalletChainId(wallet, expectedChainId, operation) {
1015
+ let actualChainId;
1016
+ try {
1017
+ actualChainId = await wallet.getChainId();
1018
+ } catch (err) {
1019
+ throw errors.signerChainUnavailable(operation, expectedChainId, err);
1020
+ }
1021
+ if (actualChainId !== expectedChainId) {
1022
+ throw errors.signerChainMismatch(operation, expectedChainId, actualChainId);
1023
+ }
1024
+ }
1025
+ async function assertRelayExecutionIdentity(quote, wallet, expectedRecipient) {
1026
+ const signer = wallet.account?.address;
1027
+ if (!signer) throw new Error("Relay execution requires a wallet account");
1028
+ const sourceChainId = quoteSourceChainId(quote);
1029
+ if (sourceChainId !== void 0) {
1030
+ await assertWalletChainId(wallet, sourceChainId, "Relay execution");
1031
+ }
1032
+ const details = asRecord(quote.details);
1033
+ const sender = asString(details.sender);
1034
+ const recipient = asString(details.recipient);
1035
+ if (!sender || sender.toLowerCase() !== signer.toLowerCase()) {
1036
+ throw new Error("Relay quote sender does not match the execution signer");
1037
+ }
1038
+ const destinationOwner = expectedRecipient ?? signer;
1039
+ if (!recipient || recipient.toLowerCase() !== destinationOwner.toLowerCase()) {
1040
+ throw new Error("Relay quote recipient does not match the expected Base recipient");
1041
+ }
1042
+ }
1043
+ function isRelaySecretKey(key) {
1044
+ const normalized = key.toLowerCase();
1045
+ return normalized === "headers" || normalized === "apikey";
1046
+ }
1047
+ function redactRelayValue(value, seen = /* @__PURE__ */ new WeakMap()) {
1048
+ if (value === null || typeof value !== "object") return value;
1049
+ if (value instanceof Date || value instanceof Error) return value;
1050
+ const existing = seen.get(value);
1051
+ if (existing !== void 0) return existing;
1052
+ if (Array.isArray(value)) {
1053
+ const output2 = [];
1054
+ seen.set(value, output2);
1055
+ for (const entry of value) output2.push(redactRelayValue(entry, seen));
1056
+ return output2;
1057
+ }
1058
+ const output = {};
1059
+ seen.set(value, output);
1060
+ for (const [key, entry] of Object.entries(value)) {
1061
+ if (!isRelaySecretKey(key)) output[key] = redactRelayValue(entry, seen);
1062
+ }
1063
+ return output;
1064
+ }
1065
+ var RELAY_WIRE_TYPE = "__zkp2pCashType";
1066
+ function sanitizeRelayValue(value, seen = /* @__PURE__ */ new WeakSet()) {
1067
+ if (typeof value === "bigint") {
1068
+ return { [RELAY_WIRE_TYPE]: "bigint", value: value.toString() };
1069
+ }
1070
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
1071
+ return value;
1072
+ }
1073
+ if (typeof value === "number") {
1074
+ return Number.isFinite(value) ? value : { [RELAY_WIRE_TYPE]: "number", value: String(value) };
1075
+ }
1076
+ if (typeof value === "undefined") return { [RELAY_WIRE_TYPE]: "undefined" };
1077
+ if (value instanceof Date) {
1078
+ return { [RELAY_WIRE_TYPE]: "date", value: value.toISOString() };
1079
+ }
1080
+ if (value instanceof Error) {
1081
+ return {
1082
+ [RELAY_WIRE_TYPE]: "error",
1083
+ name: value.name,
1084
+ message: value.message
1085
+ };
1086
+ }
1087
+ if (typeof value !== "object") return void 0;
1088
+ if (seen.has(value)) throw new TypeError("Relay payload contains a circular reference");
1089
+ seen.add(value);
1090
+ if (Array.isArray(value)) {
1091
+ const output2 = value.map((entry) => sanitizeRelayValue(entry, seen));
1092
+ seen.delete(value);
1093
+ return output2;
1094
+ }
1095
+ const output = {};
1096
+ for (const [key, entry] of Object.entries(value)) {
1097
+ if (isRelaySecretKey(key)) continue;
1098
+ const sanitized = sanitizeRelayValue(entry, seen);
1099
+ if (sanitized !== void 0) output[key] = sanitized;
1100
+ }
1101
+ seen.delete(value);
1102
+ return output;
1103
+ }
1104
+ function restoreRelayValue(value) {
1105
+ if (Array.isArray(value)) return value.map(restoreRelayValue);
1106
+ if (value === null || typeof value !== "object") return value;
1107
+ const row = value;
1108
+ const wireType = row[RELAY_WIRE_TYPE];
1109
+ const keyCount = Object.keys(row).length;
1110
+ if (keyCount === 2 && wireType === "bigint" && typeof row.value === "string") {
1111
+ return BigInt(row.value);
1112
+ }
1113
+ if (keyCount === 2 && wireType === "date" && typeof row.value === "string") {
1114
+ return new Date(row.value);
1115
+ }
1116
+ if (keyCount === 2 && wireType === "number" && typeof row.value === "string") {
1117
+ return Number(row.value);
1118
+ }
1119
+ if (keyCount === 1 && wireType === "undefined") return void 0;
1120
+ if (keyCount === 3 && wireType === "error" && typeof row.message === "string") {
1121
+ const error = new Error(row.message);
1122
+ if (typeof row.name === "string") error.name = row.name;
1123
+ return error;
1124
+ }
1125
+ return Object.fromEntries(
1126
+ Object.entries(row).map(([key, entry]) => [key, restoreRelayValue(entry)])
1127
+ );
1128
+ }
1129
+ function redactRelayQuoteRaw(quote) {
1130
+ return redactRelayValue(quote);
1131
+ }
789
1132
  function sanitizeRelayQuoteRaw(quote) {
790
- if (!quote.request) return quote;
791
- const request = { ...quote.request };
792
- delete request.headers;
793
- return { ...quote, request };
1133
+ return sanitizeRelayValue(quote);
1134
+ }
1135
+ function restoreRelayQuoteRaw(value) {
1136
+ return restoreRelayValue(value);
794
1137
  }
795
1138
  async function resolveRelayChains(options, client, config = {}) {
796
1139
  const preferInjectedClientChains = config.preferInjectedClientChains ?? true;
@@ -804,19 +1147,38 @@ function relayQuoteFromExecute(input, quote) {
804
1147
  const currencyOut = asRecord(details.currencyOut);
805
1148
  const sourceCurrency = asRecord(currencyIn.currency);
806
1149
  const destinationCurrency = asRecord(currencyOut.currency);
807
- const source = normalizeToken(input.source.chainId, sourceCurrency) ?? {
808
- chainId: input.source.chainId,
809
- address: input.source.currency,
810
- symbol: "TOKEN",
811
- decimals: 0
812
- };
813
- const destination = normalizeToken(BASE_CHAIN_ID, destinationCurrency) ?? BASE_USDC_ASSET;
1150
+ const sourceChainId = asNumber(sourceCurrency.chainId);
1151
+ const sourceAddress = asString(sourceCurrency.address);
1152
+ const sender = asString(details.sender);
1153
+ const recipient = asString(details.recipient);
1154
+ const expectedRecipient = input.recipient ?? input.user;
1155
+ const destinationChainId = asNumber(destinationCurrency.chainId);
1156
+ const destinationAddress = asString(destinationCurrency.address);
1157
+ if (sourceChainId !== input.source.chainId || sourceAddress?.toLowerCase() !== input.source.currency.toLowerCase()) {
1158
+ throw new Error("Relay quote source does not match the requested asset");
1159
+ }
1160
+ if (!sender || sender.toLowerCase() !== input.user.toLowerCase()) {
1161
+ throw new Error("Relay quote sender does not match the requested wallet");
1162
+ }
1163
+ if (!recipient || recipient.toLowerCase() !== expectedRecipient.toLowerCase()) {
1164
+ throw new Error("Relay quote recipient does not match the requested Base recipient");
1165
+ }
1166
+ if (destinationChainId !== BASE_CHAIN_ID || destinationAddress?.toLowerCase() !== BASE_USDC_ADDRESS.toLowerCase()) {
1167
+ throw new Error("Relay quote destination is not canonical Base USDC");
1168
+ }
1169
+ const source = normalizeToken(input.source.chainId, sourceCurrency);
1170
+ if (!source) throw new Error("Relay quote source metadata is malformed");
1171
+ const destination = normalizeToken(destinationChainId, destinationCurrency);
1172
+ if (!destination) throw new Error("Relay quote destination metadata is malformed");
814
1173
  const txs = quote.steps.flatMap(
815
1174
  (step) => step.items.map((item) => normalizeTx(item.data, input.source.chainId)).filter((tx) => tx !== null)
816
1175
  );
817
- const outputAmount = BigInt(
818
- String(currencyOut.minimumAmount ?? currencyOut.amount ?? input.amount.toString())
819
- );
1176
+ const rawOutputAmount = currencyOut.minimumAmount ?? currencyOut.amount;
1177
+ if (rawOutputAmount === void 0 || rawOutputAmount === null) {
1178
+ throw new Error("Relay quote is missing an output amount");
1179
+ }
1180
+ const outputAmount = BigInt(String(rawOutputAmount));
1181
+ if (outputAmount <= 0n) throw new Error("Relay quote output amount must be positive");
820
1182
  const requestId = quoteRequestId(quote);
821
1183
  const rate = asNumber(details.rate);
822
1184
  const timeEstimateSeconds = asNumber(details.timeEstimate);
@@ -824,92 +1186,135 @@ function relayQuoteFromExecute(input, quote) {
824
1186
  ...requestId ? { requestId } : {},
825
1187
  source,
826
1188
  destination,
827
- inputAmount: BigInt(String(currencyIn.amount ?? input.amount.toString())),
1189
+ inputAmount: BigInt(String(currencyIn.amount)),
828
1190
  outputAmount,
829
1191
  ...rate !== void 0 ? { rate } : {},
830
1192
  ...timeEstimateSeconds !== void 0 ? { timeEstimateSeconds } : {},
831
1193
  ...quote.fees !== void 0 ? { fees: quote.fees } : {},
832
1194
  txs,
833
- raw: sanitizeRelayQuoteRaw(quote)
1195
+ raw: redactRelayQuoteRaw(quote)
834
1196
  };
835
1197
  }
836
1198
  async function readRelaySourceCapabilities(options = {}) {
837
- const client = relayClient(options);
838
- const chains = await resolveRelayChains(options, client);
839
- return {
840
- destination: BASE_USDC_ASSET,
841
- chains: chains.map(normalizeChain).filter((chain) => chain.tokens.length > 0 && isSupportedEvmChain(chain)).sort((a, b) => a.displayName.localeCompare(b.displayName)),
842
- source: "relay-sdk",
843
- asOf: Math.floor(Date.now() / 1e3)
844
- };
1199
+ try {
1200
+ const client = relayClient(options);
1201
+ const chains = await resolveRelayChains(options, client);
1202
+ return {
1203
+ destination: BASE_USDC_ASSET,
1204
+ chains: chains.map(normalizeChain).filter((chain) => chain.tokens.length > 0 && isExecutableSourceChain(chain)).sort((a, b) => a.displayName.localeCompare(b.displayName)),
1205
+ source: "relay-sdk",
1206
+ asOf: Math.floor(Date.now() / 1e3)
1207
+ };
1208
+ } catch (err) {
1209
+ if (isCashError(err)) throw err;
1210
+ throw errors.sourceCapabilitiesFailed(err);
1211
+ }
845
1212
  }
846
1213
  async function quoteRelayToBaseUsdc(input, options = {}) {
847
- const client = relayClient(options);
848
- const quote = await client.actions.getQuote(
849
- {
850
- chainId: input.source.chainId,
851
- currency: input.source.currency,
852
- toChainId: BASE_CHAIN_ID,
853
- toCurrency: BASE_USDC_ADDRESS,
854
- user: input.user,
855
- recipient: input.recipient ?? input.user,
856
- amount: input.amount.toString(),
857
- tradeType: input.tradeType ?? "EXACT_INPUT"
858
- },
859
- false
860
- );
861
- return relayQuoteFromExecute(input, quote);
1214
+ try {
1215
+ if (input.amount <= 0n) throw new Error("Relay quote amount must be positive");
1216
+ const client = relayClient(options);
1217
+ const quote = await client.actions.getQuote(
1218
+ {
1219
+ chainId: input.source.chainId,
1220
+ currency: input.source.currency,
1221
+ toChainId: BASE_CHAIN_ID,
1222
+ toCurrency: BASE_USDC_ADDRESS,
1223
+ user: input.user,
1224
+ recipient: input.recipient ?? input.user,
1225
+ amount: input.amount.toString(),
1226
+ tradeType: input.tradeType ?? "EXACT_INPUT"
1227
+ },
1228
+ false
1229
+ );
1230
+ return relayQuoteFromExecute(input, quote);
1231
+ } catch (err) {
1232
+ if (isCashError(err)) throw err;
1233
+ throw errors.sourceQuoteFailed(err);
1234
+ }
862
1235
  }
863
1236
  async function executeRelayQuote(quote, wallet, options = {}) {
864
- const client = relayClient(options.relay);
865
- const sourceChainId = quoteSourceChainId(quote);
866
- if (sourceChainId !== void 0 && !(client.chains ?? []).some((chain) => chain.id === sourceChainId)) {
867
- await resolveRelayChains(options.relay ?? {}, client, { preferInjectedClientChains: false });
868
- }
869
- const { data } = await client.actions.execute({
870
- quote,
871
- wallet,
872
- ...options.onProgress ? { onProgress: options.onProgress } : {},
873
- ...options.disableCapabilitiesCheck !== void 0 ? { disableCapabilitiesCheck: options.disableCapabilitiesCheck } : {}
874
- });
875
- const requestId = quoteRequestId(data);
876
- return {
877
- ...requestId ? { requestId } : {},
878
- txHashes: data.steps.flatMap(
879
- (step) => step.items.flatMap((item) => (item.txHashes ?? []).map((tx) => tx.txHash))
880
- ),
881
- quote: data
882
- };
1237
+ let observedRequestId;
1238
+ let observedTransactions = { origin: [], destination: [] };
1239
+ try {
1240
+ const rawQuote = "raw" in quote ? quote.raw : quote;
1241
+ observedRequestId = quoteRequestId(rawQuote);
1242
+ assertCanonicalRelayDestination(rawQuote);
1243
+ await assertRelayExecutionIdentity(rawQuote, wallet, options.recipient);
1244
+ const client = relayClient(options.relay);
1245
+ const sourceChainId = quoteSourceChainId(rawQuote);
1246
+ if (sourceChainId !== void 0 && !(client.chains ?? []).some((chain) => chain.id === sourceChainId)) {
1247
+ await resolveRelayChains(options.relay ?? {}, client, { preferInjectedClientChains: false });
1248
+ }
1249
+ const onProgress = (data2) => {
1250
+ const progressSteps = Array.isArray(data2.steps) ? data2.steps : [];
1251
+ observedRequestId = progressSteps.map((step) => step.requestId).find((id) => id !== void 0) ?? observedRequestId;
1252
+ observedTransactions = collectRelayTransactions(progressSteps, sourceChainId);
1253
+ if (options.onProgress) {
1254
+ try {
1255
+ options.onProgress(data2);
1256
+ } catch {
1257
+ }
1258
+ }
1259
+ };
1260
+ const { data } = await client.actions.execute({
1261
+ quote: rawQuote,
1262
+ wallet,
1263
+ onProgress,
1264
+ ...options.disableCapabilitiesCheck !== void 0 ? { disableCapabilitiesCheck: options.disableCapabilitiesCheck } : {}
1265
+ });
1266
+ const requestId = quoteRequestId(data) ?? observedRequestId;
1267
+ const transactions = collectRelayTransactions(data.steps, sourceChainId);
1268
+ return {
1269
+ ...requestId ? { requestId } : {},
1270
+ txHashes: relayTransactionHashes(transactions),
1271
+ transactions,
1272
+ quote: redactRelayQuoteRaw(data)
1273
+ };
1274
+ } catch (err) {
1275
+ if (isCashError(err)) throw err;
1276
+ const txHashes = relayTransactionHashes(observedTransactions);
1277
+ throw errors.sourceExecutionFailed(err, {
1278
+ ...observedRequestId ? { requestId: observedRequestId } : {},
1279
+ txHashes,
1280
+ ...txHashes.length > 0 ? { transactions: observedTransactions } : {}
1281
+ });
1282
+ }
883
1283
  }
884
1284
  async function readRelayStatus(requestId, options = {}) {
885
- const client = relayClient(options);
886
- const response = await client.utils.request({
887
- url: `${client.baseApiUrl}/intents/status/v3`,
888
- method: "get",
889
- params: { requestId }
890
- });
891
- const root = asRecord(response.data);
892
- const status = asString(root.status);
893
- if (status !== "refund" && status !== "waiting" && status !== "depositing" && status !== "failure" && status !== "pending" && status !== "submitted" && status !== "success") {
894
- throw new Error(`Relay returned unknown status: ${String(root.status)}`);
895
- }
896
- const details = asString(root.details);
897
- const updatedAt = asNumber(root.updatedAt);
898
- const originChainId = asNumber(root.originChainId);
899
- const destinationChainId = asNumber(root.destinationChainId);
900
- const quoteCreatedAt = asNumber(root.quoteCreatedAt);
901
- return {
902
- requestId,
903
- status,
904
- ...details ? { details } : {},
905
- inTxHashes: Array.isArray(root.inTxHashes) ? root.inTxHashes.map(String) : [],
906
- txHashes: Array.isArray(root.txHashes) ? root.txHashes.map(String) : [],
907
- ...updatedAt !== void 0 ? { updatedAt } : {},
908
- ...originChainId !== void 0 ? { originChainId } : {},
909
- ...destinationChainId !== void 0 ? { destinationChainId } : {},
910
- ...quoteCreatedAt !== void 0 ? { quoteCreatedAt } : {},
911
- raw: response.data
912
- };
1285
+ try {
1286
+ const client = relayClient(options);
1287
+ const response = await client.utils.request({
1288
+ url: `${client.baseApiUrl}/intents/status/v3`,
1289
+ method: "get",
1290
+ params: { requestId }
1291
+ });
1292
+ const root = asRecord(response.data);
1293
+ const status = asString(root.status);
1294
+ if (status !== "refund" && status !== "waiting" && status !== "depositing" && status !== "failure" && status !== "pending" && status !== "submitted" && status !== "success") {
1295
+ throw new Error(`Relay returned unknown status: ${String(root.status)}`);
1296
+ }
1297
+ const details = asString(root.details);
1298
+ const updatedAt = asNumber(root.updatedAt);
1299
+ const originChainId = asNumber(root.originChainId);
1300
+ const destinationChainId = asNumber(root.destinationChainId);
1301
+ const quoteCreatedAt = asNumber(root.quoteCreatedAt);
1302
+ return {
1303
+ requestId,
1304
+ status,
1305
+ ...details ? { details } : {},
1306
+ inTxHashes: Array.isArray(root.inTxHashes) ? root.inTxHashes.map(String) : [],
1307
+ txHashes: Array.isArray(root.txHashes) ? root.txHashes.map(String) : [],
1308
+ ...updatedAt !== void 0 ? { updatedAt } : {},
1309
+ ...originChainId !== void 0 ? { originChainId } : {},
1310
+ ...destinationChainId !== void 0 ? { destinationChainId } : {},
1311
+ ...quoteCreatedAt !== void 0 ? { quoteCreatedAt } : {},
1312
+ raw: response.data
1313
+ };
1314
+ } catch (err) {
1315
+ if (isCashError(err)) throw err;
1316
+ throw errors.sourceStatusFailed(requestId, err);
1317
+ }
913
1318
  }
914
1319
 
915
1320
  // src/client/estimate.ts
@@ -956,11 +1361,16 @@ async function readEstimate(publicClient, input, context = {}) {
956
1361
  if (!feedConfig || feedConfig.feed.toLowerCase() === ZERO_ADDRESS) {
957
1362
  rate = 1;
958
1363
  } else {
959
- const result = await publicClient.readContract({
960
- address: feedConfig.feed,
961
- abi: CHAINLINK_LATEST_ROUND_ABI,
962
- functionName: "latestRoundData"
963
- });
1364
+ let result;
1365
+ try {
1366
+ result = await publicClient.readContract({
1367
+ address: feedConfig.feed,
1368
+ abi: CHAINLINK_LATEST_ROUND_ABI,
1369
+ functionName: "latestRoundData"
1370
+ });
1371
+ } catch (err) {
1372
+ throw errors.oracleReadFailed(currency, err);
1373
+ }
964
1374
  const answer = Number(result[1]);
965
1375
  const price = answer / 10 ** feedConfig.decimals;
966
1376
  if (!Number.isFinite(price) || price <= 0) {
@@ -1006,6 +1416,7 @@ async function readEstimate(publicClient, input, context = {}) {
1006
1416
  var DEFAULT_RPC_URL = "https://mainnet.base.org";
1007
1417
  var CASH_ATTRIBUTION_CODE = "peer-cash";
1008
1418
  var DEFAULT_CURATOR_URLS = {
1419
+ preproduction: "https://api-preprod.zkp2p.xyz",
1009
1420
  staging: "https://api-staging.zkp2p.xyz"
1010
1421
  };
1011
1422
  var ERC20_APPROVE_ABI = viem.parseAbi([
@@ -1040,12 +1451,29 @@ async function submitAndConfirm(client, verb, send) {
1040
1451
  try {
1041
1452
  hash = await send();
1042
1453
  } catch (err) {
1043
- throw mapChainError(verb, err);
1454
+ const mapped = mapChainError(verb, err);
1455
+ if (isKnownPreBroadcastFailure(err, mapped)) throw mapped;
1456
+ throw errors.transactionSubmissionUnknown(verb, err, {
1457
+ kind: "inspect-base-operation-submission",
1458
+ operation: verb
1459
+ });
1460
+ }
1461
+ let receipt;
1462
+ try {
1463
+ receipt = await client.publicClient.waitForTransactionReceipt({ hash });
1464
+ } catch (err) {
1465
+ throw errors.transactionStatusUnknown(hash, err, verb);
1044
1466
  }
1045
- const receipt = await client.publicClient.waitForTransactionReceipt({ hash });
1046
1467
  if (receipt.status === "reverted") throw errors.transactionFailed(hash);
1047
1468
  return hash;
1048
1469
  }
1470
+ function isKnownPreBroadcastFailure(err, mapped) {
1471
+ if (mapped.code === "INSUFFICIENT_TOKEN_BALANCE" || mapped.code === "ALLOWANCE_NOT_VISIBLE" || mapped.code === "ESCROW_PAUSED") {
1472
+ return true;
1473
+ }
1474
+ const message = err instanceof Error ? err.message : String(err);
1475
+ return /user rejected|user denied|rejected request|action_rejected/i.test(message);
1476
+ }
1049
1477
  function depositOrderOptions(deposit) {
1050
1478
  const remaining = toBigIntOrUndefined(deposit.remainingDeposits);
1051
1479
  const outstanding = toBigIntOrUndefined(deposit.outstandingIntentAmount);
@@ -1085,9 +1513,10 @@ function createCashClient(options) {
1085
1513
  }
1086
1514
  const readClient = buildSdkClient(viem.createWalletClient({ chain: chains.base, transport }));
1087
1515
  const signingClients = /* @__PURE__ */ new WeakMap();
1088
- function signingClient(verb, opts) {
1516
+ async function signingClient(verb, opts) {
1089
1517
  const signer = opts?.signer;
1090
1518
  if (!signer?.account) throw errors.signerRequired(verb);
1519
+ await assertWalletChainId(signer, BASE_CHAIN_ID, verb);
1091
1520
  let client = signingClients.get(signer);
1092
1521
  if (!client) {
1093
1522
  client = buildSdkClient(signer);
@@ -1097,13 +1526,15 @@ function createCashClient(options) {
1097
1526
  }
1098
1527
  function validatePayout(input) {
1099
1528
  const { receive } = input;
1100
- const catalog = sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment);
1101
- if (!catalog[receive.platform]) throw errors.unsupportedPlatform(receive.platform);
1529
+ const platform = buildCapabilities(environment).platforms.find(
1530
+ (capability) => capability.platform === receive.platform
1531
+ );
1532
+ if (!platform) throw errors.unsupportedPlatform(receive.platform);
1102
1533
  if (!isMarketRateSupported(receive.currency)) {
1103
1534
  throw errors.oracleUnsupportedCurrency(receive.currency);
1104
1535
  }
1105
- if (platformRequiresIdentityAttestation(receive.platform) && !receive.payee.identityAttestation) {
1106
- throw errors.payeeVerificationRequired(receive.platform);
1536
+ if (!platform.currencies.includes(receive.currency)) {
1537
+ throw errors.unsupportedPlatformCurrency(receive.platform, receive.currency);
1107
1538
  }
1108
1539
  return {
1109
1540
  payouts: [
@@ -1112,15 +1543,22 @@ function createCashClient(options) {
1112
1543
  currency: receive.currency,
1113
1544
  payeeData: receive.payee
1114
1545
  }
1115
- ],
1116
- ...input.intentAmountRange ? { intentAmountRange: input.intentAmountRange } : {}
1546
+ ]
1117
1547
  };
1118
1548
  }
1119
- function validateInput(input) {
1120
- if (input.amount < MIN_CASHOUT_AMOUNT) {
1121
- throw errors.amountBelowMinimum(input.amount, MIN_CASHOUT_AMOUNT);
1549
+ function validateDepositInput(amount, input, payoutInput = validatePayout(input)) {
1550
+ if (amount < MIN_CASHOUT_AMOUNT) {
1551
+ throw errors.amountBelowMinimum(amount, MIN_CASHOUT_AMOUNT);
1552
+ }
1553
+ const range = input.intentAmountRange;
1554
+ if (range && (range.min <= 0n || range.max < range.min || range.max > amount)) {
1555
+ throw errors.invalidIntentAmountRange(amount, range.min, range.max);
1122
1556
  }
1123
- return { amount: input.amount, ...validatePayout(input) };
1557
+ return {
1558
+ amount,
1559
+ ...payoutInput,
1560
+ ...range ? { intentAmountRange: range } : {}
1561
+ };
1124
1562
  }
1125
1563
  async function buildDepositParams(client, depositInput) {
1126
1564
  try {
@@ -1135,32 +1573,54 @@ function createCashClient(options) {
1135
1573
  throw errors.payeeRegistrationFailed(err);
1136
1574
  }
1137
1575
  }
1576
+ function parseDepositId(depositId) {
1577
+ try {
1578
+ const parsed = parseCompositeDepositId(depositId);
1579
+ return {
1580
+ ...parsed,
1581
+ compositeId: sdk.createCompositeDepositId(parsed.escrowAddress, parsed.onchainDepositId)
1582
+ };
1583
+ } catch (err) {
1584
+ throw errors.invalidDepositId(depositId, err);
1585
+ }
1586
+ }
1138
1587
  async function fetchOrder(depositId) {
1139
- const deposits = await readClient.indexer.getDepositsByIdsWithRelations([depositId], {
1140
- includeIntents: true,
1141
- intentStatuses: CASH_ORDER_STATUSES
1142
- });
1588
+ const { compositeId } = parseDepositId(depositId);
1589
+ let deposits;
1590
+ try {
1591
+ deposits = await readClient.indexer.getDepositsByIdsWithRelations([compositeId], {
1592
+ includeIntents: true,
1593
+ intentStatuses: CASH_ORDER_STATUSES
1594
+ });
1595
+ } catch (err) {
1596
+ throw errors.indexerUnavailable("order", err);
1597
+ }
1143
1598
  const deposit = deposits[0];
1144
1599
  if (!deposit) {
1145
- const intents = await readClient.indexer.getIntentsForDeposits(
1146
- [depositId],
1147
- CASH_ORDER_STATUSES
1148
- );
1149
- if (intents.length === 0) throw errors.orderNotFound(depositId);
1150
- return deriveCashOrder(depositId, intents);
1600
+ let intents;
1601
+ try {
1602
+ intents = await readClient.indexer.getIntentsForDeposits(
1603
+ [compositeId],
1604
+ CASH_ORDER_STATUSES
1605
+ );
1606
+ } catch (err) {
1607
+ throw errors.indexerUnavailable("order intents", err);
1608
+ }
1609
+ if (intents.length === 0) throw errors.orderNotFound(compositeId);
1610
+ return deriveCashOrder(compositeId, intents);
1151
1611
  }
1152
1612
  const payouts = derivePayouts(
1153
1613
  deposit.paymentMethods ?? [],
1154
1614
  deposit.currencies ?? [],
1155
1615
  sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment)
1156
1616
  );
1157
- return deriveCashOrder(depositId, deposit.intents ?? [], {
1617
+ return deriveCashOrder(compositeId, deposit.intents ?? [], {
1158
1618
  ...depositOrderOptions(deposit),
1159
1619
  ...payouts.length > 0 ? { payouts } : {}
1160
1620
  });
1161
1621
  }
1162
1622
  function escrowContext(depositId) {
1163
- const { escrowAddress, onchainDepositId } = parseCompositeDepositId(depositId);
1623
+ const { escrowAddress, onchainDepositId } = parseDepositId(depositId);
1164
1624
  return {
1165
1625
  onchainDepositId,
1166
1626
  escrowArg: escrowAddress ? { escrowAddress } : {}
@@ -1175,7 +1635,7 @@ function createCashClient(options) {
1175
1635
  const signaled = order.fills.filter((f) => f.status === "SIGNALED");
1176
1636
  const liveIntent = signaled.some((f) => isFillLive(f, nowSeconds));
1177
1637
  const expiredIntent = signaled.length > 0 && !liveIntent;
1178
- if (order.pendingAmount > 0n && liveIntent) {
1638
+ if (liveIntent || order.pendingAmount > 0n && signaled.length === 0) {
1179
1639
  throw errors.activeIntentBlocksWithdrawal(depositId);
1180
1640
  }
1181
1641
  if (availableAmount(order) <= 0n && order.pendingAmount === 0n) {
@@ -1216,22 +1676,32 @@ function createCashClient(options) {
1216
1676
  txOverrides: attribution
1217
1677
  });
1218
1678
  } catch (err) {
1219
- throw mapChainError("approve", err);
1679
+ throw mapChainError("approve", err, { requiredAmount: amount });
1220
1680
  }
1221
1681
  if (allowance.hadAllowance || !allowance.hash) return;
1222
- const receipt = await client.publicClient.waitForTransactionReceipt({ hash: allowance.hash });
1682
+ let receipt;
1683
+ try {
1684
+ receipt = await client.publicClient.waitForTransactionReceipt({ hash: allowance.hash });
1685
+ } catch (err) {
1686
+ throw errors.transactionStatusUnknown(allowance.hash, err, "approve");
1687
+ }
1223
1688
  if (receipt.status === "reverted") throw errors.transactionFailed(allowance.hash);
1689
+ let lastReadError;
1224
1690
  for (let attempt = 0; attempt < 15; attempt++) {
1225
- const visible = await client.publicClient.readContract({
1226
- address: token,
1227
- abi: ERC20_ALLOWANCE_ABI,
1228
- functionName: "allowance",
1229
- args: [owner, escrow]
1230
- });
1231
- if (visible >= amount) return;
1691
+ try {
1692
+ const visible = await client.publicClient.readContract({
1693
+ address: token,
1694
+ abi: ERC20_ALLOWANCE_ABI,
1695
+ functionName: "allowance",
1696
+ args: [owner, escrow]
1697
+ });
1698
+ if (visible >= amount) return;
1699
+ } catch (err) {
1700
+ lastReadError = err;
1701
+ }
1232
1702
  await sleep(1e3);
1233
1703
  }
1234
- throw errors.allowanceNotVisible(amount);
1704
+ throw errors.allowanceNotVisible(amount, lastReadError);
1235
1705
  }
1236
1706
  return {
1237
1707
  capabilities,
@@ -1242,8 +1712,10 @@ function createCashClient(options) {
1242
1712
  return quoteRelayToBaseUsdc(input, options.relay);
1243
1713
  },
1244
1714
  async executeSourceQuote(quote, opts) {
1715
+ if (!opts.signer.account) throw errors.signerRequired("executeSourceQuote");
1245
1716
  return executeRelayQuote(quote, opts.signer, {
1246
1717
  ...options.relay ? { relay: options.relay } : {},
1718
+ ...opts.recipient ? { recipient: opts.recipient } : {},
1247
1719
  ...opts.onProgress ? { onProgress: opts.onProgress } : {},
1248
1720
  ...opts.disableCapabilitiesCheck !== void 0 ? { disableCapabilitiesCheck: opts.disableCapabilitiesCheck } : {}
1249
1721
  });
@@ -1259,7 +1731,7 @@ function createCashClient(options) {
1259
1731
  });
1260
1732
  },
1261
1733
  async cashout(input, opts) {
1262
- const client = signingClient("cashout", opts);
1734
+ const client = await signingClient("cashout", opts);
1263
1735
  const owner = opts.signer.account.address;
1264
1736
  const payoutInput = validatePayout(input);
1265
1737
  let sourceResult;
@@ -1267,6 +1739,7 @@ function createCashClient(options) {
1267
1739
  if (input.source) {
1268
1740
  const sourceSigner = opts.sourceSigner ?? (input.source.chainId === BASE_CHAIN_ID ? opts.signer : void 0);
1269
1741
  if (!sourceSigner?.account) throw errors.signerRequired("source cashout");
1742
+ await assertWalletChainId(sourceSigner, input.source.chainId, "source cashout");
1270
1743
  if (input.source.recipient !== void 0 && input.source.recipient.toLowerCase() !== owner.toLowerCase()) {
1271
1744
  throw errors.sourceRecipientMismatch(input.source.recipient, owner);
1272
1745
  }
@@ -1284,20 +1757,23 @@ function createCashClient(options) {
1284
1757
  throw errors.amountBelowMinimum(relayQuote.outputAmount, MIN_CASHOUT_AMOUNT);
1285
1758
  }
1286
1759
  cashoutAmount = relayQuote.outputAmount;
1287
- const depositInput2 = { amount: cashoutAmount, ...payoutInput };
1760
+ const depositInput2 = validateDepositInput(cashoutAmount, input, payoutInput);
1288
1761
  const params2 = await buildDepositParams(client, depositInput2);
1289
1762
  const escrow2 = client.escrowV2Address ?? client.escrowAddress;
1290
1763
  await settleAllowance(client, params2.token, owner, escrow2, depositInput2.amount);
1291
1764
  const executed = await executeRelayQuote(relayQuote.raw, sourceSigner, {
1292
1765
  ...options.relay ? { relay: options.relay } : {},
1766
+ recipient: owner,
1293
1767
  ...opts.onSourceProgress ? { onProgress: opts.onSourceProgress } : {},
1294
1768
  ...opts.disableSourceCapabilitiesCheck !== void 0 ? { disableCapabilitiesCheck: opts.disableSourceCapabilitiesCheck } : {}
1295
1769
  });
1296
- sourceResult = {
1770
+ const routedSource = {
1297
1771
  amount: cashoutAmount,
1298
1772
  ...executed.requestId ? { requestId: executed.requestId } : {},
1299
- txHashes: executed.txHashes
1773
+ txHashes: executed.txHashes,
1774
+ ...executed.transactions ? { transactions: executed.transactions } : {}
1300
1775
  };
1776
+ sourceResult = routedSource;
1301
1777
  const attributedParams2 = { ...params2, txOverrides: attribution };
1302
1778
  const send2 = async () => {
1303
1779
  try {
@@ -1314,10 +1790,26 @@ function createCashClient(options) {
1314
1790
  try {
1315
1791
  hash2 = await send2();
1316
1792
  } catch (err) {
1317
- throw mapChainError("createDeposit", err);
1793
+ const mapped = mapChainError("createDeposit", err, {
1794
+ requiredAmount: depositInput2.amount
1795
+ });
1796
+ if (isKnownPreBroadcastFailure(err, mapped)) {
1797
+ throw errors.sourceRouteCompletedCashoutFailed(routedSource, mapped);
1798
+ }
1799
+ throw errors.sourceCashoutSubmissionUnknown(routedSource, owner, mapped);
1800
+ }
1801
+ let receipt2;
1802
+ try {
1803
+ receipt2 = await client.publicClient.waitForTransactionReceipt({ hash: hash2 });
1804
+ } catch (err) {
1805
+ throw errors.sourceCashoutStatusUnknown(routedSource, hash2, err);
1806
+ }
1807
+ if (receipt2.status === "reverted") {
1808
+ throw errors.sourceRouteCompletedCashoutFailed(
1809
+ routedSource,
1810
+ errors.transactionFailed(hash2)
1811
+ );
1318
1812
  }
1319
- const receipt2 = await client.publicClient.waitForTransactionReceipt({ hash: hash2 });
1320
- if (receipt2.status === "reverted") throw errors.transactionFailed(hash2);
1321
1813
  const abi2 = client.escrowV2Abi ?? client.escrowAbi;
1322
1814
  const resolved2 = resolveCashDepositId({ logs: receipt2.logs, abi: abi2 });
1323
1815
  if (!resolved2) throw errors.depositResolutionFailed(hash2);
@@ -1331,10 +1823,10 @@ function createCashClient(options) {
1331
1823
  escrowAddress: resolved2.escrowAddress,
1332
1824
  onchainDepositId: resolved2.onchainDepositId,
1333
1825
  order: order2,
1334
- source: sourceResult
1826
+ source: routedSource
1335
1827
  };
1336
1828
  }
1337
- const depositInput = validateInput(input);
1829
+ const depositInput = validateDepositInput(input.amount, input, payoutInput);
1338
1830
  const params = await buildDepositParams(client, depositInput);
1339
1831
  const escrow = client.escrowV2Address ?? client.escrowAddress;
1340
1832
  await settleAllowance(client, params.token, owner, escrow, depositInput.amount);
@@ -1354,9 +1846,23 @@ function createCashClient(options) {
1354
1846
  try {
1355
1847
  hash = await send();
1356
1848
  } catch (err) {
1357
- throw mapChainError("createDeposit", err);
1849
+ const mapped = mapChainError("createDeposit", err, {
1850
+ requiredAmount: depositInput.amount
1851
+ });
1852
+ if (isKnownPreBroadcastFailure(err, mapped)) throw mapped;
1853
+ throw errors.transactionSubmissionUnknown("cashout", err, {
1854
+ kind: "inspect-base-cashout-submission",
1855
+ amount: depositInput.amount.toString(),
1856
+ depositor: owner,
1857
+ txHashes: []
1858
+ });
1859
+ }
1860
+ let receipt;
1861
+ try {
1862
+ receipt = await client.publicClient.waitForTransactionReceipt({ hash });
1863
+ } catch (err) {
1864
+ throw errors.transactionStatusUnknown(hash, err, "cashout");
1358
1865
  }
1359
- const receipt = await client.publicClient.waitForTransactionReceipt({ hash });
1360
1866
  if (receipt.status === "reverted") throw errors.transactionFailed(hash);
1361
1867
  const abi = client.escrowV2Abi ?? client.escrowAbi;
1362
1868
  const resolved = resolveCashDepositId({ logs: receipt.logs, abi });
@@ -1376,7 +1882,7 @@ function createCashClient(options) {
1376
1882
  },
1377
1883
  async prepare(input) {
1378
1884
  if (input.source) throw errors.sourceRouteUnsupportedInPrepare();
1379
- const depositInput = validateInput(input);
1885
+ const depositInput = validateDepositInput(input.amount, input);
1380
1886
  const params = await buildDepositParams(readClient, depositInput);
1381
1887
  const { prepared } = await readClient.prepareCreateDeposit({
1382
1888
  ...params,
@@ -1415,13 +1921,46 @@ function createCashClient(options) {
1415
1921
  return fetchOrder(depositId);
1416
1922
  },
1417
1923
  async buyer(address) {
1418
- const intents = await readClient.indexer.getOwnerIntents(address, CASH_ORDER_STATUSES);
1924
+ let intents;
1925
+ try {
1926
+ intents = await readClient.indexer.getOwnerIntents(address, CASH_ORDER_STATUSES);
1927
+ } catch (err) {
1928
+ throw errors.indexerUnavailable("buyer profile", err);
1929
+ }
1419
1930
  return deriveBuyerProfile(address, intents);
1420
1931
  },
1421
1932
  async orders(owner, opts = {}) {
1422
1933
  const { inFlight = false, limit = 100 } = opts;
1423
- const deposits = await readClient.indexer.getDeposits({ depositor: owner }, { limit });
1424
- const derived = deposits.map((d) => deriveCashOrder(d.id, [], { ...depositOrderOptions(d), fillsIncluded: false })).filter((o) => o.totalAmount > 10000n).sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));
1934
+ let deposits;
1935
+ try {
1936
+ deposits = await readClient.indexer.getDepositsWithRelations(
1937
+ { depositor: owner },
1938
+ { limit }
1939
+ );
1940
+ } catch (err) {
1941
+ throw errors.indexerUnavailable("orders", err);
1942
+ }
1943
+ const catalog = sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment);
1944
+ const derived = deposits.flatMap((deposit) => {
1945
+ if (deposit.token.toLowerCase() !== BASE_USDC_ADDRESS.toLowerCase()) return [];
1946
+ const payouts = derivePayouts(
1947
+ deposit.paymentMethods ?? [],
1948
+ deposit.currencies ?? [],
1949
+ catalog
1950
+ );
1951
+ if (payouts.length !== 1 || !payouts.every((payout) => payout.pricing.marketRate && payout.pricing.spreadBps === 0)) {
1952
+ return [];
1953
+ }
1954
+ return [
1955
+ deriveCashOrder(deposit.id, [], {
1956
+ ...depositOrderOptions(deposit),
1957
+ payouts,
1958
+ // List rows carry no intent detail - a positive outstanding
1959
+ // amount is treated conservatively as a live lock.
1960
+ fillsIncluded: false
1961
+ })
1962
+ ];
1963
+ }).filter((o) => o.totalAmount >= MIN_CASHOUT_AMOUNT).sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));
1425
1964
  return inFlight ? derived.filter((o) => o.isInFlight) : derived;
1426
1965
  },
1427
1966
  async *watch(depositId, opts = {}) {
@@ -1451,7 +1990,7 @@ function createCashClient(options) {
1451
1990
  }
1452
1991
  },
1453
1992
  async withdraw(depositId, opts) {
1454
- const client = signingClient("withdraw", opts);
1993
+ const client = await signingClient("withdraw", opts);
1455
1994
  if (opts.amount !== void 0) {
1456
1995
  const { onchainDepositId: onchainDepositId2, escrowArg: escrowArg2 } = await partialWithdrawContext(
1457
1996
  depositId,
@@ -1549,7 +2088,7 @@ function createCashClient(options) {
1549
2088
  return { txs, steps };
1550
2089
  },
1551
2090
  async topUp(depositId, amount, opts) {
1552
- const client = signingClient("topUp", opts);
2091
+ const client = await signingClient("topUp", opts);
1553
2092
  const { onchainDepositId, escrowArg } = await topUpContext(depositId, amount);
1554
2093
  const owner = opts.signer.account.address;
1555
2094
  const escrow = escrowArg.escrowAddress ?? client.escrowV2Address ?? client.escrowAddress;
@@ -1604,6 +2143,39 @@ function createCashClient(options) {
1604
2143
  };
1605
2144
  }
1606
2145
  var bigintString = zod.z.string().regex(/^-?\d+$/, "expected a decimal bigint string");
2146
+ var nonNegativeBigintString = zod.z.string().regex(/^\d+$/, "expected a non-negative decimal bigint string");
2147
+ var relayTransactionJsonSchema = zod.z.object({
2148
+ hash: zod.z.string(),
2149
+ chainId: zod.z.number()
2150
+ });
2151
+ var relayTransactionsJsonSchema = zod.z.object({
2152
+ origin: zod.z.array(relayTransactionJsonSchema),
2153
+ destination: zod.z.array(relayTransactionJsonSchema)
2154
+ }).strict();
2155
+ var cashAssetJsonSchema = zod.z.object({
2156
+ chainId: zod.z.number(),
2157
+ address: zod.z.string(),
2158
+ symbol: zod.z.string(),
2159
+ decimals: zod.z.number(),
2160
+ name: zod.z.string().optional(),
2161
+ isNative: zod.z.boolean().optional()
2162
+ });
2163
+ var cashChainJsonSchema = zod.z.object({
2164
+ id: zod.z.number(),
2165
+ name: zod.z.string(),
2166
+ displayName: zod.z.string(),
2167
+ disabled: zod.z.boolean(),
2168
+ depositEnabled: zod.z.boolean(),
2169
+ blockProductionLagging: zod.z.boolean(),
2170
+ vmType: zod.z.string().optional(),
2171
+ tokens: zod.z.array(cashAssetJsonSchema)
2172
+ });
2173
+ var cashSourceCapabilitiesJsonSchema = zod.z.object({
2174
+ destination: cashAssetJsonSchema,
2175
+ chains: zod.z.array(cashChainJsonSchema),
2176
+ source: zod.z.literal("relay-sdk"),
2177
+ asOf: zod.z.number()
2178
+ });
1607
2179
  var cashOrderStateSchema = zod.z.enum([
1608
2180
  "awaiting-buyer",
1609
2181
  "matched",
@@ -1616,18 +2188,18 @@ var intentStatusSchema = zod.z.enum(["SIGNALED", "FULFILLED", "PRUNED", "MANUALL
1616
2188
  var cashFillJsonSchema = zod.z.object({
1617
2189
  intentHash: zod.z.string(),
1618
2190
  status: intentStatusSchema,
1619
- amount: bigintString,
2191
+ amount: nonNegativeBigintString,
1620
2192
  buyer: zod.z.string(),
1621
2193
  currency: zod.z.string().optional(),
1622
2194
  currencyHash: zod.z.string().optional(),
1623
2195
  rate: zod.z.number().optional(),
1624
- conversionRate: bigintString.optional(),
2196
+ conversionRate: nonNegativeBigintString.optional(),
1625
2197
  fiatOwed: zod.z.number().optional(),
1626
2198
  fiatPaid: zod.z.number().optional(),
1627
2199
  paidCurrency: zod.z.string().optional(),
1628
2200
  paymentId: zod.z.string().optional(),
1629
2201
  paidAt: zod.z.number().optional(),
1630
- releasedAmount: bigintString.optional(),
2202
+ releasedAmount: nonNegativeBigintString.optional(),
1631
2203
  fillLatencySeconds: zod.z.number().optional(),
1632
2204
  isExpired: zod.z.boolean().optional(),
1633
2205
  signaledAt: zod.z.number().optional(),
@@ -1666,10 +2238,10 @@ var cashOrderJsonSchema = zod.z.object({
1666
2238
  depositId: zod.z.string(),
1667
2239
  state: cashOrderStateSchema,
1668
2240
  fills: zod.z.array(cashFillJsonSchema),
1669
- totalAmount: bigintString,
1670
- filledAmount: bigintString,
1671
- pendingAmount: bigintString,
1672
- returnedAmount: bigintString,
2241
+ totalAmount: nonNegativeBigintString,
2242
+ filledAmount: nonNegativeBigintString,
2243
+ pendingAmount: nonNegativeBigintString,
2244
+ returnedAmount: nonNegativeBigintString,
1673
2245
  nextActions: zod.z.array(cashNextActionSchema),
1674
2246
  primaryIntentHash: zod.z.string().optional(),
1675
2247
  matchedAt: zod.z.number().optional(),
@@ -1684,7 +2256,7 @@ var cashOrderJsonSchema = zod.z.object({
1684
2256
  var cashEstimateJsonSchema = zod.z.object({
1685
2257
  kind: zod.z.literal("oracle-estimate"),
1686
2258
  currency: zod.z.string(),
1687
- amount: bigintString,
2259
+ amount: nonNegativeBigintString,
1688
2260
  rate: zod.z.number(),
1689
2261
  receiveAmount: zod.z.number(),
1690
2262
  asOf: zod.z.number(),
@@ -1700,7 +2272,7 @@ var cashEstimateJsonSchema = zod.z.object({
1700
2272
  name: zod.z.string().optional(),
1701
2273
  isNative: zod.z.boolean().optional()
1702
2274
  }),
1703
- inputAmount: bigintString,
2275
+ inputAmount: nonNegativeBigintString,
1704
2276
  relayQuote: zod.z.object({
1705
2277
  requestId: zod.z.string().optional(),
1706
2278
  source: zod.z.object({
@@ -1719,8 +2291,8 @@ var cashEstimateJsonSchema = zod.z.object({
1719
2291
  name: zod.z.string().optional(),
1720
2292
  isNative: zod.z.boolean().optional()
1721
2293
  }),
1722
- inputAmount: bigintString,
1723
- outputAmount: bigintString,
2294
+ inputAmount: nonNegativeBigintString,
2295
+ outputAmount: nonNegativeBigintString,
1724
2296
  rate: zod.z.number().optional(),
1725
2297
  timeEstimateSeconds: zod.z.number().optional(),
1726
2298
  fees: zod.z.unknown().optional(),
@@ -1728,7 +2300,7 @@ var cashEstimateJsonSchema = zod.z.object({
1728
2300
  zod.z.object({
1729
2301
  to: zod.z.string(),
1730
2302
  data: zod.z.string(),
1731
- value: bigintString,
2303
+ value: nonNegativeBigintString,
1732
2304
  chainId: zod.z.number()
1733
2305
  })
1734
2306
  ),
@@ -1743,9 +2315,39 @@ var cashEstimateJsonSchema = zod.z.object({
1743
2315
  var preparedTransactionJsonSchema = zod.z.object({
1744
2316
  to: zod.z.string(),
1745
2317
  data: zod.z.string(),
1746
- value: bigintString,
2318
+ value: nonNegativeBigintString,
1747
2319
  chainId: zod.z.number()
1748
2320
  });
2321
+ var relayQuoteJsonSchema = zod.z.object({
2322
+ requestId: zod.z.string().optional(),
2323
+ source: cashAssetJsonSchema,
2324
+ destination: cashAssetJsonSchema,
2325
+ inputAmount: nonNegativeBigintString,
2326
+ outputAmount: nonNegativeBigintString,
2327
+ rate: zod.z.number().optional(),
2328
+ timeEstimateSeconds: zod.z.number().optional(),
2329
+ fees: zod.z.unknown().optional(),
2330
+ txs: zod.z.array(preparedTransactionJsonSchema),
2331
+ raw: zod.z.unknown()
2332
+ });
2333
+ var relayStatusJsonSchema = zod.z.object({
2334
+ requestId: zod.z.string(),
2335
+ status: zod.z.enum(["refund", "waiting", "depositing", "failure", "pending", "submitted", "success"]),
2336
+ details: zod.z.string().optional(),
2337
+ inTxHashes: zod.z.array(zod.z.string()),
2338
+ txHashes: zod.z.array(zod.z.string()),
2339
+ updatedAt: zod.z.number().optional(),
2340
+ originChainId: zod.z.number().optional(),
2341
+ destinationChainId: zod.z.number().optional(),
2342
+ quoteCreatedAt: zod.z.number().optional(),
2343
+ raw: zod.z.unknown()
2344
+ });
2345
+ var relayExecutionResultJsonSchema = zod.z.object({
2346
+ requestId: zod.z.string().optional(),
2347
+ txHashes: zod.z.array(zod.z.string()),
2348
+ transactions: relayTransactionsJsonSchema.optional(),
2349
+ quote: zod.z.unknown()
2350
+ });
1749
2351
  var cashPreparedStepJsonSchema = zod.z.object({
1750
2352
  kind: zod.z.enum([
1751
2353
  "approve",
@@ -1761,12 +2363,13 @@ var cashoutResultJsonSchema = zod.z.object({
1761
2363
  depositId: zod.z.string(),
1762
2364
  txHash: zod.z.string(),
1763
2365
  escrowAddress: zod.z.string(),
1764
- onchainDepositId: bigintString,
2366
+ onchainDepositId: nonNegativeBigintString,
1765
2367
  order: cashOrderJsonSchema,
1766
2368
  source: zod.z.object({
1767
- amount: bigintString,
2369
+ amount: nonNegativeBigintString,
1768
2370
  requestId: zod.z.string().optional(),
1769
- txHashes: zod.z.array(zod.z.string())
2371
+ txHashes: zod.z.array(zod.z.string()),
2372
+ transactions: relayTransactionsJsonSchema.optional()
1770
2373
  }).optional()
1771
2374
  });
1772
2375
  var prepareResultJsonSchema = zod.z.object({
@@ -1796,39 +2399,7 @@ var cashCapabilitiesJsonSchema = zod.z.object({
1796
2399
  chainId: zod.z.number(),
1797
2400
  token: zod.z.object({ address: zod.z.string(), symbol: zod.z.literal("USDC"), decimals: zod.z.number() })
1798
2401
  }),
1799
- relay: zod.z.object({
1800
- destination: zod.z.object({
1801
- chainId: zod.z.number(),
1802
- address: zod.z.string(),
1803
- symbol: zod.z.string(),
1804
- decimals: zod.z.number(),
1805
- name: zod.z.string().optional(),
1806
- isNative: zod.z.boolean().optional()
1807
- }),
1808
- chains: zod.z.array(
1809
- zod.z.object({
1810
- id: zod.z.number(),
1811
- name: zod.z.string(),
1812
- displayName: zod.z.string(),
1813
- disabled: zod.z.boolean(),
1814
- depositEnabled: zod.z.boolean(),
1815
- blockProductionLagging: zod.z.boolean(),
1816
- vmType: zod.z.string().optional(),
1817
- tokens: zod.z.array(
1818
- zod.z.object({
1819
- chainId: zod.z.number(),
1820
- address: zod.z.string(),
1821
- symbol: zod.z.string(),
1822
- decimals: zod.z.number(),
1823
- name: zod.z.string().optional(),
1824
- isNative: zod.z.boolean().optional()
1825
- })
1826
- )
1827
- })
1828
- ),
1829
- source: zod.z.literal("relay-sdk"),
1830
- asOf: zod.z.number()
1831
- }).optional()
2402
+ relay: cashSourceCapabilitiesJsonSchema.optional()
1832
2403
  }),
1833
2404
  platforms: zod.z.array(
1834
2405
  zod.z.object({
@@ -1839,15 +2410,98 @@ var cashCapabilitiesJsonSchema = zod.z.object({
1839
2410
  })
1840
2411
  ),
1841
2412
  currencies: zod.z.array(zod.z.string()),
1842
- amount: zod.z.object({ min: bigintString, recommendedMin: bigintString, max: zod.z.null() }),
2413
+ amount: zod.z.object({
2414
+ min: nonNegativeBigintString,
2415
+ recommendedMin: nonNegativeBigintString,
2416
+ max: zod.z.null()
2417
+ }),
1843
2418
  pricing: zod.z.object({ kind: zod.z.literal("oracle-market-rate"), spreadBps: zod.z.literal(0) })
1844
2419
  });
2420
+ function defineCashErrorCodes(codes) {
2421
+ return codes;
2422
+ }
2423
+ var CASH_ERROR_CODES = defineCashErrorCodes([
2424
+ "ORACLE_UNSUPPORTED_CURRENCY",
2425
+ "ORACLE_READ_FAILED",
2426
+ "UNSUPPORTED_PLATFORM",
2427
+ "UNSUPPORTED_PLATFORM_CURRENCY",
2428
+ "AMOUNT_BELOW_MINIMUM",
2429
+ "INVALID_INTENT_AMOUNT_RANGE",
2430
+ "ACTIVE_INTENT_BLOCKS_WITHDRAWAL",
2431
+ "NOTHING_TO_WITHDRAW",
2432
+ "INSUFFICIENT_AVAILABLE_FUNDS",
2433
+ "INSUFFICIENT_TOKEN_BALANCE",
2434
+ "ORDER_NOT_ACTIVE",
2435
+ "INVALID_DEPOSIT_ID",
2436
+ "ESCROW_PAUSED",
2437
+ "INDEXER_LAG",
2438
+ "INDEXER_UNAVAILABLE",
2439
+ "ORDER_NOT_FOUND",
2440
+ "PAYEE_REGISTRATION_FAILED",
2441
+ "PAYEE_VERIFICATION_REQUIRED",
2442
+ "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE",
2443
+ "SOURCE_RECIPIENT_MISMATCH",
2444
+ "SOURCE_CAPABILITIES_FAILED",
2445
+ "SOURCE_QUOTE_FAILED",
2446
+ "SOURCE_EXECUTION_FAILED",
2447
+ "SOURCE_STATUS_FAILED",
2448
+ "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED",
2449
+ "SOURCE_CASHOUT_SUBMISSION_UNKNOWN",
2450
+ "SOURCE_CASHOUT_STATUS_UNKNOWN",
2451
+ "DEPOSIT_RESOLUTION_FAILED",
2452
+ "ALLOWANCE_NOT_VISIBLE",
2453
+ "SIGNER_REQUIRED",
2454
+ "SIGNER_CHAIN_MISMATCH",
2455
+ "SIGNER_CHAIN_UNAVAILABLE",
2456
+ "WATCH_TIMEOUT",
2457
+ "TRANSACTION_FAILED",
2458
+ "TRANSACTION_SUBMISSION_UNKNOWN",
2459
+ "TRANSACTION_STATUS_UNKNOWN"
2460
+ ]);
2461
+ var cashSourceRecoveryJsonShape = {
2462
+ amount: nonNegativeBigintString,
2463
+ requestId: zod.z.string().optional(),
2464
+ txHashes: zod.z.array(zod.z.string()),
2465
+ transactions: relayTransactionsJsonSchema.optional()
2466
+ };
2467
+ var cashErrorRecoveryJsonSchema = zod.z.discriminatedUnion("kind", [
2468
+ zod.z.object({
2469
+ ...cashSourceRecoveryJsonShape,
2470
+ kind: zod.z.literal("retry-base-usdc-cashout")
2471
+ }).strict(),
2472
+ zod.z.object({
2473
+ ...cashSourceRecoveryJsonShape,
2474
+ kind: zod.z.literal("inspect-base-cashout-transaction"),
2475
+ depositTxHash: zod.z.string()
2476
+ }).strict(),
2477
+ zod.z.object({
2478
+ ...cashSourceRecoveryJsonShape,
2479
+ kind: zod.z.literal("inspect-base-cashout-submission"),
2480
+ depositor: zod.z.string()
2481
+ }).strict(),
2482
+ zod.z.object({
2483
+ kind: zod.z.literal("inspect-relay-route"),
2484
+ requestId: zod.z.string().optional(),
2485
+ txHashes: zod.z.array(zod.z.string()),
2486
+ transactions: relayTransactionsJsonSchema.optional()
2487
+ }).strict(),
2488
+ zod.z.object({
2489
+ kind: zod.z.literal("inspect-base-operation-submission"),
2490
+ operation: zod.z.string()
2491
+ }).strict(),
2492
+ zod.z.object({
2493
+ kind: zod.z.literal("inspect-base-transaction"),
2494
+ transactionHash: zod.z.string(),
2495
+ operation: zod.z.string()
2496
+ }).strict()
2497
+ ]);
1845
2498
  var cashErrorJsonSchema = zod.z.object({
1846
- code: zod.z.string(),
2499
+ code: zod.z.enum(CASH_ERROR_CODES),
1847
2500
  message: zod.z.string(),
1848
2501
  retryable: zod.z.boolean(),
1849
- remediation: zod.z.string()
1850
- });
2502
+ remediation: zod.z.string(),
2503
+ recovery: cashErrorRecoveryJsonSchema.optional()
2504
+ }).strict();
1851
2505
 
1852
2506
  // src/codecs/json.ts
1853
2507
  function omitUndefined(obj) {
@@ -1878,35 +2532,38 @@ function fillToJson(fill) {
1878
2532
  });
1879
2533
  }
1880
2534
  function fillFromJson(json) {
2535
+ const parsed = cashFillJsonSchema.parse(json);
1881
2536
  return omitUndefined({
1882
- ...json,
1883
- amount: BigInt(json.amount),
1884
- conversionRate: json.conversionRate !== void 0 ? BigInt(json.conversionRate) : void 0,
1885
- releasedAmount: json.releasedAmount !== void 0 ? BigInt(json.releasedAmount) : void 0
2537
+ ...parsed,
2538
+ amount: BigInt(parsed.amount),
2539
+ conversionRate: parsed.conversionRate !== void 0 ? BigInt(parsed.conversionRate) : void 0,
2540
+ releasedAmount: parsed.releasedAmount !== void 0 ? BigInt(parsed.releasedAmount) : void 0
1886
2541
  });
1887
2542
  }
1888
2543
  function orderToJson(order) {
1889
- return omitUndefined({
1890
- depositId: order.depositId,
1891
- state: order.state,
1892
- fills: order.fills.map(fillToJson),
1893
- totalAmount: order.totalAmount.toString(),
1894
- filledAmount: order.filledAmount.toString(),
1895
- pendingAmount: order.pendingAmount.toString(),
1896
- returnedAmount: order.returnedAmount.toString(),
1897
- nextActions: order.nextActions,
1898
- primaryIntentHash: order.primaryIntentHash,
1899
- matchedAt: order.matchedAt,
1900
- deliveredAt: order.deliveredAt,
1901
- updatedAt: order.updatedAt,
1902
- intentCount: order.intentCount,
1903
- payouts: order.payouts?.map(
1904
- (p) => omitUndefined({ ...p, pricing: omitUndefined({ ...p.pricing }) })
1905
- ),
1906
- successRateBps: order.successRateBps,
1907
- isInFlight: order.isInFlight,
1908
- withdrawn: order.withdrawn
1909
- });
2544
+ return cashOrderJsonSchema.parse(
2545
+ omitUndefined({
2546
+ depositId: order.depositId,
2547
+ state: order.state,
2548
+ fills: order.fills.map(fillToJson),
2549
+ totalAmount: order.totalAmount.toString(),
2550
+ filledAmount: order.filledAmount.toString(),
2551
+ pendingAmount: order.pendingAmount.toString(),
2552
+ returnedAmount: order.returnedAmount.toString(),
2553
+ nextActions: order.nextActions,
2554
+ primaryIntentHash: order.primaryIntentHash,
2555
+ matchedAt: order.matchedAt,
2556
+ deliveredAt: order.deliveredAt,
2557
+ updatedAt: order.updatedAt,
2558
+ intentCount: order.intentCount,
2559
+ payouts: order.payouts?.map(
2560
+ (p) => omitUndefined({ ...p, pricing: omitUndefined({ ...p.pricing }) })
2561
+ ),
2562
+ successRateBps: order.successRateBps,
2563
+ isInFlight: order.isInFlight,
2564
+ withdrawn: order.withdrawn
2565
+ })
2566
+ );
1910
2567
  }
1911
2568
  function orderFromJson(json) {
1912
2569
  const parsed = cashOrderJsonSchema.parse(json);
@@ -1932,6 +2589,7 @@ function estimateToJson(estimate) {
1932
2589
  inputAmount: estimate.source.relayQuote.inputAmount.toString(),
1933
2590
  outputAmount: estimate.source.relayQuote.outputAmount.toString(),
1934
2591
  txs: estimate.source.relayQuote.txs.map(preparedTxToJson),
2592
+ ...estimate.source.relayQuote.fees !== void 0 ? { fees: sanitizeRelayValue(estimate.source.relayQuote.fees) } : {},
1935
2593
  raw: sanitizeRelayQuoteRaw(estimate.source.relayQuote.raw)
1936
2594
  }
1937
2595
  } : void 0
@@ -1950,11 +2608,108 @@ function estimateFromJson(json) {
1950
2608
  ...parsed.source.relayQuote,
1951
2609
  inputAmount: BigInt(parsed.source.relayQuote.inputAmount),
1952
2610
  outputAmount: BigInt(parsed.source.relayQuote.outputAmount),
1953
- txs: parsed.source.relayQuote.txs.map(preparedTxFromJson)
2611
+ txs: parsed.source.relayQuote.txs.map(preparedTxFromJson),
2612
+ ...parsed.source.relayQuote.fees !== void 0 ? { fees: restoreRelayValue(parsed.source.relayQuote.fees) } : {},
2613
+ raw: restoreRelayQuoteRaw(parsed.source.relayQuote.raw)
1954
2614
  }
1955
2615
  } : void 0
1956
2616
  });
1957
2617
  }
2618
+ function cashAssetFromJson(asset) {
2619
+ return {
2620
+ chainId: asset.chainId,
2621
+ address: asset.address,
2622
+ symbol: asset.symbol,
2623
+ decimals: asset.decimals,
2624
+ ...asset.name !== void 0 ? { name: asset.name } : {},
2625
+ ...asset.isNative !== void 0 ? { isNative: asset.isNative } : {}
2626
+ };
2627
+ }
2628
+ function relayQuoteToJson(quote) {
2629
+ return relayQuoteJsonSchema.parse({
2630
+ ...quote.requestId !== void 0 ? { requestId: quote.requestId } : {},
2631
+ source: quote.source,
2632
+ destination: quote.destination,
2633
+ inputAmount: quote.inputAmount.toString(),
2634
+ outputAmount: quote.outputAmount.toString(),
2635
+ ...quote.rate !== void 0 ? { rate: quote.rate } : {},
2636
+ ...quote.timeEstimateSeconds !== void 0 ? { timeEstimateSeconds: quote.timeEstimateSeconds } : {},
2637
+ ...quote.fees !== void 0 ? { fees: sanitizeRelayValue(quote.fees) } : {},
2638
+ txs: quote.txs.map(preparedTxToJson),
2639
+ raw: sanitizeRelayQuoteRaw(quote.raw)
2640
+ });
2641
+ }
2642
+ function relayQuoteFromJson(json) {
2643
+ const parsed = relayQuoteJsonSchema.parse(json);
2644
+ return {
2645
+ ...parsed.requestId !== void 0 ? { requestId: parsed.requestId } : {},
2646
+ source: cashAssetFromJson(parsed.source),
2647
+ destination: cashAssetFromJson(parsed.destination),
2648
+ inputAmount: BigInt(parsed.inputAmount),
2649
+ outputAmount: BigInt(parsed.outputAmount),
2650
+ ...parsed.rate !== void 0 ? { rate: parsed.rate } : {},
2651
+ ...parsed.timeEstimateSeconds !== void 0 ? { timeEstimateSeconds: parsed.timeEstimateSeconds } : {},
2652
+ ...parsed.fees !== void 0 ? { fees: restoreRelayValue(parsed.fees) } : {},
2653
+ txs: parsed.txs.map(preparedTxFromJson),
2654
+ raw: restoreRelayQuoteRaw(parsed.raw)
2655
+ };
2656
+ }
2657
+ function sourceCapabilitiesToJson(capabilities) {
2658
+ return cashSourceCapabilitiesJsonSchema.parse(capabilities);
2659
+ }
2660
+ function sourceCapabilitiesFromJson(json) {
2661
+ const parsed = cashSourceCapabilitiesJsonSchema.parse(json);
2662
+ return {
2663
+ destination: cashAssetFromJson(parsed.destination),
2664
+ chains: parsed.chains.map((chain) => ({
2665
+ id: chain.id,
2666
+ name: chain.name,
2667
+ displayName: chain.displayName,
2668
+ disabled: chain.disabled,
2669
+ depositEnabled: chain.depositEnabled,
2670
+ blockProductionLagging: chain.blockProductionLagging,
2671
+ ...chain.vmType !== void 0 ? { vmType: chain.vmType } : {},
2672
+ tokens: chain.tokens.map(cashAssetFromJson)
2673
+ })),
2674
+ source: parsed.source,
2675
+ asOf: parsed.asOf
2676
+ };
2677
+ }
2678
+ function relayStatusToJson(status) {
2679
+ return relayStatusJsonSchema.parse({ ...status, raw: sanitizeRelayValue(status.raw) });
2680
+ }
2681
+ function relayStatusFromJson(json) {
2682
+ const parsed = relayStatusJsonSchema.parse(json);
2683
+ return {
2684
+ requestId: parsed.requestId,
2685
+ status: parsed.status,
2686
+ ...parsed.details !== void 0 ? { details: parsed.details } : {},
2687
+ inTxHashes: parsed.inTxHashes,
2688
+ txHashes: parsed.txHashes,
2689
+ ...parsed.updatedAt !== void 0 ? { updatedAt: parsed.updatedAt } : {},
2690
+ ...parsed.originChainId !== void 0 ? { originChainId: parsed.originChainId } : {},
2691
+ ...parsed.destinationChainId !== void 0 ? { destinationChainId: parsed.destinationChainId } : {},
2692
+ ...parsed.quoteCreatedAt !== void 0 ? { quoteCreatedAt: parsed.quoteCreatedAt } : {},
2693
+ raw: restoreRelayValue(parsed.raw)
2694
+ };
2695
+ }
2696
+ function relayExecutionResultToJson(result) {
2697
+ return relayExecutionResultJsonSchema.parse({
2698
+ ...result.requestId !== void 0 ? { requestId: result.requestId } : {},
2699
+ txHashes: result.txHashes,
2700
+ ...result.transactions !== void 0 ? { transactions: result.transactions } : {},
2701
+ quote: sanitizeRelayQuoteRaw(result.quote)
2702
+ });
2703
+ }
2704
+ function relayExecutionResultFromJson(json) {
2705
+ const parsed = relayExecutionResultJsonSchema.parse(json);
2706
+ return {
2707
+ ...parsed.requestId !== void 0 ? { requestId: parsed.requestId } : {},
2708
+ txHashes: parsed.txHashes,
2709
+ ...parsed.transactions !== void 0 ? { transactions: parsed.transactions } : {},
2710
+ quote: restoreRelayQuoteRaw(parsed.quote)
2711
+ };
2712
+ }
1958
2713
  function preparedTxToJson(tx) {
1959
2714
  return { to: tx.to, data: tx.data, value: tx.value.toString(), chainId: tx.chainId };
1960
2715
  }
@@ -2073,6 +2828,69 @@ function capabilitiesFromJson(json) {
2073
2828
  }
2074
2829
  };
2075
2830
  }
2831
+ function cashErrorToJson(error) {
2832
+ return cashErrorJsonSchema.parse({
2833
+ code: error.code,
2834
+ message: error.message,
2835
+ retryable: error.retryable,
2836
+ remediation: error.remediation,
2837
+ ...error.recovery ? { recovery: error.recovery } : {}
2838
+ });
2839
+ }
2840
+ function cashErrorFromJson(json) {
2841
+ const parsed = cashErrorJsonSchema.parse(json);
2842
+ let recovery;
2843
+ if (parsed.recovery) {
2844
+ if (parsed.recovery.kind === "inspect-base-transaction") {
2845
+ recovery = {
2846
+ kind: parsed.recovery.kind,
2847
+ transactionHash: parsed.recovery.transactionHash,
2848
+ operation: parsed.recovery.operation
2849
+ };
2850
+ } else if (parsed.recovery.kind === "inspect-base-operation-submission") {
2851
+ recovery = {
2852
+ kind: parsed.recovery.kind,
2853
+ operation: parsed.recovery.operation
2854
+ };
2855
+ } else if (parsed.recovery.kind === "inspect-relay-route") {
2856
+ recovery = {
2857
+ kind: parsed.recovery.kind,
2858
+ txHashes: parsed.recovery.txHashes,
2859
+ ...parsed.recovery.requestId !== void 0 ? { requestId: parsed.recovery.requestId } : {},
2860
+ ...parsed.recovery.transactions !== void 0 ? { transactions: parsed.recovery.transactions } : {}
2861
+ };
2862
+ } else {
2863
+ const common = {
2864
+ amount: parsed.recovery.amount,
2865
+ txHashes: parsed.recovery.txHashes,
2866
+ ...parsed.recovery.requestId !== void 0 ? { requestId: parsed.recovery.requestId } : {},
2867
+ ...parsed.recovery.transactions !== void 0 ? { transactions: parsed.recovery.transactions } : {}
2868
+ };
2869
+ if (parsed.recovery.kind === "retry-base-usdc-cashout") {
2870
+ recovery = { ...common, kind: parsed.recovery.kind };
2871
+ } else if (parsed.recovery.kind === "inspect-base-cashout-submission") {
2872
+ recovery = {
2873
+ ...common,
2874
+ kind: parsed.recovery.kind,
2875
+ depositor: parsed.recovery.depositor
2876
+ };
2877
+ } else {
2878
+ recovery = {
2879
+ ...common,
2880
+ kind: parsed.recovery.kind,
2881
+ depositTxHash: parsed.recovery.depositTxHash
2882
+ };
2883
+ }
2884
+ }
2885
+ }
2886
+ return new CashError({
2887
+ code: parsed.code,
2888
+ message: parsed.message,
2889
+ retryable: parsed.retryable,
2890
+ remediation: parsed.remediation,
2891
+ ...recovery ? { recovery } : {}
2892
+ });
2893
+ }
2076
2894
 
2077
2895
  exports.BASE_CHAIN_ID = BASE_CHAIN_ID;
2078
2896
  exports.BASE_USDC_ADDRESS = BASE_USDC_ADDRESS;
@@ -2095,9 +2913,14 @@ exports.buyerProfileFromJson = buyerProfileFromJson;
2095
2913
  exports.buyerProfileToJson = buyerProfileToJson;
2096
2914
  exports.capabilitiesFromJson = capabilitiesFromJson;
2097
2915
  exports.capabilitiesToJson = capabilitiesToJson;
2916
+ exports.cashAssetJsonSchema = cashAssetJsonSchema;
2098
2917
  exports.cashBuyerProfileJsonSchema = cashBuyerProfileJsonSchema;
2099
2918
  exports.cashCapabilitiesJsonSchema = cashCapabilitiesJsonSchema;
2919
+ exports.cashChainJsonSchema = cashChainJsonSchema;
2920
+ exports.cashErrorFromJson = cashErrorFromJson;
2100
2921
  exports.cashErrorJsonSchema = cashErrorJsonSchema;
2922
+ exports.cashErrorRecoveryJsonSchema = cashErrorRecoveryJsonSchema;
2923
+ exports.cashErrorToJson = cashErrorToJson;
2101
2924
  exports.cashEstimateJsonSchema = cashEstimateJsonSchema;
2102
2925
  exports.cashFillJsonSchema = cashFillJsonSchema;
2103
2926
  exports.cashNextActionSchema = cashNextActionSchema;
@@ -2106,6 +2929,7 @@ exports.cashOrderStateSchema = cashOrderStateSchema;
2106
2929
  exports.cashPayoutInfoJsonSchema = cashPayoutInfoJsonSchema;
2107
2930
  exports.cashPayoutPricingJsonSchema = cashPayoutPricingJsonSchema;
2108
2931
  exports.cashPreparedStepJsonSchema = cashPreparedStepJsonSchema;
2932
+ exports.cashSourceCapabilitiesJsonSchema = cashSourceCapabilitiesJsonSchema;
2109
2933
  exports.cashoutResultFromJson = cashoutResultFromJson;
2110
2934
  exports.cashoutResultJsonSchema = cashoutResultJsonSchema;
2111
2935
  exports.cashoutResultToJson = cashoutResultToJson;
@@ -2127,6 +2951,7 @@ exports.intentStatusSchema = intentStatusSchema;
2127
2951
  exports.isCashError = isCashError;
2128
2952
  exports.isFillLive = isFillLive;
2129
2953
  exports.isMarketRateSupported = isMarketRateSupported;
2954
+ exports.nonNegativeBigintString = nonNegativeBigintString;
2130
2955
  exports.orderFromJson = orderFromJson;
2131
2956
  exports.orderToJson = orderToJson;
2132
2957
  exports.parseCompositeDepositId = parseCompositeDepositId;
@@ -2140,7 +2965,20 @@ exports.preparedTransactionJsonSchema = preparedTransactionJsonSchema;
2140
2965
  exports.preparedTxFromJson = preparedTxFromJson;
2141
2966
  exports.preparedTxToJson = preparedTxToJson;
2142
2967
  exports.rateToNumber = rateToNumber;
2968
+ exports.relayExecutionResultFromJson = relayExecutionResultFromJson;
2969
+ exports.relayExecutionResultJsonSchema = relayExecutionResultJsonSchema;
2970
+ exports.relayExecutionResultToJson = relayExecutionResultToJson;
2971
+ exports.relayQuoteFromJson = relayQuoteFromJson;
2972
+ exports.relayQuoteJsonSchema = relayQuoteJsonSchema;
2973
+ exports.relayQuoteToJson = relayQuoteToJson;
2974
+ exports.relayStatusFromJson = relayStatusFromJson;
2975
+ exports.relayStatusJsonSchema = relayStatusJsonSchema;
2976
+ exports.relayStatusToJson = relayStatusToJson;
2977
+ exports.relayTransactionJsonSchema = relayTransactionJsonSchema;
2978
+ exports.relayTransactionsJsonSchema = relayTransactionsJsonSchema;
2143
2979
  exports.resolveCashDepositId = resolveCashDepositId;
2980
+ exports.sourceCapabilitiesFromJson = sourceCapabilitiesFromJson;
2981
+ exports.sourceCapabilitiesToJson = sourceCapabilitiesToJson;
2144
2982
  exports.topUpResultFromJson = topUpResultFromJson;
2145
2983
  exports.topUpResultJsonSchema = topUpResultJsonSchema;
2146
2984
  exports.topUpResultToJson = topUpResultToJson;
@@ -2149,5 +2987,3 @@ exports.withExplain = withExplain;
2149
2987
  exports.withdrawResultFromJson = withdrawResultFromJson;
2150
2988
  exports.withdrawResultJsonSchema = withdrawResultJsonSchema;
2151
2989
  exports.withdrawResultToJson = withdrawResultToJson;
2152
- //# sourceMappingURL=index.cjs.map
2153
- //# sourceMappingURL=index.cjs.map