@provex/react 1.9.2 → 1.10.0-rc.20260820232714.83636f8

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.
@@ -51,8 +51,11 @@ interface UseDepositsOptions {
51
51
  refetchIntervalMs?: number;
52
52
  }
53
53
  /**
54
- * Get the best (lowest) conversion rate for a deposit across the main provider
55
- * and all sub-providers.
54
+ * Get the conversion rate a deposit offers for a payment method and currency.
55
+ *
56
+ * Quotes the rail's own rate and does not fall back to a sub-provider's. A rate
57
+ * that only exists under `zelle-chase` belongs to a payment method the buyer
58
+ * cannot be attested for, so quoting it prices an order that cannot complete.
56
59
  *
57
60
  * Returns 0n when the deposit has no rate for the given payment method / currency.
58
61
  */
@@ -51,8 +51,11 @@ interface UseDepositsOptions {
51
51
  refetchIntervalMs?: number;
52
52
  }
53
53
  /**
54
- * Get the best (lowest) conversion rate for a deposit across the main provider
55
- * and all sub-providers.
54
+ * Get the conversion rate a deposit offers for a payment method and currency.
55
+ *
56
+ * Quotes the rail's own rate and does not fall back to a sub-provider's. A rate
57
+ * that only exists under `zelle-chase` belongs to a payment method the buyer
58
+ * cannot be attested for, so quoting it prices an order that cannot complete.
56
59
  *
57
60
  * Returns 0n when the deposit has no rate for the given payment method / currency.
58
61
  */
