@zkp2p/sdk 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  Stable TypeScript SDK for trustless fiat-to-crypto on Base. ZKP2P combines escrowed on-chain settlement, TLS attestations for payment verification, and API/indexer helpers so makers, takers, wallets, and embedded ramps can ship production-grade fiat liquidity flows without building their own contract or indexing stack.
8
8
 
9
- Current version: `0.1.0`
9
+ Current version: `0.2.3`
10
10
 
11
11
  ## Why This SDK
12
12
 
@@ -29,7 +29,7 @@ Current version: `0.1.0`
29
29
  - RPC-first reads: primary reads use ProtocolViewer and on-chain fallbacks, so `getDeposits()`, `getDeposit()`, `getIntents()`, `getIntent()`, and the `getPv*` methods are not blocked on indexer lag.
30
30
  - Indexer for history and filtering: use `client.indexer.*` for pagination, historical volumes, fund activities, daily snapshots, and vault analytics.
31
31
  - Current-stack routing: the client resolves against the upgraded escrow and orchestrator contracts, with historical escrow lookups available for reads and legacy deposits.
32
- - Modular internals: stable `0.1.0` extracted intent, vault, and ProtocolViewer logic into `IntentOperations`, `VaultOperations`, and `ProtocolViewerReader`, keeping `Zkp2pClient` focused on orchestration.
32
+ - Modular internals: intent, vault, and ProtocolViewer logic are extracted into `IntentOperations`, `VaultOperations`, and `ProtocolViewerReader`, keeping `Zkp2pClient` focused on orchestration.
33
33
  - App-level rollout control: the SDK is capability-based. Product gating and phase flags belong in your app layer, not inside transaction helpers.
34
34
 
35
35
  ## Installation
