@zkp2p/cash 0.1.2 → 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,18 +791,22 @@ 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
  }
618
- var ETA_WINDOW_DAYS = 7;
806
+ var ETA_WINDOW_DAYS = 30;
619
807
  var ETA_WINDOW_SECONDS = ETA_WINDOW_DAYS * 24 * 60 * 60;
620
- var ETA_SAMPLE_LIMIT = 250;
808
+ var ETA_PAGE_LIMIT = 250;
809
+ var ETA_MAX_DEPOSIT_SCAN = 2e3;
621
810
  var FULFILLED = /* @__PURE__ */ new Set(["FULFILLED", "MANUALLY_RELEASED"]);
622
811
  function toUnixSeconds2(value) {
623
812
  if (value === null || value === void 0 || value === "") return void 0;
@@ -652,19 +841,27 @@ function matchesPayout(deposit, environment, platform, currency) {
652
841
  deposit.currencies ?? [],
653
842
  sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment)
654
843
  );
655
- if (payouts.length === 0) return true;
656
844
  return payouts.some(
657
- (payout) => (platform === void 0 || payout.platform === platform) && (currency === void 0 || payout.currency === currency)
845
+ (payout) => payout.pricing.marketRate && payout.pricing.spreadBps === 0 && (platform === void 0 || payout.platform === platform) && (currency === void 0 || payout.currency === currency)
658
846
  );
659
847
  }