@@ -4,12 +4,13 @@ import { createPublicClient, http, encodeAbiParameters, parseAbiParameters, zero
4
4
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
5
5
  import { SUPPORTED_CURRENCIES, tickerToContractId } from '@provex/utils/currencies';
6
6
  import { parseUnits, formatUnits } from '@provex/utils/units';
7
- import { providerConfigs, providerKeyToContractId, computePayeeDetailsHash, tiers, verifiablePaymentMethods, getPlatformRisk, verifierGetsKey, resolveApiProviderKey, getPaymentMethodName } from '@provex/utils/payment';
7
+ import { providerKeyToContractId, providerConfigs, computePayeeDetailsHash, resolveRailProviderKey, tiers, verifiablePaymentMethods, getPlatformRisk, verifierGetsKey, resolveApiProviderKey, getPaymentMethodName } from '@provex/utils/payment';
8
8
  import { convertCurrencyToTokenOutput } from '@provex/utils/conversionRates';
9
- import { getLatestContract, reclaimSigners, getEscrowVersion } from '@provex/utils/contracts';
9
+ import { getLatestContract, getLatestConfiguredVersion, getEscrowVersion, getConfiguredOrchestratorForEscrow, reclaimSigners, getPaymentAttestationVerifier } from '@provex/utils/contracts';
10
10
  import { encodeV3PaymentProof } from '@provex/utils';
11
+ import { toEscrowCurrencies } from '@provex/utils/deposit';
11
12
  import { normalizeFeePrecision } from '@provex/utils/fees';
12
- import { V3EscrowAbi, OrchestratorAbi, PaymentVerifierRegistryAbi, UnifiedPaymentVerifierAbi, NullifierRegistryAbi, V4OrchestratorAbi } from '@provex/abis';
13
+ import { OrchestratorAbi, escrowAbiByVersion, V3EscrowAbi, PaymentVerifierRegistryAbi, UnifiedPaymentVerifierAbi, NullifierRegistryAbi, V4OrchestratorAbi } from '@provex/abis';
13
14
  import { publicClient, getDefaultToken } from '@provex/utils/tokens';
14
15
  import { chainIdToChain } from '@provex/utils/chain';
15
16
  import { base } from 'viem/chains';
@@ -110,22 +111,9 @@ function getRate({
110
111
  currency
111
112
  }) {
112
113
  if (!deposit) return 0n;
113
- const paymentConfig = providerConfigs(deposit.chainId)[paymentMethod];
114
- const candidateKeys = [
115
- paymentMethod,
116
- ...Array.from(paymentConfig?.subProviders ?? []).map((sp) => sp.key)
117
- ];
118
- let minRate = null;
119
- for (const key of candidateKeys) {
120
- const contractId = providerKeyToContractId(key).toLowerCase();
121
- const value = deposit.conversionRates.get(contractId)?.get(currency.contractId.toLowerCase());
122
- if (value) {
123
- if (minRate === null || value < minRate) {
124
- minRate = value;
125
- }
126
- }
127
- }
128
- return minRate ?? 0n;
114
+ const contractId = providerKeyToContractId(paymentMethod).toLowerCase();
115
+ const value = deposit.conversionRates.get(contractId)?.get(currency.contractId.toLowerCase());
116
+ return value ?? 0n;
129
117
  }
130
118
  function toDepositInfo(deposit) {
131
119
  return {
@@ -158,11 +146,7 @@ function useDeposits(options) {
158
146
  const paymentConfig = providerConfigs(token.chainId)[paymentMethod];
159
147
  return /* @__PURE__ */ new Set([
160
148
  providerKeyToContractId(paymentMethod).toLowerCase(),
161
- ...paymentConfig.v2Verifiers.map((v) => v.toLowerCase()),
162
- ...Array.from(paymentConfig.subProviders).flatMap((subProvider) => [
163
- providerKeyToContractId(subProvider.key).toLowerCase(),
164
- ...subProvider.v2Verifiers(token.chainId).map((v) => v.toLowerCase())
165
- ])
149
+ ...paymentConfig.v2Verifiers.map((v) => v.toLowerCase())
166
150
  ]);
167
151
  }, [token.chainId, paymentMethod]);
168
152
  const depositsQuery = useQuery({
@@ -396,82 +380,85 @@ var ProveXClient = class {
396
380
  this.onSlowSync = config.onSlowSync;
397
381
  this.apiUrl = config.apiUrl ?? defaults?.apiUrl ?? "https://app.provex.com";
398
382
  this.createDepositRaw = this.buildWritableMethod({
399
- abi: V3EscrowAbi,
383
+ abi: () => this.getEscrowAbi(),
400
384
  contractResolver: () => this.getEscrowAddress(),
401
385
  functionName: "createDeposit",
402
- argsMapper: (params) => [params]
386
+ argsMapper: (params) => [{
387
+ ...params,
388
+ currencies: params.currencies.map((perMethod) => toEscrowCurrencies(perMethod, this.getEscrowGeneration()))
389
+ }]
403
390
  });
404
391
  this.addFunds = this.buildWritableMethod({
405
- abi: V3EscrowAbi,
392
+ abi: () => this.getEscrowAbi(),
406
393
  contractResolver: () => this.getEscrowAddress(),
407
394
  functionName: "addFunds",
408
395
  argsMapper: (params) => [params.depositId, params.amount]
409
396
  });
410
397
  this.removeFunds = this.buildWritableMethod({
411
- abi: V3EscrowAbi,
398
+ abi: () => this.getEscrowAbi(),
412
399
  contractResolver: () => this.getEscrowAddress(),
413
400
  functionName: "removeFunds",
414
401
  argsMapper: (params) => [params.depositId, params.amount]
415
402
  });
416
403
  this.withdrawDeposit = this.buildWritableMethod({
417
- abi: V3EscrowAbi,
404
+ abi: () => this.getEscrowAbi(),
418
405
  contractResolver: () => this.getEscrowAddress(),
419
406
  functionName: "withdrawDeposit",
420
407
  argsMapper: (params) => [params.depositId]
421
408
  });
422
409
  this.pruneExpiredIntents = this.buildWritableMethod({
423
- abi: V3EscrowAbi,
410
+ abi: () => this.getEscrowAbi(),
424
411
  contractResolver: () => this.getEscrowAddress(),
425
412
  functionName: "pruneExpiredIntents",
426
413
  argsMapper: (params) => [params.depositId]
427
414
  });
428
415
  this.setAcceptingIntents = this.buildWritableMethod({
429
- abi: V3EscrowAbi,
416
+ abi: () => this.getEscrowAbi(),
430
417
  contractResolver: () => this.getEscrowAddress(),
431
418
  functionName: "setAcceptingIntents",
432
419
  argsMapper: (params) => [params.depositId, params.accepting]
433
420
  });
434
421
  this.setRetainOnEmpty = this.buildWritableMethod({
435
- abi: V3EscrowAbi,
422
+ abi: () => this.getEscrowAbi(),
436
423
  contractResolver: () => this.getEscrowAddress(),
437
424
  functionName: "setRetainOnEmpty",
438
425
  argsMapper: (params) => [params.depositId, params.retain]
439
426
  });
440
427
  this.setIntentRange = this.buildWritableMethod({
441
- abi: V3EscrowAbi,
428
+ abi: () => this.getEscrowAbi(),
442
429
  contractResolver: () => this.getEscrowAddress(),
443
430
  functionName: "setIntentRange",
444
431
  argsMapper: (params) => [params.depositId, { min: params.min, max: params.max }]
445
432
  });
446
433
  this.setPaymentMethodActive = this.buildWritableMethod({
447
- abi: V3EscrowAbi,
434
+ abi: () => this.getEscrowAbi(),
448
435
  contractResolver: () => this.getEscrowAddress(),
449
436
  functionName: "setPaymentMethodActive",
450
437
  argsMapper: (params) => [params.depositId, params.paymentMethod, params.active]
451
438
  });
452
439
  this.setCurrencyMinRate = this.buildWritableMethod({
453
- abi: V3EscrowAbi,
440
+ abi: () => this.getEscrowAbi(),
454
441
  contractResolver: () => this.getEscrowAddress(),
455
442
  functionName: "setCurrencyMinRate",
456
443
  argsMapper: (params) => [params.depositId, params.paymentMethod, params.currency, params.rate]
457
444
  });
458
445
  this.addCurrencies = this.buildWritableMethod({
459
- abi: V3EscrowAbi,
446
+ abi: () => this.getEscrowAbi(),
460
447
  contractResolver: () => this.getEscrowAddress(),
461
448
  functionName: "addCurrencies",
462
- argsMapper: (params) => [params.depositId, params.paymentMethod, params.currencies]
449
+ argsMapper: (params) => [params.depositId, params.paymentMethod, toEscrowCurrencies(params.currencies, this.getEscrowGeneration())]
463
450
  });
464
451
  this.deactivateCurrency = this.buildWritableMethod({
465
- abi: V3EscrowAbi,
452
+ abi: () => this.getEscrowAbi(),
466
453
  contractResolver: () => this.getEscrowAddress(),
467
454
  functionName: "deactivateCurrency",
468
455
  argsMapper: (params) => [params.depositId, params.paymentMethod, params.currencyCode]
469
456
  });
470
457
  this.addPaymentMethods = this.buildWritableMethod({
471
- abi: V3EscrowAbi,
458
+ abi: () => this.getEscrowAbi(),
472
459
  contractResolver: () => this.getEscrowAddress(),
473
460
  functionName: "addPaymentMethods",
474
- argsMapper: (params) => [params.depositId, params.paymentMethods, params.paymentMethodData, params.currencies]
461
+ argsMapper: (params) => [params.depositId, params.paymentMethods, params.paymentMethodData, params.currencies.map((perMethod) => toEscrowCurrencies(perMethod, this.getEscrowGeneration()))]
475
462
  });
476
463
  this.cancelIntent = this.buildWritableMethod({
477
464
  abi: OrchestratorAbi,
@@ -506,17 +493,66 @@ var ProveXClient = class {
506
493
  });
507
494
  }
508
495
  // ─── Address Resolution ──────────────────────────────────────────────────
509
- /** Get the V3 escrow address for this client's chain. */
496
+ /**
497
+ * The escrow this client acts on.
498
+ *
499
+ * Callers that touch a specific deposit MUST construct the client with
500
+ * `escrowAddress: deposit.escrow` — the fallback below is only correct for a
501
+ * client that has no deposit in hand, and silently sends every write to the
502
+ * wrong escrow otherwise.
503
+ *
504
+ * That fallback follows the chain's current generation rather than a pinned
505
+ * v3. The only writes that reach it are ones with no existing deposit to
506
+ * name — `createDeposit` above all — and those belong on the generation the
507
+ * protocol is actually running, not the one it has moved off.
508
+ */
510
509
  getEscrowAddress() {
511
510
  if (this.escrowOverride) return this.escrowOverride;
512
- const addr = getLatestContract(this.chainId, "escrow", "v3");
513
- if (!addr) throw new ProveXError("VALIDATION_ERROR", `No V3 escrow found for chain ${this.chainId}`);
511
+ const addr = getLatestContract(this.chainId, "escrow", getLatestConfiguredVersion(this.chainId));
512
+ if (!addr) throw new ProveXError("VALIDATION_ERROR", `No escrow configured for chain ${this.chainId}`);
514
513
  return addr;
515
514
  }
516
- /** Get the orchestrator address (cached after first read). */
515
+ /**
516
+ * The escrow's generation, used to pick the matching interface.
517
+ *
518
+ * An unrecognised address is not an error: callers may point the client at a
519
+ * fork or a local deployment through `escrowAddress`. Those fall back to v3,
520
+ * which is what this client assumed for every escrow before generations were
521
+ * resolved at all — so an override that worked before still works.
522
+ */
523
+ getEscrowGeneration() {
524
+ return getEscrowVersion(this.getEscrowAddress(), this.chainId) ?? "v3";
525
+ }
526
+ /**
527
+ * The escrow interface matching this client's escrow generation.
528
+ *
529
+ * EscrowV2 is not signature-compatible with the v3 escrow for every maker
530
+ * write — `createDeposit`, `addPaymentMethods` and `addCurrencies` each gain
531
+ * an oracle rate config in their currency tuple, which changes the selector.
532
+ * Binding one generation's interface to whatever address we resolved
533
+ * produces a call the contract cannot decode, and since these writes are not
534
+ * simulated the maker signs and pays gas for a certain revert.
535
+ */
536
+ getEscrowAbi() {
537
+ return escrowAbiByVersion[this.getEscrowGeneration()];
538
+ }
539
+ /**
540
+ * Get the orchestrator address (cached after first read).
541
+ *
542
+ * Generation decides where this comes from. v2 and v3 escrows expose
543
+ * `orchestrator()`; EscrowV2 authorizes through an `OrchestratorRegistry`
544
+ * and exposes no such function, so reading it reverts and the address has to
545
+ * come from configuration. Probing on-chain first would therefore break
546
+ * every v4 flow before the wallet ever opens.
547
+ */
517
548
  async getOrchestratorAddress() {
518
549
  if (this.cachedOrchestratorAddress) return this.cachedOrchestratorAddress;
519
550
  const escrow = this.getEscrowAddress();
551
+ const configured = getConfiguredOrchestratorForEscrow(escrow);
552
+ if (configured) {
553
+ this.cachedOrchestratorAddress = configured;
554
+ return configured;
555
+ }
520
556
  const result = await this.readContract({
521
557
  address: escrow,
522
558
  abi: V3EscrowAbi,
@@ -666,34 +702,16 @@ var ProveXClient = class {
666
702
  }
667
703
  /**
668
704
  * Convert human-readable deposit params to raw contract params.
669
- * Handles provider expansion, hashing, gating service encoding, and defaults.
705
+ * Handles rail collapsing, hashing, gating service encoding, and defaults.
670
706
  */
671
707
  buildCreateDepositRawParams(params) {
672
- const expanded = [];
673
- const configs = providerConfigs(this.chainId);
674
- for (const pm of params.paymentMethods) {
675
- const hash = computePayeeDetailsHash(pm.payeeId);
676
- const config = configs[pm.provider];
677
- if (config?.subProviders && config.subProviders.size > 0) {
678
- for (const sub of config.subProviders) {
679
- expanded.push({
680
- providerKey: sub.key,
681
- payeeDetailsHash: hash,
682
- currencies: pm.currencies,
683
- intentGatingService: pm.intentGatingService,
684
- data: pm.data
685
- });
686
- }
687
- } else {
688
- expanded.push({
689
- providerKey: pm.provider,
690
- payeeDetailsHash: hash,
691
- currencies: pm.currencies,
692
- intentGatingService: pm.intentGatingService,
693
- data: pm.data
694
- });
695
- }
696
- }
708
+ const collapsed = params.paymentMethods.map((pm) => ({
709
+ providerKey: resolveRailProviderKey(pm.provider),
710
+ payeeDetailsHash: computePayeeDetailsHash(pm.payeeId),
711
+ currencies: pm.currencies,
712
+ intentGatingService: pm.intentGatingService,
713
+ data: pm.data
714
+ }));
697
715
  const defaultGatingData = encodeAbiParameters(
698
716
  parseAbiParameters(["address[]"]),
699
717
  [[reclaimSigners.peerWitnessSigner, reclaimSigners.reclaimWitnessSigner]]
@@ -706,13 +724,13 @@ var ProveXClient = class {
706
724
  min: params.intentRange?.min ?? 1000000n,
707
725
  max: params.intentRange?.max ?? params.amount
708
726
  },
709
- paymentMethods: expanded.map((p) => providerKeyToContractId(p.providerKey)),
710
- paymentMethodData: expanded.map((p) => ({
727
+ paymentMethods: collapsed.map((p) => providerKeyToContractId(p.providerKey)),
728
+ paymentMethodData: collapsed.map((p) => ({
711
729
  intentGatingService: p.intentGatingService ?? defaultGatingService,
712
730
  payeeDetails: p.payeeDetailsHash,
713
731
  data: p.data ?? defaultGatingData
714
732
  })),
715
- currencies: expanded.map(
733
+ currencies: collapsed.map(
716
734
  (p) => p.currencies.map((c) => ({
717
735
  code: tickerToContractId(c.code),
718
736
  minConversionRate: c.minRate
@@ -1023,7 +1041,7 @@ var ProveXClient = class {
1023
1041
  const to = await contractResolver(params);
1024
1042
  const args = argsMapper(params);
1025
1043
  const data = encodeFunctionData({
1026
- abi,
1044
+ abi: typeof abi === "function" ? abi() : abi,
1027
1045
  functionName,
1028
1046
  args
1029
1047
  });
@@ -1514,16 +1532,34 @@ function useOrchestratorAddress({
1514
1532
  chainId,
1515
1533
  enabled = true
1516
1534
  }) {
1517
- return useContractRead({
1535
+ const configuredOrchestrator = useMemo(
1536
+ () => escrowAddress ? getConfiguredOrchestratorForEscrow(escrowAddress) : null,
1537
+ [escrowAddress]
1538
+ );
1539
+ const query = useContractRead({
1518
1540
  address: escrowAddress,
1519
1541
  abi: V3EscrowAbi,
1520
1542
  functionName: "orchestrator",
1521
1543
  chainId,
1522
1544
  query: {
1523
- enabled: enabled && !!escrowAddress,
1545
+ enabled: enabled && !!escrowAddress && !configuredOrchestrator,
1524
1546
  staleTime: Infinity
1525
1547
  }
1526
1548
  });
1549
+ return useMemo(() => {
1550
+ if (!configuredOrchestrator) return query;
1551
+ return {
1552
+ ...query,
1553
+ data: configuredOrchestrator,
1554
+ isLoading: false,
1555
+ isPending: false,
1556
+ isFetching: false,
1557
+ isSuccess: true,
1558
+ isError: false,
1559
+ error: null,
1560
+ status: "success"
1561
+ };
1562
+ }, [query, configuredOrchestrator]);
1527
1563
  }
1528
1564
  var FEE_CACHE_STALE_TIME = 60 * 60 * 1e3;
1529
1565
  function useProtocolFees({
@@ -1842,7 +1878,7 @@ function useProvexBuy({
1842
1878
  );
1843
1879
  const attestationBaseUrl = config.apiUrl;
1844
1880
  const verifyingContract = useMemo(
1845
- () => getLatestContract(chainId, "unifiedPaymentVerifier", "v3"),
1881
+ () => getPaymentAttestationVerifier(chainId),
1846
1882
  [chainId]
1847
1883
  );
1848
1884
  const captureRequest = useMemo(() => {
@@ -2508,5 +2544,5 @@ function ProvexBuyRoot({
2508
2544
  }
2509
2545
 
2510
2546
  export { BrowsePhase, CommittedPhase, CompletePhase, ProveXClient, ProveXError, ProvexBuy, ProvexBuyProvider, ProvexProvider, ProvingPhase, checkMutation, checkTransactionIndexed, createApiClient, createProveXClient, getRate, getTierDisplayInfo, getTransactionGasInputs, getUserFriendlyErrorMessage, intentStatuses, isUserRejectionError, useContractRead, useDeposits, useNullifierRegistry, useOptionalProvex, useOptionalProvexPublicClient, useOptionalProvexWallet, useOrchestratorAddress, usePayeeDetails, useProtocolFeePercentage, useProtocolFees, useProveXClient, useProvex, useProvexBuy, useProvexBuyContext, useProvexPublicClient, useProvexWallet, useReputation, useReputationLimits, useSignalIntent };
2511
- //# sourceMappingURL=chunk-ORPPRRER.js.map
2512
- //# sourceMappingURL=chunk-ORPPRRER.js.map
2547
+ //# sourceMappingURL=chunk-NYG43ZIX.js.map
2548
+ //# sourceMappingURL=chunk-NYG43ZIX.js.map