@@ -72,10 +72,14 @@ const client = new Zkp2pClient({
72
72
 
73
73
  - Supported runtime environments: `'production'`, `'preproduction'`, `'staging'`
74
74
  - `runtimeEnv` default: `'production'`
75
- - `apiKey`: optional curator API key for authenticated service endpoints
75
+ - `rpcUrl`: optional RPC URL override (defaults to wallet's chain RPC)
76
+ - `apiKey`: optional curator-issued API key — used when the SDK auto-fetches `signalIntent()` gating signatures and enables richer authenticated `getQuote()` responses with maker `depositData`; curator may also attach `skipTierEnforce` to trusted keys on hybrid intent-signing endpoints
76
77
  - `authorizationToken` / `getAuthorizationToken`: optional bearer auth for hybrid client and indexer flows
77
78
  - `indexerApiKey`: optional `x-api-key` for indexer proxy auth
78
79
  - `indexerUrl` and `baseApiUrl`: override defaults when you are targeting custom deployments
80
+ - `timeouts`: `{ api?: number }` — API timeout in milliseconds (default 15000)
81
+
82
+ **No API key is required to get started.** `createDeposit`, `registerPayeeDetails`, `getQuote`, `getTakerTier`, and the rest of the SDK work without `apiKey` or `authorizationToken`. The main tradeoff is that `signalIntent()` only auto-fetches a gating service signature from curator `/v3/intent` when `apiKey` or `authorizationToken` is available; otherwise provide both `gatingServiceSignature` and `signatureExpiration` manually if your integration needs one. Authenticated quotes also include richer maker `depositData`, and curator-issued API keys may carry `skipTierEnforce` on hybrid intent-signing endpoints.
79
83
 
80
84
  Indexer defaults by environment:
81
85
 
@@ -85,20 +89,20 @@ Indexer defaults by environment:
85
89
 
86
90
  ## Core Capabilities
87
91
 
88
- | Area | Stable surface |
89
- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
90
- | Deposits | `createDeposit`, `addFunds`, `removeFunds`, `withdrawDeposit`, `ensureAllowance`, `setAcceptingIntents`, `setIntentRange`, `setCurrencyMinRate`, `setRetainOnEmpty` |
91
- | Payment methods and currencies | `addPaymentMethods`, `removePaymentMethod`, `setPaymentMethodActive`, `addCurrencies`, `removeCurrency`, `deactivateCurrency`, `pruneExpiredIntents` |
92
- | Intents | `signalIntent`, `fulfillIntent`, `cancelIntent`, `releaseFundsToPayer`, `getFulfillIntentInputs` |
93
- | Prepared transactions | `client.prepareCreateDeposit(...)`, `client.signalIntent.prepare(...)`, `client.fulfillIntent.prepare(...)`, `client.setVaultFee.prepare(...)`, and equivalent prepare flows across the rest of the prepareable write surface |
94
- | Payee and quote APIs | `registerPayeeDetails`, `resolvePayeeHash`, `getQuote`, `getTakerTier` |
95
- | Delegation and hooks | `setDelegate`, `removeDelegate`, `setRateManager`, `clearRateManager`, `setDepositRateManager`, `clearDepositRateManager`, `setDepositPreIntentHook`, `setDepositWhitelistHook` |
96
- | Vault / DRM | `createRateManager`, `setVaultMinRate`, `setVaultMinRatesBatch`, `setVaultFee`, `setVaultConfig`, `getDepositRateManager`, `getManagerFee`, `getEffectiveRate` |
97
- | Oracle config | `setOracleRateConfig`, `setOracleRateConfigBatch`, `removeOracleRateConfig`, `updateCurrencyConfigBatch`, `deactivateCurrenciesBatch`, `supportsInlineOracleRateConfig`, `validateOracleFeedsOnChain` |
98
- | RPC reads | `getDeposits`, `getDeposit`, `getDepositsById`, `getIntents`, `getIntent`, `getPvDepositById`, `getPvDepositsFromIds`, `getPvAccountDeposits`, `getPvAccountIntents`, `getPvIntent` |
99
- | Indexer | `client.indexer.getDeposits`, `getDepositsWithRelations`, `getDepositById`, `getIntentFulfillmentAmounts`, `getDepositFundActivities`, `getDepositDailySnapshots`, `getRateManagers`, `getRateManagerDetail`, `getManagerDailySnapshots` |
100
- | React hooks | `@zkp2p/sdk/react` exports hooks for deposits, intents, delegation, vaults, payment methods, and taker tier |
101
- | Attribution | ERC-8021 helpers like `sendTransactionWithAttribution`, `encodeWithAttribution`, and `txOverrides.referrer` support |
92
+ | Area | Stable surface |
93
+ | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
94
+ | Deposits | `createDeposit`, `addFunds`, `removeFunds`, `withdrawDeposit`, `ensureAllowance`, `setAcceptingIntents`, `setIntentRange`, `setCurrencyMinRate`, `setRetainOnEmpty` |
95
+ | Payment methods and currencies | `addPaymentMethods`, `removePaymentMethod`, `setPaymentMethodActive`, `addCurrencies`, `removeCurrency`, `deactivateCurrency`, `pruneExpiredIntents` |
96
+ | Intents | `signalIntent`, `fulfillIntent`, `cancelIntent`, `releaseFundsToPayer`, `getFulfillIntentInputs` |
97
+ | Prepared transactions | `client.prepareCreateDeposit(...)`, `client.signalIntent.prepare(...)`, `client.fulfillIntent.prepare(...)`, `client.setVaultFee.prepare(...)`, and equivalent prepare flows across the rest of the prepareable write surface |
98
+ | Payee and quote APIs | `registerPayeeDetails`, `resolvePayeeHash`, `getQuote`, `getTakerTier` |
99
+ | Delegation and hooks | `setDelegate`, `removeDelegate`, `setRateManager`, `clearRateManager`, `setDepositRateManager`, `clearDepositRateManager`, `setDepositPreIntentHook`, `setDepositWhitelistHook` |
100
+ | Vault / DRM | `createRateManager`, `setVaultMinRate`, `setVaultMinRatesBatch`, `setVaultFee`, `setVaultConfig`, `getDepositRateManager`, `getManagerFee`, `getEffectiveRate` |
101
+ | Oracle config | `setOracleRateConfig`, `setOracleRateConfigBatch`, `removeOracleRateConfig`, `updateCurrencyConfigBatch`, `deactivateCurrenciesBatch`, `supportsInlineOracleRateConfig`, `validateOracleFeedsOnChain` |
102
+ | RPC reads | `getDeposits`, `getDeposit`, `getDepositsById`, `getIntents`, `getIntent`, `getPvDepositById`, `getPvDepositsFromIds`, `getPvAccountDeposits`, `getPvAccountIntents`, `getPvIntent` |
103
+ | Indexer | `client.indexer.getDeposits`, `getDepositsWithRelations`, `getDepositById`, `getDepositsByIds`, `getDepositsByIdsWithRelations`, `getDepositsByPayeeHash`, `getIntentsForDeposits`, `getOwnerIntents`, `getIntentsByRateManager`, `getIntentByHash`, `getExpiredIntents`, `getFulfilledIntentEvents`, `getIntentFulfillmentAmounts`, `getFulfillmentAndPayment`, `getDepositFundActivities`, `getMakerFundActivities`, `getDepositDailySnapshots`, `getProfitSnapshotsByDeposits`, `getRateManagers`, `getRateManagerDetail`, `getRateManagerDelegations`, `getDelegationForDeposit`, `getManagerDailySnapshots`, `getManualRateUpdates`, `getOracleConfigUpdates`, `query` |
104
+ | React hooks | `@zkp2p/sdk/react` exports hooks for deposits, intents, delegation, vaults, payment methods, and taker tier |
105
+ | Attribution | ERC-8021 helpers like `sendTransactionWithAttribution`, `encodeWithAttribution`, and `txOverrides.referrer` support |
102
106
 
103
107
  ## Create a Deposit
104
108
 
@@ -385,35 +389,77 @@ You can also use the convenience wrappers `getDeposits()`, `getDeposit()`, `getI
385
389
 
386
390
  ## Indexer Queries
387
391
 
388
- Use the indexer for filtered queries, pagination, fund activity history, snapshots, and vault analytics.
392
+ Use the indexer for filtered queries, pagination, fund activity history, snapshots, and vault analytics. All methods live on the flat `client.indexer.*` namespace.
389
393
 
390
394
  ```ts
395
+ // Deposit queries
391
396
  const deposits = await client.indexer.getDeposits(
392
397
  { status: 'ACTIVE', depositor: '0xMaker' },
393
398
  { limit: 25, orderBy: 'updatedAt', orderDirection: 'desc' },
394
399
  );
395
-
396
- const depositWithRelations = await client.indexer.getDepositById('8453_0xEscrowAddress_42', {
400
+ const depositsWithRelations = await client.indexer.getDepositsWithRelations(
401
+ { status: 'ACTIVE' },
402
+ { limit: 10 },
403
+ { includeIntents: true },
404
+ );
405
+ const deposit = await client.indexer.getDepositById('8453_0xEscrowAddress_42', {
406
+ includeIntents: true,
407
+ });
408
+ const depositsByIds = await client.indexer.getDepositsByIds(['8453_0xEscrow_42']);
409
+ const depositsByIdsWithRelations = await client.indexer.getDepositsByIdsWithRelations(
410
+ ['8453_0xEscrow_42'],
411
+ { includeIntents: true },
412
+ );
413
+ const depositsByPayee = await client.indexer.getDepositsByPayeeHash('0xPayeeHash', {
414
+ paymentMethodHash: '0x...',
415
+ limit: 10,
397
416
  includeIntents: true,
398
417
  });
399
418
 
419
+ // Intent queries
420
+ const intentsForDeposits = await client.indexer.getIntentsForDeposits(
421
+ ['8453_0xEscrow_42'],
422
+ ['SIGNALED'],
423
+ );
424
+ const ownerIntents = await client.indexer.getOwnerIntents('0xTaker', ['SIGNALED', 'FULFILLED']);
425
+ const intentsByVault = await client.indexer.getIntentsByRateManager('0xVaultId');
426
+ const intent = await client.indexer.getIntentByHash('0xIntentHash');
427
+ const expiredIntents = await client.indexer.getExpiredIntents({
428
+ now: BigInt(Math.floor(Date.now() / 1000)),
429
+ depositIds: ['8453_0xEscrow_42'],
430
+ });
431
+ const fulfilledEvents = await client.indexer.getFulfilledIntentEvents(['0xIntentHash']);
400
432
  const fulfillment = await client.indexer.getIntentFulfillmentAmounts('0xIntentHash');
433
+ const fulfillmentAndPayment = await client.indexer.getFulfillmentAndPayment('0xIntentHash');
434
+
435
+ // Fund activity and snapshots
401
436
  const fundActivities = await client.indexer.getDepositFundActivities('8453_0xEscrowAddress_42');
437
+ const makerActivities = await client.indexer.getMakerFundActivities('0xMaker', 50);
402
438
  const snapshots = await client.indexer.getDepositDailySnapshots('8453_0xEscrowAddress_42', 30);
439
+ const profitSnapshots = await client.indexer.getProfitSnapshotsByDeposits(['8453_0xEscrow_42']);
403
440
 
441
+ // Rate manager (vault) queries
404
442
  const managers = await client.indexer.getRateManagers({
405
443
  limit: 10,
406
444
  orderBy: 'currentDelegatedBalance',
407
445
  orderDirection: 'desc',
408
446
  });
409
-
410
447
  const managerDetail = await client.indexer.getRateManagerDetail('0xVaultId', {
411
448
  rateManagerAddress: '0xVaultAddress',
449
+ statsLimit: 30,
450
+ });
451
+ const delegations = await client.indexer.getRateManagerDelegations('0xVaultId');
452
+ const delegation = await client.indexer.getDelegationForDeposit('8453_0xEscrow_42');
453
+ const managerSnapshots = await client.indexer.getManagerDailySnapshots('0xVaultId');
454
+ const manualRates = await client.indexer.getManualRateUpdates('0xVaultId');
455
+ const oracleUpdates = await client.indexer.getOracleConfigUpdates('0xVaultId');
456
+
457
+ // Raw GraphQL
458
+ const custom = await client.indexer.query<MyType>({
459
+ query: '{ deposits(limit: 5) { id } }',
412
460
  });
413
461
  ```
414
462
 
415
- `managerDetail?.aggregate` gives you current delegated balance and filled volume stats alongside recent snapshots and delegation history.
416
-
417
463
  ## React Hooks
418
464
 
419
465
  Install React and import hooks from `@zkp2p/sdk/react`. React is an optional peer dependency of the SDK.
@@ -494,7 +540,7 @@ const hash = await client.signalIntent({
494
540
  });
495
541
  ```
496
542
 
497
- Lower-level helpers are also exported: `BASE_BUILDER_CODE`, `getAttributionDataSuffix()`, `appendAttributionToCalldata()`, `encodeWithAttribution()`, and `sendTransactionWithAttribution()`.
543
+ Lower-level helpers are also exported: `BASE_BUILDER_CODE`, `ZKP2P_IOS_REFERRER`, `ZKP2P_ANDROID_REFERRER`, `getAttributionDataSuffix()`, `appendAttributionToCalldata()`, `encodeWithAttribution()`, and `sendTransactionWithAttribution()`.
498
544
 
499
545
  ## TypeDoc API Reference
500
546
 
package/dist/index.cjs CHANGED
@@ -1099,15 +1099,9 @@ var init_protocolViewerParsers = __esm({
1099
1099
 
1100
1100
  // src/client/clientUtils.ts
1101
1101
  init_bigint();
1102
+
1103
+ // src/utils/address.ts
1102
1104
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
1103
- var MIN_ORACLE_SPREAD_BPS = -32768;
1104
- var MAX_ORACLE_SPREAD_BPS = 32767;
1105
- var EMPTY_ORACLE_RATE_CONFIG = {
1106
- adapter: ZERO_ADDRESS,
1107
- adapterConfig: "0x",
1108
- spreadBps: 0,
1109
- maxStaleness: 0
1110
- };
1111
1105
  var isValidHexAddress = (addr) => {
1112
1106
  if (typeof addr !== "string") return false;
1113
1107
  return /^0x[0-9a-fA-F]{40}$/.test(addr);
@@ -1116,6 +1110,16 @@ var normalizeAddress = (addr) => {
1116
1110
  if (!isValidHexAddress(addr)) return void 0;
1117
1111
  return addr;
1118
1112
  };
1113
+
1114
+ // src/client/clientUtils.ts
1115
+ var MIN_ORACLE_SPREAD_BPS = -32768;
1116
+ var MAX_ORACLE_SPREAD_BPS = 32767;
1117
+ var EMPTY_ORACLE_RATE_CONFIG = {
1118
+ adapter: ZERO_ADDRESS,
1119
+ adapterConfig: "0x",
1120
+ spreadBps: 0,
1121
+ maxStaleness: 0
1122
+ };
1119
1123
  var parseEscrowAddressFromCompositeDepositId = (depositId) => {
1120
1124
  if (typeof depositId !== "string") return void 0;
1121
1125
  const parts = depositId.split("_");
@@ -1422,9 +1426,6 @@ function parseAPIError(response, responseText) {
1422
1426
  } catch {
1423
1427
  if (responseText && responseText.length < 200) message = responseText;
1424
1428
  }
1425
- if (response.status === 429) {
1426
- message = "Too many requests. Please try again later.";
1427
- }
1428
1429
  return new exports.APIError(message, response.status, { url: response.url });
1429
1430
  }
1430
1431
  async function withRetry(fn, maxRetries = 3, delayMs = 1e3, timeoutMs) {
@@ -1488,11 +1489,13 @@ async function apiSignIntentV3(request, opts) {
1488
1489
  const sig = json?.responseObject?.signedIntent;
1489
1490
  const expStr = json?.responseObject?.intentData?.signatureExpiration ?? json?.responseObject?.signatureExpiration;
1490
1491
  const preIntentHookData = json?.responseObject?.intentData?.preIntentHookData ?? json?.responseObject?.preIntentHookData;
1492
+ const referralFees = json?.responseObject?.intentData?.referralFees ?? json?.responseObject?.referralFees;
1491
1493
  if (!sig || !expStr) throw new Error("v3/intent missing signature or expiration");
1492
1494
  return {
1493
1495
  signature: sig,
1494
1496
  signatureExpiration: BigInt(expStr),
1495
- preIntentHookData
1497
+ preIntentHookData,
1498
+ referralFees
1496
1499
  };
1497
1500
  }
1498
1501
 
@@ -1919,7 +1922,7 @@ var IntentOperations = class {
1919
1922
  const depositId = parseRawDepositId(params.depositId);
1920
1923
  const amount = typeof params.amount === "bigint" ? params.amount : BigInt(params.amount);
1921
1924
  const conversionRate = typeof params.conversionRate === "bigint" ? params.conversionRate : BigInt(params.conversionRate);
1922
- const referralFees = referrerFeeConfig !== void 0 ? [
1925
+ let referralFees = referrerFeeConfig !== void 0 ? [
1923
1926
  {
1924
1927
  recipient: referrerFeeConfig.recipient,
1925
1928
  fee: referrerFeeConfigToPreciseUnits(referrerFeeConfig)
@@ -1961,6 +1964,23 @@ var IntentOperations = class {
1961
1964
  gatingServiceSignature = response.signature;
1962
1965
  signatureExpiration = response.signatureExpiration;
1963
1966
  preIntentHookData = response.preIntentHookData ?? preIntentHookData;
1967
+ if (response.referralFees !== void 0) {
1968
+ referralFees = response.referralFees.map((referralFee) => {
1969
+ if (!isValidReferrerFeeRecipient(referralFee.recipient)) {
1970
+ throw new Error("v3/intent returned invalid referral fee recipient");
1971
+ }
1972
+ let fee;
1973
+ try {
1974
+ fee = BigInt(referralFee.fee);
1975
+ } catch {
1976
+ throw new Error("v3/intent returned non-integer referral fee value");
1977
+ }
1978
+ return {
1979
+ recipient: referralFee.recipient,
1980
+ fee
1981
+ };
1982
+ });
1983
+ }
1964
1984
  }
1965
1985
  if (!gatingServiceSignature || !signatureExpiration) {
1966
1986
  throw new Error("Missing gatingServiceSignature/signatureExpiration");
@@ -3461,6 +3481,7 @@ var DEPOSIT_FIELDS = `
3461
3481
  timestamp
3462
3482
  txHash
3463
3483
  updatedAt
3484
+ whitelistHookAddress
3464
3485
  `;
3465
3486
  var LEGACY_DEPOSIT_FIELDS = `
3466
3487
  id
@@ -4451,6 +4472,35 @@ var DEPOSIT_DAILY_SNAPSHOTS_QUERY = (
4451
4472
  }
4452
4473
  `
4453
4474
  );
4475
+ var PROFIT_SNAPSHOTS_BY_DEPOSITS_QUERY = (
4476
+ /* GraphQL */
4477
+ `
4478
+ query GetProfitSnapshotsByDeposits($depositIds: [String!]) {
4479
+ profitSnapshots: MakerProfitSnapshot(
4480
+ where: { depositId: { _in: $depositIds } }
4481
+ order_by: { createdAt: desc }
4482
+ ) {
4483
+ id
4484
+ chainId
4485
+ maker
4486
+ intentId
4487
+ depositId
4488
+ fiatCurrency
4489
+ quoteConversionRate
4490
+ oracleRate
4491
+ spreadBps
4492
+ amount
4493
+ notionalFiatUsdCents
4494
+ feeUsd
4495
+ realizedProfitUsdCents
4496
+ priceSnapshotId
4497
+ status
4498
+ createdAt
4499
+ updatedAt
4500
+ }
4501
+ }
4502
+ `
4503
+ );
4454
4504
  var FULFILLMENT_AND_PAYMENT_QUERY = (
4455
4505
  /* GraphQL */
4456
4506
  `
@@ -4560,9 +4610,10 @@ function convertIndexerDepositToEscrowView(deposit, _chainId, _escrowAddress) {
4560
4610
  verifiers
4561
4611
  };
4562
4612
  }
4563
- function convertDepositsForLiquidity(deposits, chainId, escrowAddress) {
4613
+ function convertDepositsForLiquidity(deposits, chainId, escrowAddress, options = {}) {
4614
+ const { includePrivateOrderbooks = false } = options;
4564
4615
  return deposits.filter(
4565
- (d) => d.depositor && d.depositor.toLowerCase() !== ZERO && d.acceptingIntents && toBigInt(d.remainingDeposits) > 0n && d.status === "ACTIVE"
4616
+ (d) => d.depositor && d.depositor.toLowerCase() !== ZERO && (includePrivateOrderbooks || normalizeAddress2(d.whitelistHookAddress).toLowerCase() === ZERO) && d.acceptingIntents && toBigInt(d.remainingDeposits) > 0n && d.status === "ACTIVE"
4566
4617
  ).map((d) => convertIndexerDepositToEscrowView(d));
4567
4618
  }
4568
4619
  function convertIndexerIntentsToEscrowViews(intents, depositViewsById) {
@@ -4678,14 +4729,16 @@ var IndexerDepositService = class {
4678
4729
  const where = {};
4679
4730
  if (params.depositIds?.length) where.depositId = { _in: params.depositIds };
4680
4731
  if (params.owner) where.owner = { _ilike: params.owner };
4732
+ if (params.rateManagerId) where.rateManagerId = { _ilike: params.rateManagerId };
4681
4733
  if (params.statuses?.length) where.status = { _in: params.statuses };
4682
4734
  if (!Object.keys(where).length) return [];
4735
+ const orderByField = params.orderByField ?? "signalTimestamp";
4683
4736
  const result = await this.queryWithLegacyFallback({
4684
4737
  query: INTENTS_QUERY,
4685
4738
  legacyQuery: LEGACY_INTENTS_QUERY,
4686
4739
  variables: {
4687
4740
  where,
4688
- order_by: [{ signalTimestamp: "desc" }],
4741
+ order_by: [{ [orderByField]: "desc" }],
4689
4742
  limit: params.limit,
4690
4743
  offset: params.offset
4691
4744
  }
@@ -4748,6 +4801,16 @@ var IndexerDepositService = class {
4748
4801
  if (!owner) return [];
4749
4802
  return this.fetchIntents({ owner, statuses });
4750
4803
  }
4804
+ async fetchIntentsByRateManager(rateManagerId, statuses) {
4805
+ const normalizedRateManagerId = rateManagerId?.trim();
4806
+ if (!normalizedRateManagerId) return [];
4807
+ return this.fetchIntents({
4808
+ rateManagerId: normalizedRateManagerId,
4809
+ statuses,
4810
+ limit: 500,
4811
+ orderByField: "fulfillTimestamp"
4812
+ });
4813
+ }
4751
4814
  async fetchIntentByHash(intentHash) {
4752
4815
  if (!intentHash) return null;
4753
4816
  const result = await this.queryWithLegacyFallback({
@@ -4969,6 +5032,26 @@ var IndexerDepositService = class {
4969
5032
  return [];
4970
5033
  }
4971
5034
  }
5035
+ async fetchProfitSnapshotsByDeposits(depositIds) {
5036
+ const normalizedDepositIds = Array.from(
5037
+ new Set(
5038
+ depositIds.map((depositId) => depositId?.trim()).filter((depositId) => Boolean(depositId))
5039
+ )
5040
+ );
5041
+ if (!normalizedDepositIds.length) return [];
5042
+ try {
5043
+ const result = await this.client.query({
5044
+ query: PROFIT_SNAPSHOTS_BY_DEPOSITS_QUERY,
5045
+ variables: { depositIds: normalizedDepositIds }
5046
+ });
5047
+ return result.profitSnapshots ?? result.MakerProfitSnapshot ?? [];
5048
+ } catch (error) {
5049
+ if (!isSchemaCompatibilityError(error)) {
5050
+ throw error;
5051
+ }
5052
+ return [];
5053
+ }
5054
+ }
4972
5055
  };
4973
5056
 
4974
5057
  // src/indexer/rateManagerService.ts
@@ -5865,13 +5948,11 @@ function convertIndexerDepositToLegacyApiDeposit(deposit) {
5865
5948
  verifiers
5866
5949
  };
5867
5950
  }
5868
- async function apiPostDepositDetails(req, baseApiUrl, timeoutMs, apiKey, authToken) {
5951
+ async function apiPostDepositDetails(req, baseApiUrl, timeoutMs, _apiKey, _authToken) {
5869
5952
  return apiFetch({
5870
5953
  url: `${withApiBase(baseApiUrl)}/v1/makers/create`,
5871
5954
  method: "POST",
5872
5955
  body: req,
5873
- apiKey,
5874
- authToken,
5875
5956
  timeoutMs
5876
5957
  });
5877
5958
  }
@@ -5881,13 +5962,25 @@ async function apiGetQuote(req, baseApiUrl, timeoutMs, apiKey, authToken) {
5881
5962
  throw new exports.ValidationError("quotesToReturn must be a positive integer", "quotesToReturn");
5882
5963
  }
5883
5964
  }
5965
+ if (!isValidHexAddress(req.user)) {
5966
+ throw new exports.ValidationError("user must be a valid Ethereum address", "user");
5967
+ }
5968
+ if (!isValidHexAddress(req.recipient)) {
5969
+ throw new exports.ValidationError("recipient must be a valid Ethereum address", "recipient");
5970
+ }
5971
+ if (!isValidHexAddress(req.destinationToken)) {
5972
+ throw new exports.ValidationError(
5973
+ "destinationToken must be a valid Ethereum address",
5974
+ "destinationToken"
5975
+ );
5976
+ }
5884
5977
  const isExactFiat = req.isExactFiat !== false;
5885
5978
  const endpoint = isExactFiat ? "exact-fiat" : "exact-token";
5886
5979
  let url = `${withApiBase(baseApiUrl)}/v2/quote/${endpoint}`;
5887
5980
  if (req.quotesToReturn) url += `?quotesToReturn=${req.quotesToReturn}`;
5888
5981
  const requestBody = {
5889
5982
  ...req,
5890
- [isExactFiat ? "exactFiatAmount" : "exactTokenAmount"]: req.amount,
5983
+ [isExactFiat ? "exactFiatAmount" : "exactTokenAmount"]: String(req.amount),
5891
5984
  amount: void 0,
5892
5985
  isExactFiat: void 0,
5893
5986
  quotesToReturn: void 0
@@ -5902,6 +5995,29 @@ async function apiGetQuote(req, baseApiUrl, timeoutMs, apiKey, authToken) {
5902
5995
  timeoutMs
5903
5996
  });
5904
5997
  }
5998
+ async function apiGetQuotesBestByPlatform(req, baseApiUrl, timeoutMs, apiKey, authToken) {
5999
+ const isExactFiat = req.isExactFiat !== false;
6000
+ const endpoint = isExactFiat ? "best-by-platform" : "best-by-platform-exact-token";
6001
+ const url = `${withApiBase(baseApiUrl)}/v2/quote/${endpoint}`;
6002
+ const requestBody = {
6003
+ ...req,
6004
+ [isExactFiat ? "exactFiatAmount" : "exactTokenAmount"]: String(req.amount),
6005
+ amount: void 0,
6006
+ isExactFiat: void 0,
6007
+ referrerFeeConfig: void 0
6008
+ };
6009
+ Object.keys(requestBody).forEach(
6010
+ (key) => requestBody[key] === void 0 && delete requestBody[key]
6011
+ );
6012
+ return apiFetch({
6013
+ url,
6014
+ method: "POST",
6015
+ body: requestBody,
6016
+ apiKey,
6017
+ authToken,
6018
+ timeoutMs
6019
+ });
6020
+ }
5905
6021
  async function apiGetPayeeDetails(req, apiKey, baseApiUrl, authToken, timeoutMs) {
5906
6022
  return apiFetch({
5907
6023
  url: `${baseApiUrl.replace(/\/$/, "")}/v1/makers/${req.processorName}/${req.hashedOnchainId}`,
@@ -5968,7 +6084,6 @@ async function apiGetTakerTier(req, apiKey, baseApiUrl, timeoutMs) {
5968
6084
  return apiFetch({
5969
6085
  url: `${withApiBase(baseApiUrl)}${endpoint}`,
5970
6086
  method: "GET",
5971
- apiKey,
5972
6087
  timeoutMs
5973
6088
  });
5974
6089
  }
@@ -6070,6 +6185,23 @@ var appendReferrerFeeDisplayFields = (quoteResponse, referrerFeeConfig) => {
6070
6185
  }
6071
6186
  };
6072
6187
  };
6188
+ var appendReferrerFeeDisplayFieldsToBestByPlatform = (quoteResponse, referrerFeeConfig) => {
6189
+ if (!referrerFeeConfig) {
6190
+ return quoteResponse;
6191
+ }
6192
+ const decimals = quoteResponse.responseObject?.token?.decimals ?? 6;
6193
+ const enrichedPlatformQuotes = (quoteResponse.responseObject?.platformQuotes ?? []).map((platformQuote) => ({
6194
+ ...platformQuote,
6195
+ bestQuote: platformQuote.available && platformQuote.bestQuote ? applyReferrerFeeDisplayFieldsToQuote(platformQuote.bestQuote, referrerFeeConfig, decimals) : platformQuote.bestQuote
6196
+ }));
6197
+ return {
6198
+ ...quoteResponse,
6199
+ responseObject: {
6200
+ ...quoteResponse.responseObject,
6201
+ platformQuotes: enrichedPlatformQuotes
6202
+ }
6203
+ };
6204
+ };
6073
6205
 
6074
6206
  // src/utils/erc20.ts
6075
6207
  var ERC20_ABI = [
@@ -6642,7 +6774,9 @@ var Zkp2pClient = class {
6642
6774
  * sending fiat payment to the deposit's payee.
6643
6775
  *
6644
6776
  * If `gatingServiceSignature` is not provided, the SDK will automatically
6645
- * fetch one from the API (requires `apiKey` or `authorizationToken`).
6777
+ * fetch one from curator `/v3/intent` when `apiKey` or `authorizationToken`
6778
+ * is available. Otherwise you must provide `gatingServiceSignature` and
6779
+ * `signatureExpiration` yourself.
6646
6780
  *
6647
6781
  * **Prepare Mode**: Use `.prepare()` to get the transaction calldata without sending:
6648
6782
  * ```typescript
@@ -7766,6 +7900,12 @@ var Zkp2pClient = class {
7766
7900
  getOwnerIntents: (owner, statuses) => {
7767
7901
  return service.fetchIntentsByOwner(owner, statuses);
7768
7902
  },
7903
+ /**
7904
+ * Fetches fulfilled intents for a vault by rate manager ID.
7905
+ */
7906
+ getIntentsByRateManager: (rateManagerId, statuses) => {
7907
+ return service.fetchIntentsByRateManager(rateManagerId, statuses);
7908
+ },
7769
7909
  /**
7770
7910
  * Fetches a single intent by hash.
7771
7911
  */
@@ -7816,6 +7956,12 @@ var Zkp2pClient = class {
7816
7956
  getDepositsByIdsWithRelations: (ids, options) => {
7817
7957
  return service.fetchDepositsByIdsWithRelations(ids, options);
7818
7958
  },
7959
+ /**
7960
+ * Fetches maker profit snapshots for the provided deposits.
7961
+ */
7962
+ getProfitSnapshotsByDeposits: (depositIds) => {
7963
+ return service.fetchProfitSnapshotsByDeposits(depositIds);
7964
+ },
7819
7965
  /**
7820
7966
  * Fetches rate managers (vaults) with aggregate stats.
7821
7967
  */
@@ -7969,15 +8115,7 @@ var Zkp2pClient = class {
7969
8115
  })
7970
8116
  );
7971
8117
  const apiResponses = await Promise.all(
7972
- depositDetails.map(
7973
- (req) => apiPostDepositDetails(
7974
- req,
7975
- baseApiUrl,
7976
- this.apiTimeoutMs,
7977
- this.apiKey,
7978
- this.authorizationToken
7979
- )
7980
- )
8118
+ depositDetails.map((req) => apiPostDepositDetails(req, baseApiUrl, this.apiTimeoutMs))
7981
8119
  );
7982
8120
  if (!apiResponses.every((r) => r?.success)) {
7983
8121
  const failed = apiResponses.find((r) => !r?.success);
@@ -8104,15 +8242,7 @@ var Zkp2pClient = class {
8104
8242
  } else {
8105
8243
  const baseApiUrl = (this.baseApiUrl ?? "https://api.zkp2p.xyz").replace(/\/$/, "");
8106
8244
  const apiResponses = await Promise.all(
8107
- depositDetails.map(
8108
- (req) => apiPostDepositDetails(
8109
- req,
8110
- baseApiUrl,
8111
- this.apiTimeoutMs,
8112
- this.apiKey,
8113
- this.authorizationToken
8114
- )
8115
- )
8245
+ depositDetails.map((req) => apiPostDepositDetails(req, baseApiUrl, this.apiTimeoutMs))
8116
8246
  );
8117
8247
  if (!apiResponses.every((r) => r?.success)) {
8118
8248
  const failed = apiResponses.find((r) => !r?.success);
@@ -8315,6 +8445,57 @@ var Zkp2pClient = class {
8315
8445
  }
8316
8446
  return appendReferrerFeeDisplayFields(quote, referrerFeeConfig);
8317
8447
  }
8448
+ /**
8449
+ * **Supporting Method** - Fetches the best available quote per supported payment platform.
8450
+ *
8451
+ * Returns one quote per platform when available. When authenticated, the API
8452
+ * returns payee details in each platform's best quote.
8453
+ *
8454
+ * @param req - Best-by-platform quote request parameters
8455
+ * @param opts - Optional overrides for API URL and timeout
8456
+ * @returns Best-by-platform quote response
8457
+ */
8458
+ async getQuotesBestByPlatform(req, opts) {
8459
+ const referrerFeeConfig = assertValidReferrerFeeConfig(
8460
+ req.referrerFeeConfig,
8461
+ "getQuotesBestByPlatform"
8462
+ );
8463
+ const baseApiUrl = (opts?.baseApiUrl ?? this.baseApiUrl ?? "https://api.zkp2p.xyz").replace(
8464
+ /\/$/,
8465
+ ""
8466
+ );
8467
+ const timeoutMs = opts?.timeoutMs ?? this.apiTimeoutMs;
8468
+ const reqWithEscrow = { ...req };
8469
+ if (!reqWithEscrow.escrowAddresses || reqWithEscrow.escrowAddresses.length === 0) {
8470
+ const configuredEscrows = this.escrowAddresses.length > 0 ? [...this.escrowAddresses] : this.escrowAddress ? [this.escrowAddress] : [];
8471
+ if (configuredEscrows.length > 0) {
8472
+ reqWithEscrow.escrowAddresses = configuredEscrows;
8473
+ }
8474
+ }
8475
+ const quote = await apiGetQuotesBestByPlatform(
8476
+ reqWithEscrow,
8477
+ baseApiUrl,
8478
+ timeoutMs,
8479
+ this.apiKey,
8480
+ this.authorizationToken
8481
+ );
8482
+ const enrichedQuote = quote ? {
8483
+ ...quote,
8484
+ responseObject: {
8485
+ ...quote.responseObject,
8486
+ platformQuotes: (quote.responseObject?.platformQuotes ?? []).map((platformQuote) => {
8487
+ const bestQuote = platformQuote?.bestQuote;
8488
+ const makerDepositData = bestQuote?.maker?.depositData;
8489
+ if (!bestQuote || !makerDepositData) return platformQuote;
8490
+ return {
8491
+ ...platformQuote,
8492
+ bestQuote: { ...bestQuote, payeeData: makerDepositData }
8493
+ };
8494
+ })
8495
+ }
8496
+ } : quote;
8497
+ return appendReferrerFeeDisplayFieldsToBestByPlatform(enrichedQuote, referrerFeeConfig);
8498
+ }
8318
8499
  // ───────────────────────────────────────────────────────────────────────────
8319
8500
  // SUPPORTING: TAKER TIER
8320
8501
  // (Used by frontends to display taker limits)
@@ -8334,7 +8515,7 @@ var Zkp2pClient = class {
8334
8515
  ""
8335
8516
  );
8336
8517
  const timeoutMs = opts?.timeoutMs ?? this.apiTimeoutMs;
8337
- return apiGetTakerTier(req, this.apiKey, baseApiUrl, timeoutMs);
8518
+ return apiGetTakerTier(req, void 0, baseApiUrl, timeoutMs);
8338
8519
  }
8339
8520
  // ╔═══════════════════════════════════════════════════════════════════════════╗
8340
8521
  // ║ CORE: ON-CHAIN DEPOSIT VIEWS ║
@@ -8764,6 +8945,7 @@ exports.ZKP2P_IOS_REFERRER = ZKP2P_IOS_REFERRER;
8764
8945
  exports.Zkp2pClient = Zkp2pClient;
8765
8946
  exports.apiGetOwnerDeposits = apiGetOwnerDeposits;
8766
8947
  exports.apiGetPayeeDetails = apiGetPayeeDetails;
8948
+ exports.apiGetQuotesBestByPlatform = apiGetQuotesBestByPlatform;
8767
8949
  exports.apiGetTakerTier = apiGetTakerTier;
8768
8950
  exports.apiPostDepositDetails = apiPostDepositDetails;
8769
8951
  exports.apiValidatePayeeDetails = apiValidatePayeeDetails;