660
848
  async function readFillEta(client, input) {
661
849
  const now = Math.floor(Date.now() / 1e3);
662
850
  const windowStart = now - ETA_WINDOW_SECONDS;
663
- const deposits = await client.indexer.getDepositsWithRelations(
664
- { chainId: BASE_CHAIN_ID },
665
- { limit: ETA_SAMPLE_LIMIT, orderBy: "updatedAt", orderDirection: "desc" },
666
- { includeIntents: true, intentStatuses: ["FULFILLED", "MANUALLY_RELEASED"] }
667
- );
851
+ const deposits = [];
852
+ for (let offset = 0; offset < ETA_MAX_DEPOSIT_SCAN; offset += ETA_PAGE_LIMIT) {
853
+ const page = await client.indexer.getDepositsWithRelations(
854
+ { chainId: BASE_CHAIN_ID },
855
+ { limit: ETA_PAGE_LIMIT, offset, orderBy: "timestamp", orderDirection: "desc" },
856
+ { includeIntents: true, intentStatuses: ["FULFILLED", "MANUALLY_RELEASED"] }
857
+ );
858
+ deposits.push(...page);
859
+ if (page.length < ETA_PAGE_LIMIT) break;
860
+ const oldestCreatedAt = Math.min(
861
+ ...page.map((deposit) => toUnixSeconds2(deposit.createdAt ?? deposit.timestamp) ?? Infinity)
862
+ );
863
+ if (oldestCreatedAt < windowStart) break;
864
+ }
668
865
  const firstFillLatencies = [];
669
866
  for (const deposit of deposits) {
670
867
  const createdAt = toUnixSeconds2(deposit.createdAt ?? deposit.timestamp);
@@ -768,20 +965,175 @@ function normalizeChain(chain) {
768
965
  function isSupportedEvmChain(chain) {
769
966
  return chain.vmType === void 0 || chain.vmType === "evm";
770
967
  }
968
+ function isExecutableSourceChain(chain) {
969
+ return isSupportedEvmChain(chain) && !chain.disabled && chain.depositEnabled && !chain.blockProductionLagging;
970
+ }
771
971
  function quoteRequestId(quote) {
772
972
  return quote.steps.map((step) => step.requestId).find((id) => id !== void 0);
773
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
+ }
774
1000
  function quoteSourceChainId(quote) {
775
1001
  const details = asRecord(quote.details);
776
1002
  const currencyIn = asRecord(details.currencyIn);
777
1003
  const sourceCurrency = asRecord(currencyIn.currency);
778
1004
  return asNumber(sourceCurrency.chainId);
779
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
+ }
780
1132
  function sanitizeRelayQuoteRaw(quote) {
781
- if (!quote.request) return quote;
782
- const request = { ...quote.request };
783
- delete request.headers;
784
- return { ...quote, request };
1133
+ return sanitizeRelayValue(quote);
1134
+ }
1135
+ function restoreRelayQuoteRaw(value) {
1136
+ return restoreRelayValue(value);
785
1137
  }
786
1138
  async function resolveRelayChains(options, client, config = {}) {
787
1139
  const preferInjectedClientChains = config.preferInjectedClientChains ?? true;
@@ -795,19 +1147,38 @@ function relayQuoteFromExecute(input, quote) {
795
1147
  const currencyOut = asRecord(details.currencyOut);
796
1148
  const sourceCurrency = asRecord(currencyIn.currency);
797
1149
  const destinationCurrency = asRecord(currencyOut.currency);
798
- const source = normalizeToken(input.source.chainId, sourceCurrency) ?? {
799
- chainId: input.source.chainId,
800
- address: input.source.currency,
801
- symbol: "TOKEN",
802
- decimals: 0
803
- };
804
- 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");
805
1173
  const txs = quote.steps.flatMap(
806
1174
  (step) => step.items.map((item) => normalizeTx(item.data, input.source.chainId)).filter((tx) => tx !== null)
807
1175
  );
808
- const outputAmount = BigInt(
809
- String(currencyOut.minimumAmount ?? currencyOut.amount ?? input.amount.toString())
810
- );
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");
811
1182
  const requestId = quoteRequestId(quote);
812
1183
  const rate = asNumber(details.rate);
813
1184
  const timeEstimateSeconds = asNumber(details.timeEstimate);
@@ -815,92 +1186,135 @@ function relayQuoteFromExecute(input, quote) {
815
1186
  ...requestId ? { requestId } : {},
816
1187
  source,
817
1188
  destination,
818
- inputAmount: BigInt(String(currencyIn.amount ?? input.amount.toString())),
1189
+ inputAmount: BigInt(String(currencyIn.amount)),
819
1190
  outputAmount,
820
1191
  ...rate !== void 0 ? { rate } : {},
821
1192
  ...timeEstimateSeconds !== void 0 ? { timeEstimateSeconds } : {},
822
1193
  ...quote.fees !== void 0 ? { fees: quote.fees } : {},
823
1194
  txs,
824
- raw: sanitizeRelayQuoteRaw(quote)
1195
+ raw: redactRelayQuoteRaw(quote)
825
1196
  };
826
1197
  }
827
1198
  async function readRelaySourceCapabilities(options = {}) {
828
- const client = relayClient(options);
829
- const chains = await resolveRelayChains(options, client);
830
- return {
831
- destination: BASE_USDC_ASSET,
832
- chains: chains.map(normalizeChain).filter((chain) => chain.tokens.length > 0 && isSupportedEvmChain(chain)).sort((a, b) => a.displayName.localeCompare(b.displayName)),
833
- source: "relay-sdk",
834
- asOf: Math.floor(Date.now() / 1e3)
835
- };
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
+ }
836
1212
  }
837
1213
  async function quoteRelayToBaseUsdc(input, options = {}) {
838
- const client = relayClient(options);
839
- const quote = await client.actions.getQuote(
840
- {
841
- chainId: input.source.chainId,
842
- currency: input.source.currency,
843
- toChainId: BASE_CHAIN_ID,
844
- toCurrency: BASE_USDC_ADDRESS,
845
- user: input.user,
846
- recipient: input.recipient ?? input.user,
847
- amount: input.amount.toString(),
848
- tradeType: input.tradeType ?? "EXACT_INPUT"
849
- },
850
- false
851
- );
852
- 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
+ }
853
1235
  }
854
1236
  async function executeRelayQuote(quote, wallet, options = {}) {
855
- const client = relayClient(options.relay);
856
- const sourceChainId = quoteSourceChainId(quote);
857
- if (sourceChainId !== void 0 && !(client.chains ?? []).some((chain) => chain.id === sourceChainId)) {
858
- await resolveRelayChains(options.relay ?? {}, client, { preferInjectedClientChains: false });
859
- }
860
- const { data } = await client.actions.execute({
861
- quote,
862
- wallet,
863
- ...options.onProgress ? { onProgress: options.onProgress } : {},
864
- ...options.disableCapabilitiesCheck !== void 0 ? { disableCapabilitiesCheck: options.disableCapabilitiesCheck } : {}
865
- });
866
- const requestId = quoteRequestId(data);
867
- return {
868
- ...requestId ? { requestId } : {},
869
- txHashes: data.steps.flatMap(
870
- (step) => step.items.flatMap((item) => (item.txHashes ?? []).map((tx) => tx.txHash))
871
- ),
872
- quote: data
873
- };
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
+ }
874
1283
  }
875
1284
  async function readRelayStatus(requestId, options = {}) {
876
- const client = relayClient(options);
877
- const response = await client.utils.request({
878
- url: `${client.baseApiUrl}/intents/status/v3`,
879
- method: "get",
880
- params: { requestId }
881
- });
882
- const root = asRecord(response.data);
883
- const status = asString(root.status);
884
- if (status !== "refund" && status !== "waiting" && status !== "depositing" && status !== "failure" && status !== "pending" && status !== "submitted" && status !== "success") {
885
- throw new Error(`Relay returned unknown status: ${String(root.status)}`);
886
- }
887
- const details = asString(root.details);
888
- const updatedAt = asNumber(root.updatedAt);
889
- const originChainId = asNumber(root.originChainId);
890
- const destinationChainId = asNumber(root.destinationChainId);
891
- const quoteCreatedAt = asNumber(root.quoteCreatedAt);
892
- return {
893
- requestId,
894
- status,
895
- ...details ? { details } : {},
896
- inTxHashes: Array.isArray(root.inTxHashes) ? root.inTxHashes.map(String) : [],
897
- txHashes: Array.isArray(root.txHashes) ? root.txHashes.map(String) : [],
898
- ...updatedAt !== void 0 ? { updatedAt } : {},
899
- ...originChainId !== void 0 ? { originChainId } : {},
900
- ...destinationChainId !== void 0 ? { destinationChainId } : {},
901
- ...quoteCreatedAt !== void 0 ? { quoteCreatedAt } : {},
902
- raw: response.data
903
- };
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
+ }
904
1318
  }
905
1319
 
906
1320
  // src/client/estimate.ts
@@ -947,11 +1361,16 @@ async function readEstimate(publicClient, input, context = {}) {
947
1361
  if (!feedConfig || feedConfig.feed.toLowerCase() === ZERO_ADDRESS) {
948
1362
  rate = 1;
949
1363
  } else {
950
- const result = await publicClient.readContract({
951
- address: feedConfig.feed,
952
- abi: CHAINLINK_LATEST_ROUND_ABI,
953
- functionName: "latestRoundData"
954
- });
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
+ }
955
1374
  const answer = Number(result[1]);
956
1375
  const price = answer / 10 ** feedConfig.decimals;
957
1376
  if (!Number.isFinite(price) || price <= 0) {
@@ -997,6 +1416,7 @@ async function readEstimate(publicClient, input, context = {}) {
997
1416
  var DEFAULT_RPC_URL = "https://mainnet.base.org";
998
1417
  var CASH_ATTRIBUTION_CODE = "peer-cash";
999
1418
  var DEFAULT_CURATOR_URLS = {
1419
+ preproduction: "https://api-preprod.zkp2p.xyz",
1000
1420
  staging: "https://api-staging.zkp2p.xyz"
1001
1421
  };
1002
1422
  var ERC20_APPROVE_ABI = viem.parseAbi([
@@ -1031,12 +1451,29 @@ async function submitAndConfirm(client, verb, send) {
1031
1451
  try {
1032
1452
  hash = await send();
1033
1453
  } catch (err) {
1034
- 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);
1035
1466
  }
1036
- const receipt = await client.publicClient.waitForTransactionReceipt({ hash });
1037
1467
  if (receipt.status === "reverted") throw errors.transactionFailed(hash);
1038
1468
  return hash;
1039
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
+ }
1040
1477
  function depositOrderOptions(deposit) {
1041
1478
  const remaining = toBigIntOrUndefined(deposit.remainingDeposits);
1042
1479
  const outstanding = toBigIntOrUndefined(deposit.outstandingIntentAmount);
@@ -1076,9 +1513,10 @@ function createCashClient(options) {
1076
1513
  }
1077
1514
  const readClient = buildSdkClient(viem.createWalletClient({ chain: chains.base, transport }));
1078
1515
  const signingClients = /* @__PURE__ */ new WeakMap();
1079
- function signingClient(verb, opts) {
1516
+ async function signingClient(verb, opts) {
1080
1517
  const signer = opts?.signer;
1081
1518
  if (!signer?.account) throw errors.signerRequired(verb);
1519
+ await assertWalletChainId(signer, BASE_CHAIN_ID, verb);
1082
1520
  let client = signingClients.get(signer);
1083
1521
  if (!client) {
1084
1522
  client = buildSdkClient(signer);
@@ -1088,13 +1526,15 @@ function createCashClient(options) {
1088
1526
  }
1089
1527
  function validatePayout(input) {
1090
1528
  const { receive } = input;
1091
- const catalog = sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment);
1092
- 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);
1093
1533
  if (!isMarketRateSupported(receive.currency)) {
1094
1534
  throw errors.oracleUnsupportedCurrency(receive.currency);
1095
1535
  }
1096
- if (platformRequiresIdentityAttestation(receive.platform) && !receive.payee.identityAttestation) {
1097
- throw errors.payeeVerificationRequired(receive.platform);
1536
+ if (!platform.currencies.includes(receive.currency)) {
1537
+ throw errors.unsupportedPlatformCurrency(receive.platform, receive.currency);
1098
1538
  }
1099
1539
  return {
1100
1540
  payouts: [
@@ -1103,15 +1543,22 @@ function createCashClient(options) {
1103
1543
  currency: receive.currency,
1104
1544
  payeeData: receive.payee
1105
1545
  }
1106
- ],
1107
- ...input.intentAmountRange ? { intentAmountRange: input.intentAmountRange } : {}
1546
+ ]
1108
1547
  };
1109
1548
  }
1110
- function validateInput(input) {
1111
- if (input.amount < MIN_CASHOUT_AMOUNT) {
1112
- 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);
1113
1552
  }
1114
- return { amount: input.amount, ...validatePayout(input) };
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);
1556
+ }
1557
+ return {
1558
+ amount,
1559
+ ...payoutInput,
1560
+ ...range ? { intentAmountRange: range } : {}
1561
+ };
1115
1562
  }
1116
1563
  async function buildDepositParams(client, depositInput) {
1117
1564
  try {
@@ -1126,32 +1573,54 @@ function createCashClient(options) {
1126
1573
  throw errors.payeeRegistrationFailed(err);
1127
1574
  }
1128
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
+ }
1129
1587
  async function fetchOrder(depositId) {
1130
- const deposits = await readClient.indexer.getDepositsByIdsWithRelations([depositId], {
1131
- includeIntents: true,
1132
- intentStatuses: CASH_ORDER_STATUSES
1133
- });
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
+ }
1134
1598
  const deposit = deposits[0];
1135
1599
  if (!deposit) {
1136
- const intents = await readClient.indexer.getIntentsForDeposits(
1137
- [depositId],
1138
- CASH_ORDER_STATUSES
1139
- );
1140
- if (intents.length === 0) throw errors.orderNotFound(depositId);
1141
- 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);
1142
1611
  }
1143
1612
  const payouts = derivePayouts(
1144
1613
  deposit.paymentMethods ?? [],
1145
1614
  deposit.currencies ?? [],
1146
1615
  sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment)
1147
1616
  );
1148
- return deriveCashOrder(depositId, deposit.intents ?? [], {
1617
+ return deriveCashOrder(compositeId, deposit.intents ?? [], {
1149
1618
  ...depositOrderOptions(deposit),
1150
1619
  ...payouts.length > 0 ? { payouts } : {}
1151
1620
  });
1152
1621
  }
1153
1622
  function escrowContext(depositId) {
1154
- const { escrowAddress, onchainDepositId } = parseCompositeDepositId(depositId);
1623
+ const { escrowAddress, onchainDepositId } = parseDepositId(depositId);
1155
1624
  return {
1156
1625
  onchainDepositId,
1157
1626
  escrowArg: escrowAddress ? { escrowAddress } : {}
@@ -1166,7 +1635,7 @@ function createCashClient(options) {
1166
1635
  const signaled = order.fills.filter((f) => f.status === "SIGNALED");
1167
1636
  const liveIntent = signaled.some((f) => isFillLive(f, nowSeconds));
1168
1637
  const expiredIntent = signaled.length > 0 && !liveIntent;
1169
- if (order.pendingAmount > 0n && liveIntent) {
1638
+ if (liveIntent || order.pendingAmount > 0n && signaled.length === 0) {
1170
1639
  throw errors.activeIntentBlocksWithdrawal(depositId);
1171
1640
  }
1172
1641
  if (availableAmount(order) <= 0n && order.pendingAmount === 0n) {
@@ -1207,22 +1676,32 @@ function createCashClient(options) {
1207
1676
  txOverrides: attribution
1208
1677
  });
1209
1678
  } catch (err) {
1210
- throw mapChainError("approve", err);
1679
+ throw mapChainError("approve", err, { requiredAmount: amount });
1211
1680
  }
1212
1681
  if (allowance.hadAllowance || !allowance.hash) return;
1213
- 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
+ }
1214
1688
  if (receipt.status === "reverted") throw errors.transactionFailed(allowance.hash);
1689
+ let lastReadError;
1215
1690
  for (let attempt = 0; attempt < 15; attempt++) {
1216
- const visible = await client.publicClient.readContract({
1217
- address: token,
1218
- abi: ERC20_ALLOWANCE_ABI,
1219
- functionName: "allowance",
1220
- args: [owner, escrow]
1221
- });
1222
- 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
+ }
1223
1702
  await sleep(1e3);
1224
1703
  }
1225
- throw errors.allowanceNotVisible(amount);
1704
+ throw errors.allowanceNotVisible(amount, lastReadError);
1226
1705
  }
1227
1706
  return {
1228
1707
  capabilities,
@@ -1233,8 +1712,10 @@ function createCashClient(options) {
1233
1712
  return quoteRelayToBaseUsdc(input, options.relay);
1234
1713
  },
1235
1714
  async executeSourceQuote(quote, opts) {
1715
+ if (!opts.signer.account) throw errors.signerRequired("executeSourceQuote");
1236
1716
  return executeRelayQuote(quote, opts.signer, {
1237
1717
  ...options.relay ? { relay: options.relay } : {},
1718
+ ...opts.recipient ? { recipient: opts.recipient } : {},
1238
1719
  ...opts.onProgress ? { onProgress: opts.onProgress } : {},
1239
1720
  ...opts.disableCapabilitiesCheck !== void 0 ? { disableCapabilitiesCheck: opts.disableCapabilitiesCheck } : {}
1240
1721
  });
@@ -1250,7 +1731,7 @@ function createCashClient(options) {
1250
1731
  });
1251
1732
  },
1252
1733
  async cashout(input, opts) {
1253
- const client = signingClient("cashout", opts);
1734
+ const client = await signingClient("cashout", opts);
1254
1735
  const owner = opts.signer.account.address;
1255
1736
  const payoutInput = validatePayout(input);
1256
1737
  let sourceResult;
@@ -1258,6 +1739,7 @@ function createCashClient(options) {
1258
1739
  if (input.source) {
1259
1740
  const sourceSigner = opts.sourceSigner ?? (input.source.chainId === BASE_CHAIN_ID ? opts.signer : void 0);
1260
1741
  if (!sourceSigner?.account) throw errors.signerRequired("source cashout");
1742
+ await assertWalletChainId(sourceSigner, input.source.chainId, "source cashout");
1261
1743
  if (input.source.recipient !== void 0 && input.source.recipient.toLowerCase() !== owner.toLowerCase()) {
1262
1744
  throw errors.sourceRecipientMismatch(input.source.recipient, owner);
1263
1745
  }
@@ -1275,20 +1757,23 @@ function createCashClient(options) {
1275
1757
  throw errors.amountBelowMinimum(relayQuote.outputAmount, MIN_CASHOUT_AMOUNT);
1276
1758
  }
1277
1759
  cashoutAmount = relayQuote.outputAmount;
1278
- const depositInput2 = { amount: cashoutAmount, ...payoutInput };
1760
+ const depositInput2 = validateDepositInput(cashoutAmount, input, payoutInput);
1279
1761
  const params2 = await buildDepositParams(client, depositInput2);
1280
1762
  const escrow2 = client.escrowV2Address ?? client.escrowAddress;
1281
1763
  await settleAllowance(client, params2.token, owner, escrow2, depositInput2.amount);
1282
1764
  const executed = await executeRelayQuote(relayQuote.raw, sourceSigner, {
1283
1765
  ...options.relay ? { relay: options.relay } : {},
1766
+ recipient: owner,
1284
1767
  ...opts.onSourceProgress ? { onProgress: opts.onSourceProgress } : {},
1285
1768
  ...opts.disableSourceCapabilitiesCheck !== void 0 ? { disableCapabilitiesCheck: opts.disableSourceCapabilitiesCheck } : {}
1286
1769
  });
1287
- sourceResult = {
1770
+ const routedSource = {
1288
1771
  amount: cashoutAmount,
1289
1772
  ...executed.requestId ? { requestId: executed.requestId } : {},
1290
- txHashes: executed.txHashes
1773
+ txHashes: executed.txHashes,
1774
+ ...executed.transactions ? { transactions: executed.transactions } : {}
1291
1775
  };
1776
+ sourceResult = routedSource;
1292
1777
  const attributedParams2 = { ...params2, txOverrides: attribution };
1293
1778
  const send2 = async () => {
1294
1779
  try {
@@ -1305,10 +1790,26 @@ function createCashClient(options) {
1305
1790
  try {
1306
1791
  hash2 = await send2();
1307
1792
  } catch (err) {
1308
- 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
+ );
1309
1812
  }
1310
- const receipt2 = await client.publicClient.waitForTransactionReceipt({ hash: hash2 });
1311
- if (receipt2.status === "reverted") throw errors.transactionFailed(hash2);
1312
1813
  const abi2 = client.escrowV2Abi ?? client.escrowAbi;
1313
1814
  const resolved2 = resolveCashDepositId({ logs: receipt2.logs, abi: abi2 });
1314
1815
  if (!resolved2) throw errors.depositResolutionFailed(hash2);
@@ -1322,10 +1823,10 @@ function createCashClient(options) {
1322
1823
  escrowAddress: resolved2.escrowAddress,
1323
1824
  onchainDepositId: resolved2.onchainDepositId,
1324
1825
  order: order2,
1325
- source: sourceResult
1826
+ source: routedSource
1326
1827
  };
1327
1828
  }
1328
- const depositInput = validateInput(input);
1829
+ const depositInput = validateDepositInput(input.amount, input, payoutInput);
1329
1830
  const params = await buildDepositParams(client, depositInput);
1330
1831
  const escrow = client.escrowV2Address ?? client.escrowAddress;
1331
1832
  await settleAllowance(client, params.token, owner, escrow, depositInput.amount);
@@ -1345,9 +1846,23 @@ function createCashClient(options) {
1345
1846
  try {
1346
1847
  hash = await send();
1347
1848
  } catch (err) {
1348
- 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");
1349
1865
  }
1350
- const receipt = await client.publicClient.waitForTransactionReceipt({ hash });
1351
1866
  if (receipt.status === "reverted") throw errors.transactionFailed(hash);
1352
1867
  const abi = client.escrowV2Abi ?? client.escrowAbi;
1353
1868
  const resolved = resolveCashDepositId({ logs: receipt.logs, abi });
@@ -1367,7 +1882,7 @@ function createCashClient(options) {
1367
1882
  },
1368
1883
  async prepare(input) {
1369
1884
  if (input.source) throw errors.sourceRouteUnsupportedInPrepare();
1370
- const depositInput = validateInput(input);
1885
+ const depositInput = validateDepositInput(input.amount, input);
1371
1886
  const params = await buildDepositParams(readClient, depositInput);
1372
1887
  const { prepared } = await readClient.prepareCreateDeposit({
1373
1888
  ...params,
@@ -1406,13 +1921,46 @@ function createCashClient(options) {
1406
1921
  return fetchOrder(depositId);
1407
1922
  },
1408
1923
  async buyer(address) {
1409
- 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
+ }
1410
1930
  return deriveBuyerProfile(address, intents);
1411
1931
  },
1412
1932
  async orders(owner, opts = {}) {
1413
1933
  const { inFlight = false, limit = 100 } = opts;
1414
- const deposits = await readClient.indexer.getDeposits({ depositor: owner }, { limit });
1415
- 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));
1416
1964
  return inFlight ? derived.filter((o) => o.isInFlight) : derived;
1417
1965
  },
1418
1966
  async *watch(depositId, opts = {}) {
@@ -1442,7 +1990,7 @@ function createCashClient(options) {
1442
1990
  }
1443
1991
  },
1444
1992
  async withdraw(depositId, opts) {
1445
- const client = signingClient("withdraw", opts);
1993
+ const client = await signingClient("withdraw", opts);
1446
1994
  if (opts.amount !== void 0) {
1447
1995
  const { onchainDepositId: onchainDepositId2, escrowArg: escrowArg2 } = await partialWithdrawContext(
1448
1996
  depositId,
@@ -1540,7 +2088,7 @@ function createCashClient(options) {
1540
2088
  return { txs, steps };
1541
2089
  },
1542
2090
  async topUp(depositId, amount, opts) {
1543
- const client = signingClient("topUp", opts);
2091
+ const client = await signingClient("topUp", opts);
1544
2092
  const { onchainDepositId, escrowArg } = await topUpContext(depositId, amount);
1545
2093
  const owner = opts.signer.account.address;
1546
2094
  const escrow = escrowArg.escrowAddress ?? client.escrowV2Address ?? client.escrowAddress;
@@ -1595,6 +2143,39 @@ function createCashClient(options) {
1595
2143
  };
1596
2144
  }
1597
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
+ });
1598
2179
  var cashOrderStateSchema = zod.z.enum([
1599
2180
  "awaiting-buyer",
1600
2181
  "matched",
@@ -1607,18 +2188,18 @@ var intentStatusSchema = zod.z.enum(["SIGNALED", "FULFILLED", "PRUNED", "MANUALL
1607
2188
  var cashFillJsonSchema = zod.z.object({
1608
2189
  intentHash: zod.z.string(),
1609
2190
  status: intentStatusSchema,
1610
- amount: bigintString,
2191
+ amount: nonNegativeBigintString,
1611
2192
  buyer: zod.z.string(),
1612
2193
  currency: zod.z.string().optional(),
1613
2194
  currencyHash: zod.z.string().optional(),
1614
2195
  rate: zod.z.number().optional(),
1615
- conversionRate: bigintString.optional(),
2196
+ conversionRate: nonNegativeBigintString.optional(),
1616
2197
  fiatOwed: zod.z.number().optional(),
1617
2198
  fiatPaid: zod.z.number().optional(),
1618
2199
  paidCurrency: zod.z.string().optional(),
1619
2200
  paymentId: zod.z.string().optional(),
1620
2201
  paidAt: zod.z.number().optional(),
1621
- releasedAmount: bigintString.optional(),
2202
+ releasedAmount: nonNegativeBigintString.optional(),
1622
2203
  fillLatencySeconds: zod.z.number().optional(),
1623
2204
  isExpired: zod.z.boolean().optional(),
1624
2205
  signaledAt: zod.z.number().optional(),
@@ -1657,10 +2238,10 @@ var cashOrderJsonSchema = zod.z.object({
1657
2238
  depositId: zod.z.string(),
1658
2239
  state: cashOrderStateSchema,
1659
2240
  fills: zod.z.array(cashFillJsonSchema),
1660
- totalAmount: bigintString,
1661
- filledAmount: bigintString,
1662
- pendingAmount: bigintString,
1663
- returnedAmount: bigintString,
2241
+ totalAmount: nonNegativeBigintString,
2242
+ filledAmount: nonNegativeBigintString,
2243
+ pendingAmount: nonNegativeBigintString,
2244
+ returnedAmount: nonNegativeBigintString,
1664
2245
  nextActions: zod.z.array(cashNextActionSchema),
1665
2246
  primaryIntentHash: zod.z.string().optional(),
1666
2247
  matchedAt: zod.z.number().optional(),
@@ -1675,7 +2256,7 @@ var cashOrderJsonSchema = zod.z.object({
1675
2256
  var cashEstimateJsonSchema = zod.z.object({
1676
2257
  kind: zod.z.literal("oracle-estimate"),
1677
2258
  currency: zod.z.string(),
1678
- amount: bigintString,
2259
+ amount: nonNegativeBigintString,
1679
2260
  rate: zod.z.number(),
1680
2261
  receiveAmount: zod.z.number(),
1681
2262
  asOf: zod.z.number(),
@@ -1691,7 +2272,7 @@ var cashEstimateJsonSchema = zod.z.object({
1691
2272
  name: zod.z.string().optional(),
1692
2273
  isNative: zod.z.boolean().optional()
1693
2274
  }),
1694
- inputAmount: bigintString,
2275
+ inputAmount: nonNegativeBigintString,
1695
2276
  relayQuote: zod.z.object({
1696
2277
  requestId: zod.z.string().optional(),
1697
2278
  source: zod.z.object({
@@ -1710,8 +2291,8 @@ var cashEstimateJsonSchema = zod.z.object({
1710
2291
  name: zod.z.string().optional(),
1711
2292
  isNative: zod.z.boolean().optional()
1712
2293
  }),
1713
- inputAmount: bigintString,
1714
- outputAmount: bigintString,
2294
+ inputAmount: nonNegativeBigintString,
2295
+ outputAmount: nonNegativeBigintString,
1715
2296
  rate: zod.z.number().optional(),
1716
2297
  timeEstimateSeconds: zod.z.number().optional(),
1717
2298
  fees: zod.z.unknown().optional(),
@@ -1719,7 +2300,7 @@ var cashEstimateJsonSchema = zod.z.object({
1719
2300
  zod.z.object({
1720
2301
  to: zod.z.string(),
1721
2302
  data: zod.z.string(),
1722
- value: bigintString,
2303
+ value: nonNegativeBigintString,
1723
2304
  chainId: zod.z.number()
1724
2305
  })
1725
2306
  ),
@@ -1734,9 +2315,39 @@ var cashEstimateJsonSchema = zod.z.object({
1734
2315
  var preparedTransactionJsonSchema = zod.z.object({
1735
2316
  to: zod.z.string(),
1736
2317
  data: zod.z.string(),
1737
- value: bigintString,
2318
+ value: nonNegativeBigintString,
1738
2319
  chainId: zod.z.number()
1739
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
+ });
1740
2351
  var cashPreparedStepJsonSchema = zod.z.object({
1741
2352
  kind: zod.z.enum([
1742
2353
  "approve",
@@ -1752,12 +2363,13 @@ var cashoutResultJsonSchema = zod.z.object({
1752
2363
  depositId: zod.z.string(),
1753
2364
  txHash: zod.z.string(),
1754
2365
  escrowAddress: zod.z.string(),
1755
- onchainDepositId: bigintString,
2366
+ onchainDepositId: nonNegativeBigintString,
1756
2367
  order: cashOrderJsonSchema,
1757
2368
  source: zod.z.object({
1758
- amount: bigintString,
2369
+ amount: nonNegativeBigintString,
1759
2370
  requestId: zod.z.string().optional(),
1760
- txHashes: zod.z.array(zod.z.string())
2371
+ txHashes: zod.z.array(zod.z.string()),
2372
+ transactions: relayTransactionsJsonSchema.optional()
1761
2373
  }).optional()
1762
2374
  });
1763
2375
  var prepareResultJsonSchema = zod.z.object({
@@ -1787,39 +2399,7 @@ var cashCapabilitiesJsonSchema = zod.z.object({
1787
2399
  chainId: zod.z.number(),
1788
2400
  token: zod.z.object({ address: zod.z.string(), symbol: zod.z.literal("USDC"), decimals: zod.z.number() })
1789
2401
  }),
1790
- relay: zod.z.object({
1791
- destination: zod.z.object({
1792
- chainId: zod.z.number(),
1793
- address: zod.z.string(),
1794
- symbol: zod.z.string(),
1795
- decimals: zod.z.number(),
1796
- name: zod.z.string().optional(),
1797
- isNative: zod.z.boolean().optional()
1798
- }),
1799
- chains: zod.z.array(
1800
- zod.z.object({
1801
- id: zod.z.number(),
1802
- name: zod.z.string(),
1803
- displayName: zod.z.string(),
1804
- disabled: zod.z.boolean(),
1805
- depositEnabled: zod.z.boolean(),
1806
- blockProductionLagging: zod.z.boolean(),
1807
- vmType: zod.z.string().optional(),
1808
- tokens: zod.z.array(
1809
- zod.z.object({
1810
- chainId: zod.z.number(),
1811
- address: zod.z.string(),
1812
- symbol: zod.z.string(),
1813
- decimals: zod.z.number(),
1814
- name: zod.z.string().optional(),
1815
- isNative: zod.z.boolean().optional()
1816
- })
1817
- )
1818
- })
1819
- ),
1820
- source: zod.z.literal("relay-sdk"),
1821
- asOf: zod.z.number()
1822
- }).optional()
2402
+ relay: cashSourceCapabilitiesJsonSchema.optional()
1823
2403
  }),
1824
2404
  platforms: zod.z.array(
1825
2405
  zod.z.object({
@@ -1830,15 +2410,98 @@ var cashCapabilitiesJsonSchema = zod.z.object({
1830
2410
  })
1831
2411
  ),
1832
2412
  currencies: zod.z.array(zod.z.string()),
1833
- 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
+ }),
1834
2418
  pricing: zod.z.object({ kind: zod.z.literal("oracle-market-rate"), spreadBps: zod.z.literal(0) })
1835
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
+ ]);
1836
2498
  var cashErrorJsonSchema = zod.z.object({
1837
- code: zod.z.string(),
2499
+ code: zod.z.enum(CASH_ERROR_CODES),
1838
2500
  message: zod.z.string(),
1839
2501
  retryable: zod.z.boolean(),
1840
- remediation: zod.z.string()
1841
- });
2502
+ remediation: zod.z.string(),
2503
+ recovery: cashErrorRecoveryJsonSchema.optional()
2504
+ }).strict();
1842
2505
 
1843
2506
  // src/codecs/json.ts
1844
2507
  function omitUndefined(obj) {
@@ -1869,35 +2532,38 @@ function fillToJson(fill) {
1869
2532
  });
1870
2533
  }
1871
2534
  function fillFromJson(json) {
2535
+ const parsed = cashFillJsonSchema.parse(json);
1872
2536
  return omitUndefined({
1873
- ...json,
1874
- amount: BigInt(json.amount),
1875
- conversionRate: json.conversionRate !== void 0 ? BigInt(json.conversionRate) : void 0,
1876
- 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
1877
2541
  });
1878
2542
  }
1879
2543
  function orderToJson(order) {
1880
- return omitUndefined({
1881
- depositId: order.depositId,
1882
- state: order.state,
1883
- fills: order.fills.map(fillToJson),
1884
- totalAmount: order.totalAmount.toString(),
1885
- filledAmount: order.filledAmount.toString(),
1886
- pendingAmount: order.pendingAmount.toString(),
1887
- returnedAmount: order.returnedAmount.toString(),
1888
- nextActions: order.nextActions,
1889
- primaryIntentHash: order.primaryIntentHash,
1890
- matchedAt: order.matchedAt,
1891
- deliveredAt: order.deliveredAt,
1892
- updatedAt: order.updatedAt,
1893
- intentCount: order.intentCount,
1894
- payouts: order.payouts?.map(
1895
- (p) => omitUndefined({ ...p, pricing: omitUndefined({ ...p.pricing }) })
1896
- ),
1897
- successRateBps: order.successRateBps,
1898
- isInFlight: order.isInFlight,
1899
- withdrawn: order.withdrawn
1900
- });
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
+ );
1901
2567
  }
1902
2568
  function orderFromJson(json) {
1903
2569
  const parsed = cashOrderJsonSchema.parse(json);
@@ -1923,6 +2589,7 @@ function estimateToJson(estimate) {
1923
2589
  inputAmount: estimate.source.relayQuote.inputAmount.toString(),
1924
2590
  outputAmount: estimate.source.relayQuote.outputAmount.toString(),
1925
2591
  txs: estimate.source.relayQuote.txs.map(preparedTxToJson),
2592
+ ...estimate.source.relayQuote.fees !== void 0 ? { fees: sanitizeRelayValue(estimate.source.relayQuote.fees) } : {},
1926
2593
  raw: sanitizeRelayQuoteRaw(estimate.source.relayQuote.raw)
1927
2594
  }
1928
2595
  } : void 0
@@ -1941,11 +2608,108 @@ function estimateFromJson(json) {
1941
2608
  ...parsed.source.relayQuote,
1942
2609
  inputAmount: BigInt(parsed.source.relayQuote.inputAmount),
1943
2610
  outputAmount: BigInt(parsed.source.relayQuote.outputAmount),
1944
- 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)
1945
2614
  }
1946
2615
  } : void 0
1947
2616
  });
1948
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
+ }
1949
2713
  function preparedTxToJson(tx) {
1950
2714
  return { to: tx.to, data: tx.data, value: tx.value.toString(), chainId: tx.chainId };
1951
2715
  }
@@ -2064,6 +2828,69 @@ function capabilitiesFromJson(json) {
2064
2828
  }
2065
2829
  };
2066
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
+ }
2067
2894
 
2068
2895
  exports.BASE_CHAIN_ID = BASE_CHAIN_ID;
2069
2896
  exports.BASE_USDC_ADDRESS = BASE_USDC_ADDRESS;
@@ -2086,9 +2913,14 @@ exports.buyerProfileFromJson = buyerProfileFromJson;
2086
2913
  exports.buyerProfileToJson = buyerProfileToJson;
2087
2914
  exports.capabilitiesFromJson = capabilitiesFromJson;
2088
2915
  exports.capabilitiesToJson = capabilitiesToJson;
2916
+ exports.cashAssetJsonSchema = cashAssetJsonSchema;
2089
2917
  exports.cashBuyerProfileJsonSchema = cashBuyerProfileJsonSchema;
2090
2918
  exports.cashCapabilitiesJsonSchema = cashCapabilitiesJsonSchema;
2919
+ exports.cashChainJsonSchema = cashChainJsonSchema;
2920
+ exports.cashErrorFromJson = cashErrorFromJson;
2091
2921
  exports.cashErrorJsonSchema = cashErrorJsonSchema;
2922
+ exports.cashErrorRecoveryJsonSchema = cashErrorRecoveryJsonSchema;
2923
+ exports.cashErrorToJson = cashErrorToJson;
2092
2924
  exports.cashEstimateJsonSchema = cashEstimateJsonSchema;
2093
2925
  exports.cashFillJsonSchema = cashFillJsonSchema;
2094
2926
  exports.cashNextActionSchema = cashNextActionSchema;
@@ -2097,6 +2929,7 @@ exports.cashOrderStateSchema = cashOrderStateSchema;
2097
2929
  exports.cashPayoutInfoJsonSchema = cashPayoutInfoJsonSchema;
2098
2930
  exports.cashPayoutPricingJsonSchema = cashPayoutPricingJsonSchema;
2099
2931
  exports.cashPreparedStepJsonSchema = cashPreparedStepJsonSchema;
2932
+ exports.cashSourceCapabilitiesJsonSchema = cashSourceCapabilitiesJsonSchema;
2100
2933
  exports.cashoutResultFromJson = cashoutResultFromJson;
2101
2934
  exports.cashoutResultJsonSchema = cashoutResultJsonSchema;
2102
2935
  exports.cashoutResultToJson = cashoutResultToJson;
@@ -2118,6 +2951,7 @@ exports.intentStatusSchema = intentStatusSchema;
2118
2951
  exports.isCashError = isCashError;
2119
2952
  exports.isFillLive = isFillLive;
2120
2953
  exports.isMarketRateSupported = isMarketRateSupported;
2954
+ exports.nonNegativeBigintString = nonNegativeBigintString;
2121
2955
  exports.orderFromJson = orderFromJson;
2122
2956
  exports.orderToJson = orderToJson;
2123
2957
  exports.parseCompositeDepositId = parseCompositeDepositId;
@@ -2131,7 +2965,20 @@ exports.preparedTransactionJsonSchema = preparedTransactionJsonSchema;
2131
2965
  exports.preparedTxFromJson = preparedTxFromJson;
2132
2966
  exports.preparedTxToJson = preparedTxToJson;
2133
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;
2134
2979
  exports.resolveCashDepositId = resolveCashDepositId;
2980
+ exports.sourceCapabilitiesFromJson = sourceCapabilitiesFromJson;
2981
+ exports.sourceCapabilitiesToJson = sourceCapabilitiesToJson;
2135
2982
  exports.topUpResultFromJson = topUpResultFromJson;
2136
2983
  exports.topUpResultJsonSchema = topUpResultJsonSchema;
2137
2984
  exports.topUpResultToJson = topUpResultToJson;
@@ -2140,5 +2987,3 @@ exports.withExplain = withExplain;
2140
2987
  exports.withdrawResultFromJson = withdrawResultFromJson;
2141
2988
  exports.withdrawResultJsonSchema = withdrawResultJsonSchema;
2142
2989
  exports.withdrawResultToJson = withdrawResultToJson;
2143
- //# sourceMappingURL=index.cjs.map
2144
- //# sourceMappingURL=index.cjs.map