@zkp2p/sdk 0.2.4 → 0.3.1

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.2.3`
9
+ Current version: `0.3.1`
10
10
 
11
11
  ## Why This SDK
12
12
 
@@ -73,13 +73,13 @@ const client = new Zkp2pClient({
73
73
  - Supported runtime environments: `'production'`, `'preproduction'`, `'staging'`
74
74
  - `runtimeEnv` default: `'production'`
75
75
  - `rpcUrl`: optional RPC URL override (defaults to wallet's chain RPC)
76
- - `apiKey`: optional curator API key — enhances some responses (e.g. `getQuote` returns `depositData` when authenticated) but is **not required** for any SDK method
76
+ - `apiKey`: optional curator-issued API key — used when the SDK auto-fetches `signalIntent()` gating signatures and enables richer authenticated `getQuote()` responses with resolved maker payee details (`offchainId`, `telegramUsername`, `metadata`)
77
77
  - `authorizationToken` / `getAuthorizationToken`: optional bearer auth for hybrid client and indexer flows
78
78
  - `indexerApiKey`: optional `x-api-key` for indexer proxy auth
79
79
  - `indexerUrl` and `baseApiUrl`: override defaults when you are targeting custom deployments
80
80
  - `timeouts`: `{ api?: number }` — API timeout in milliseconds (default 15000)
81
81
 
82
- **No API key is required to get started.** `createDeposit`, `registerPayeeDetails`, `getQuote`, `getTakerTier`, and all other SDK methods work without `apiKey` or `authorizationToken`. Auth credentials are optional and only affect response richness (e.g. authenticated quotes include maker `depositData`).
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/sign` when `apiKey` or `authorizationToken` is available; otherwise provide both `gatingServiceSignature` and `signatureExpiration` manually if your integration needs one. Authenticated quotes also include resolved maker payee details (`offchainId`, `telegramUsername`, `metadata`).
83
83
 
84
84
  Indexer defaults by environment:
85
85
 
@@ -95,7 +95,7 @@ Indexer defaults by environment:
95
95
  | Payment methods and currencies | `addPaymentMethods`, `removePaymentMethod`, `setPaymentMethodActive`, `addCurrencies`, `removeCurrency`, `deactivateCurrency`, `pruneExpiredIntents` |
96
96
  | Intents | `signalIntent`, `fulfillIntent`, `cancelIntent`, `releaseFundsToPayer`, `getFulfillIntentInputs` |
97
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` |
98
+ | Payee and quote APIs | `registerPayeeDetails`, `resolvePayeeHash`, `getQuote`, `getQuotesBestByPlatform`, `getTakerTier` |
99
99
  | Delegation and hooks | `setDelegate`, `removeDelegate`, `setRateManager`, `clearRateManager`, `setDepositRateManager`, `clearDepositRateManager`, `setDepositPreIntentHook`, `setDepositWhitelistHook` |
100
100
  | Vault / DRM | `createRateManager`, `setVaultMinRate`, `setVaultMinRatesBatch`, `setVaultFee`, `setVaultConfig`, `getDepositRateManager`, `getManagerFee`, `getEffectiveRate` |
101
101
  | Oracle config | `setOracleRateConfig`, `setOracleRateConfigBatch`, `removeOracleRateConfig`, `updateCurrencyConfigBatch`, `deactivateCurrenciesBatch`, `supportsInlineOracleRateConfig`, `validateOracleFeedsOnChain` |
@@ -156,7 +156,7 @@ const payeeHash = await client.resolvePayeeHash(
156
156
  );
157
157
  ```
158
158
 
159
- `getQuote()` returns available liquidity plus payee details when authenticated. `getTakerTier()` returns limits and cooldown data for taker UX.
159
+ `getQuote()` returns available liquidity plus payee details when authenticated. Use `getQuotesBestByPlatform()` to fetch the best quote per supported payment platform in a single call (handy for cross-platform comparison UIs). `getTakerTier()` returns limits and cooldown data for taker UX.
160
160
 
161
161
  ## Signal, Fulfill, and Release Intents
162
162
 
@@ -519,7 +519,7 @@ The SDK ships currency metadata for 34 fiat currencies:
519
519
 
520
520
  ## Supported Payment Platforms
521
521
 
522
- `wise`, `venmo`, `revolut`, `cashapp`, `mercadopago`, `zelle`, `paypal`, `monzo`, `chime`, `luxon`, `n26`
522
+ `wise`, `venmo`, `revolut`, `cashapp`, `mercadopago`, `zelle`, `paypal`, `monzo`, `chime`, `luxon`, `n26`, `alipay`
523
523
 
524
524
  ## Attribution (ERC-8021)
525
525
 
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) {
@@ -1459,7 +1460,7 @@ function createHeaders(apiKey, authorizationToken) {
1459
1460
  return headers2;
1460
1461
  }
1461
1462
  async function apiSignIntentV3(request, opts) {
1462
- const url = `${opts.baseApiUrl.replace(/\/$/, "")}/v3/intent`;
1463
+ const url = `${opts.baseApiUrl.replace(/\/$/, "")}/v3/intent/sign`;
1463
1464
  const json = await withRetry(
1464
1465
  async () => {
1465
1466
  let res;
@@ -1471,7 +1472,7 @@ async function apiSignIntentV3(request, opts) {
1471
1472
  });
1472
1473
  } catch (error) {
1473
1474
  throw new exports.NetworkError("Failed to connect to API server", {
1474
- endpoint: "/v3/intent",
1475
+ endpoint: "/v3/intent/sign",
1475
1476
  error
1476
1477
  });
1477
1478
  }
@@ -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;
1491
- if (!sig || !expStr) throw new Error("v3/intent missing signature or expiration");
1492
+ const referralFees = json?.responseObject?.intentData?.referralFees ?? json?.responseObject?.referralFees;
1493
+ if (!sig || !expStr) throw new Error("v3/intent/sign 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/sign returned invalid referral fee recipient");
1971
+ }
1972
+ let fee;
1973
+ try {
1974
+ fee = BigInt(referralFee.fee);
1975
+ } catch {
1976
+ throw new Error("v3/intent/sign 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");
@@ -4590,9 +4610,10 @@ function convertIndexerDepositToEscrowView(deposit, _chainId, _escrowAddress) {
4590
4610
  verifiers
4591
4611
  };
4592
4612
  }
4593
- function convertDepositsForLiquidity(deposits, chainId, escrowAddress) {
4613
+ function convertDepositsForLiquidity(deposits, chainId, escrowAddress, options = {}) {
4614
+ const { includePrivateOrderbooks = false } = options;
4594
4615
  return deposits.filter(
4595
- (d) => d.depositor && d.depositor.toLowerCase() !== ZERO && normalizeAddress2(d.whitelistHookAddress).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"
4596
4617
  ).map((d) => convertIndexerDepositToEscrowView(d));
4597
4618
  }
4598
4619
  function convertIndexerIntentsToEscrowViews(intents, depositViewsById) {
@@ -5927,13 +5948,11 @@ function convertIndexerDepositToLegacyApiDeposit(deposit) {
5927
5948
  verifiers
5928
5949
  };
5929
5950
  }
5930
- async function apiPostDepositDetails(req, baseApiUrl, timeoutMs, apiKey, authToken) {
5951
+ async function apiPostDepositDetails(req, baseApiUrl, timeoutMs, _apiKey, _authToken) {
5931
5952
  return apiFetch({
5932
- url: `${withApiBase(baseApiUrl)}/v1/makers/create`,
5953
+ url: `${withApiBase(baseApiUrl)}/v2/makers/create`,
5933
5954
  method: "POST",
5934
5955
  body: req,
5935
- apiKey,
5936
- authToken,
5937
5956
  timeoutMs
5938
5957
  });
5939
5958
  }
@@ -5943,16 +5962,29 @@ async function apiGetQuote(req, baseApiUrl, timeoutMs, apiKey, authToken) {
5943
5962
  throw new exports.ValidationError("quotesToReturn must be a positive integer", "quotesToReturn");
5944
5963
  }
5945
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
+ }
5946
5977
  const isExactFiat = req.isExactFiat !== false;
5947
5978
  const endpoint = isExactFiat ? "exact-fiat" : "exact-token";
5948
5979
  let url = `${withApiBase(baseApiUrl)}/v2/quote/${endpoint}`;
5949
5980
  if (req.quotesToReturn) url += `?quotesToReturn=${req.quotesToReturn}`;
5950
5981
  const requestBody = {
5951
5982
  ...req,
5952
- [isExactFiat ? "exactFiatAmount" : "exactTokenAmount"]: req.amount,
5983
+ [isExactFiat ? "exactFiatAmount" : "exactTokenAmount"]: String(req.amount),
5953
5984
  amount: void 0,
5954
5985
  isExactFiat: void 0,
5955
- quotesToReturn: void 0
5986
+ quotesToReturn: void 0,
5987
+ includePrivateOrderbooks: req.includePrivateOrderbooks
5956
5988
  };
5957
5989
  Object.keys(requestBody).forEach((k) => requestBody[k] === void 0 && delete requestBody[k]);
5958
5990
  return apiFetch({
@@ -5964,9 +5996,32 @@ async function apiGetQuote(req, baseApiUrl, timeoutMs, apiKey, authToken) {
5964
5996
  timeoutMs
5965
5997
  });
5966
5998
  }
5999
+ async function apiGetQuotesBestByPlatform(req, baseApiUrl, timeoutMs, apiKey, authToken) {
6000
+ const isExactFiat = req.isExactFiat !== false;
6001
+ const endpoint = isExactFiat ? "best-by-platform" : "best-by-platform-exact-token";
6002
+ const url = `${withApiBase(baseApiUrl)}/v2/quote/${endpoint}`;
6003
+ const requestBody = {
6004
+ ...req,
6005
+ [isExactFiat ? "exactFiatAmount" : "exactTokenAmount"]: String(req.amount),
6006
+ amount: void 0,
6007
+ isExactFiat: void 0,
6008
+ referrerFeeConfig: void 0
6009
+ };
6010
+ Object.keys(requestBody).forEach(
6011
+ (key) => requestBody[key] === void 0 && delete requestBody[key]
6012
+ );
6013
+ return apiFetch({
6014
+ url,
6015
+ method: "POST",
6016
+ body: requestBody,
6017
+ apiKey,
6018
+ authToken,
6019
+ timeoutMs
6020
+ });
6021
+ }
5967
6022
  async function apiGetPayeeDetails(req, apiKey, baseApiUrl, authToken, timeoutMs) {
5968
6023
  return apiFetch({
5969
- url: `${baseApiUrl.replace(/\/$/, "")}/v1/makers/${req.processorName}/${req.hashedOnchainId}`,
6024
+ url: `${baseApiUrl.replace(/\/$/, "")}/v2/makers/${req.processorName}/${req.hashedOnchainId}`,
5970
6025
  method: "GET",
5971
6026
  apiKey,
5972
6027
  authToken,
@@ -5975,7 +6030,7 @@ async function apiGetPayeeDetails(req, apiKey, baseApiUrl, authToken, timeoutMs)
5975
6030
  }
5976
6031
  async function apiValidatePayeeDetails(req, baseApiUrl, timeoutMs) {
5977
6032
  const data = await apiFetch({
5978
- url: `${baseApiUrl.replace(/\/$/, "")}/v1/makers/validate`,
6033
+ url: `${baseApiUrl.replace(/\/$/, "")}/v2/makers/validate`,
5979
6034
  method: "POST",
5980
6035
  body: req,
5981
6036
  timeoutMs
@@ -6030,7 +6085,6 @@ async function apiGetTakerTier(req, apiKey, baseApiUrl, timeoutMs) {
6030
6085
  return apiFetch({
6031
6086
  url: `${withApiBase(baseApiUrl)}${endpoint}`,
6032
6087
  method: "GET",
6033
- apiKey,
6034
6088
  timeoutMs
6035
6089
  });
6036
6090
  }
@@ -6132,6 +6186,23 @@ var appendReferrerFeeDisplayFields = (quoteResponse, referrerFeeConfig) => {
6132
6186
  }
6133
6187
  };
6134
6188
  };
6189
+ var appendReferrerFeeDisplayFieldsToBestByPlatform = (quoteResponse, referrerFeeConfig) => {
6190
+ if (!referrerFeeConfig) {
6191
+ return quoteResponse;
6192
+ }
6193
+ const decimals = quoteResponse.responseObject?.token?.decimals ?? 6;
6194
+ const enrichedPlatformQuotes = (quoteResponse.responseObject?.platformQuotes ?? []).map((platformQuote) => ({
6195
+ ...platformQuote,
6196
+ bestQuote: platformQuote.available && platformQuote.bestQuote ? applyReferrerFeeDisplayFieldsToQuote(platformQuote.bestQuote, referrerFeeConfig, decimals) : platformQuote.bestQuote
6197
+ }));
6198
+ return {
6199
+ ...quoteResponse,
6200
+ responseObject: {
6201
+ ...quoteResponse.responseObject,
6202
+ platformQuotes: enrichedPlatformQuotes
6203
+ }
6204
+ };
6205
+ };
6135
6206
 
6136
6207
  // src/utils/erc20.ts
6137
6208
  var ERC20_ABI = [
@@ -6158,6 +6229,95 @@ var ERC20_ABI = [
6158
6229
  ];
6159
6230
 
6160
6231
  // src/client/Zkp2pClient.ts
6232
+ function isStringRecord(value) {
6233
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6234
+ return false;
6235
+ }
6236
+ return Object.values(value).every((entry) => typeof entry === "string");
6237
+ }
6238
+ function normalizeTelegramUsername(value) {
6239
+ if (typeof value !== "string") {
6240
+ return value === null ? null : null;
6241
+ }
6242
+ const normalized = value.trim();
6243
+ return normalized.length > 0 ? normalized : null;
6244
+ }
6245
+ function extractLegacyQuotePayeeData(depositData) {
6246
+ if (!depositData || typeof depositData !== "object" || Array.isArray(depositData)) {
6247
+ return void 0;
6248
+ }
6249
+ const stringEntries = Object.entries(depositData).filter(
6250
+ (entry) => typeof entry[1] === "string" && entry[1].trim().length > 0
6251
+ );
6252
+ const telegramUsername = stringEntries.find(([key]) => key === "telegramUsername")?.[1] ?? null;
6253
+ const identifierEntries = stringEntries.filter(([key]) => key !== "telegramUsername");
6254
+ const [primaryEntry, ...metadataEntries] = identifierEntries;
6255
+ if (!primaryEntry) {
6256
+ return void 0;
6257
+ }
6258
+ return {
6259
+ offchainId: primaryEntry[1],
6260
+ telegramUsername,
6261
+ metadata: metadataEntries.length > 0 ? Object.fromEntries(metadataEntries) : null
6262
+ };
6263
+ }
6264
+ function normalizeQuotePayeeData(maker) {
6265
+ const legacy = extractLegacyQuotePayeeData(maker?.depositData);
6266
+ const offchainId = typeof maker?.offchainId === "string" && maker.offchainId.trim().length > 0 ? maker.offchainId : legacy?.offchainId;
6267
+ if (!offchainId) {
6268
+ return void 0;
6269
+ }
6270
+ return {
6271
+ offchainId,
6272
+ telegramUsername: normalizeTelegramUsername(maker?.telegramUsername) ?? legacy?.telegramUsername ?? null,
6273
+ metadata: isStringRecord(maker?.metadata) ? maker.metadata : legacy?.metadata ?? null
6274
+ };
6275
+ }
6276
+ function normalizePayeeDataInputItem(raw) {
6277
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
6278
+ return null;
6279
+ }
6280
+ const candidate = raw;
6281
+ if (typeof candidate.offchainId === "string" && candidate.offchainId.trim().length > 0) {
6282
+ return candidate;
6283
+ }
6284
+ const legacy = extractLegacyQuotePayeeData(raw);
6285
+ if (!legacy) {
6286
+ return null;
6287
+ }
6288
+ return {
6289
+ offchainId: legacy.offchainId,
6290
+ telegramUsername: legacy.telegramUsername,
6291
+ metadata: legacy.metadata
6292
+ };
6293
+ }
6294
+ function resolvePayeeDataInput(params, methodName) {
6295
+ const payeeData = params.payeeData ?? params.depositData;
6296
+ if (!Array.isArray(payeeData)) {
6297
+ throw new Error(`${methodName} requires payeeData`);
6298
+ }
6299
+ const normalized = payeeData.map((item, index) => {
6300
+ const result = normalizePayeeDataInputItem(item);
6301
+ if (!result) {
6302
+ throw new Error(
6303
+ `${methodName}: payeeData[${index}] must include a non-empty offchainId or a recognizable legacy identifier`
6304
+ );
6305
+ }
6306
+ return result;
6307
+ });
6308
+ return normalized;
6309
+ }
6310
+ function toPostDepositDetailsRequest(processorName, payeeData, index) {
6311
+ if (!payeeData || typeof payeeData.offchainId !== "string" || payeeData.offchainId.length === 0) {
6312
+ throw new Error(`payeeData[${index}] must include a non-empty offchainId`);
6313
+ }
6314
+ return {
6315
+ processorName,
6316
+ offchainId: payeeData.offchainId,
6317
+ telegramUsername: payeeData.telegramUsername,
6318
+ metadata: payeeData.metadata
6319
+ };
6320
+ }
6161
6321
  var Zkp2pClient = class {
6162
6322
  /**
6163
6323
  * Creates a new Zkp2pClient instance.
@@ -6704,7 +6864,9 @@ var Zkp2pClient = class {
6704
6864
  * sending fiat payment to the deposit's payee.
6705
6865
  *
6706
6866
  * If `gatingServiceSignature` is not provided, the SDK will automatically
6707
- * fetch one from the API (requires `apiKey` or `authorizationToken`).
6867
+ * fetch one from curator `/v3/intent/sign` when `apiKey` or `authorizationToken`
6868
+ * is available. Otherwise you must provide `gatingServiceSignature` and
6869
+ * `signatureExpiration` yourself.
6708
6870
  *
6709
6871
  * **Prepare Mode**: Use `.prepare()` to get the transaction calldata without sending:
6710
6872
  * ```typescript
@@ -8016,42 +8178,32 @@ var Zkp2pClient = class {
8016
8178
  * register maker payment details with the curator service.
8017
8179
  *
8018
8180
  * @param params.processorNames - Payment platforms (e.g., ['wise', 'revolut'])
8019
- * @param params.depositData - Payee details per processor (e.g., [{ email: '...' }])
8181
+ * @param params.payeeData - Payee details per processor (e.g., [{ offchainId: 'you@example.com' }]). Required when the SDK needs to register payee details with the curator.
8020
8182
  * @returns The posted deposit details and their corresponding hashed on-chain IDs
8021
8183
  *
8022
8184
  * @example
8023
8185
  * ```typescript
8024
8186
  * const { hashedOnchainIds } = await client.registerPayeeDetails({
8025
8187
  * processorNames: ['wise'],
8026
- * depositData: [{ email: 'you@example.com' }],
8188
+ * payeeData: [{ offchainId: 'you@example.com' }],
8027
8189
  * });
8028
8190
  * // Then pass hashedOnchainIds to createDeposit
8029
8191
  * ```
8030
8192
  */
8031
8193
  async registerPayeeDetails(params) {
8194
+ const payeeData = resolvePayeeDataInput(params, "registerPayeeDetails");
8032
8195
  if (!Array.isArray(params.processorNames) || params.processorNames.length === 0) {
8033
8196
  throw new Error("processorNames must be a non-empty array");
8034
8197
  }
8035
- if (params.processorNames.length !== params.depositData.length) {
8036
- throw new Error("processorNames and depositData length mismatch");
8198
+ if (params.processorNames.length !== payeeData.length) {
8199
+ throw new Error("processorNames and payeeData length mismatch");
8037
8200
  }
8038
8201
  const baseApiUrl = (this.baseApiUrl ?? "https://api.zkp2p.xyz").replace(/\/$/, "");
8039
8202
  const depositDetails = params.processorNames.map(
8040
- (processorName, index) => ({
8041
- processorName,
8042
- depositData: params.depositData[index] || {}
8043
- })
8203
+ (processorName, index) => toPostDepositDetailsRequest(processorName, payeeData[index], index)
8044
8204
  );
8045
8205
  const apiResponses = await Promise.all(
8046
- depositDetails.map(
8047
- (req) => apiPostDepositDetails(
8048
- req,
8049
- baseApiUrl,
8050
- this.apiTimeoutMs,
8051
- this.apiKey,
8052
- this.authorizationToken
8053
- )
8054
- )
8206
+ depositDetails.map((req) => apiPostDepositDetails(req, baseApiUrl, this.apiTimeoutMs))
8055
8207
  );
8056
8208
  if (!apiResponses.every((r) => r?.success)) {
8057
8209
  const failed = apiResponses.find((r) => !r?.success);
@@ -8075,16 +8227,17 @@ var Zkp2pClient = class {
8075
8227
  * @param params.amount - Total deposit amount in token units (6 decimals for USDC)
8076
8228
  * @param params.intentAmountRange - Min/max amount per intent
8077
8229
  * @param params.processorNames - Payment platforms to accept (e.g., ['wise', 'revolut'])
8078
- * @param params.depositData - Payee details per processor (e.g., [{ email: '...' }])
8230
+ * @param params.payeeData - Payee details per processor (e.g., [{ offchainId: 'you@example.com' }])
8079
8231
  * @param params.conversionRates - Conversion rates per processor, grouped by currency
8080
8232
  * @param params.payeeDetailsHashes - Pre-computed hashed on-chain IDs (from registerPayeeDetails). When provided, skips the curator API call entirely.
8081
8233
  * @param params.delegate - Optional delegate address that can manage the deposit
8082
8234
  * @param params.intentGuardian - Optional guardian for intent approval
8083
8235
  * @param params.retainOnEmpty - Keep deposit active when balance reaches zero
8084
8236
  * @param params.txOverrides - Optional viem transaction overrides
8085
- * @returns The deposit details posted to API and the transaction hash
8237
+ * @returns The deposit details posted to API (empty when payee registration is skipped) and the transaction hash
8086
8238
  *
8087
- * @throws Error if processorNames, depositData, and conversionRates lengths don't match
8239
+ * @throws Error if processorNames, payeeData, and conversionRates lengths don't match
8240
+ * @throws Error if payeeData is missing and neither payeeDetailsHashes nor full payment method overrides are provided
8088
8241
  * @throws Error if a currency is not supported by the specified processor
8089
8242
  *
8090
8243
  * @example
@@ -8095,7 +8248,7 @@ var Zkp2pClient = class {
8095
8248
  * amount: 1000_000000n,
8096
8249
  * intentAmountRange: { min: 10_000000n, max: 500_000000n },
8097
8250
  * processorNames: ['wise'],
8098
- * depositData: [{ email: 'you@example.com' }],
8251
+ * payeeData: [{ offchainId: 'you@example.com' }],
8099
8252
  * conversionRates: [[
8100
8253
  * { currency: 'USD', conversionRate: '1020000000000000000' }, // 1.02
8101
8254
  * { currency: 'EUR', conversionRate: '1100000000000000000' }, // 1.10
@@ -8128,24 +8281,30 @@ var Zkp2pClient = class {
8128
8281
  };
8129
8282
  }
8130
8283
  async prepareCreateDepositInternal(params) {
8284
+ const hasOverrides = Boolean(
8285
+ params.paymentMethodsOverride || params.paymentMethodDataOverride || params.currenciesOverride
8286
+ );
8287
+ const payeeDetailsHashes = params.payeeDetailsHashes;
8288
+ const hasPayeeHashes = payeeDetailsHashes !== void 0;
8289
+ const shouldResolvePayeeData = params.payeeData !== void 0 || params.depositData !== void 0;
8290
+ const payeeData = shouldResolvePayeeData ? resolvePayeeDataInput(params, "createDeposit") : null;
8131
8291
  if (!Array.isArray(params.processorNames) || params.processorNames.length === 0) {
8132
8292
  throw new Error("processorNames must be a non-empty array");
8133
8293
  }
8134
8294
  if (params.processorNames.length !== params.conversionRates.length) {
8135
8295
  throw new Error("processorNames and conversionRates length mismatch");
8136
8296
  }
8137
- if (params.processorNames.length !== params.depositData.length) {
8138
- throw new Error("processorNames and depositData length mismatch");
8297
+ if (payeeData && params.processorNames.length !== payeeData.length) {
8298
+ throw new Error("processorNames and payeeData length mismatch");
8139
8299
  }
8140
- const depositDetails = params.processorNames.map(
8141
- (processorName, index) => ({
8142
- processorName,
8143
- depositData: params.depositData[index] || {}
8144
- })
8145
- );
8146
- const hasOverrides = Boolean(
8147
- params.paymentMethodsOverride || params.paymentMethodDataOverride || params.currenciesOverride
8148
- );
8300
+ if (!hasOverrides && !hasPayeeHashes && !payeeData) {
8301
+ throw new Error(
8302
+ "createDeposit requires payeeData unless payeeDetailsHashes or full payment method overrides are provided"
8303
+ );
8304
+ }
8305
+ const depositDetails = payeeData ? params.processorNames.map(
8306
+ (processorName, index) => toPostDepositDetailsRequest(processorName, payeeData[index], index)
8307
+ ) : [];
8149
8308
  let paymentMethods;
8150
8309
  let paymentMethodData;
8151
8310
  let currencies;
@@ -8170,23 +8329,15 @@ var Zkp2pClient = class {
8170
8329
  );
8171
8330
  const intentGatingService = getGatingServiceAddress(this.chainId, this.runtimeEnv);
8172
8331
  let hashedOnchainIds;
8173
- if (params.payeeDetailsHashes) {
8174
- if (params.payeeDetailsHashes.length !== params.processorNames.length) {
8332
+ if (payeeDetailsHashes !== void 0) {
8333
+ if (payeeDetailsHashes.length !== params.processorNames.length) {
8175
8334
  throw new Error("payeeDetailsHashes length must match processorNames length");
8176
8335
  }
8177
- hashedOnchainIds = params.payeeDetailsHashes;
8336
+ hashedOnchainIds = payeeDetailsHashes;
8178
8337
  } else {
8179
8338
  const baseApiUrl = (this.baseApiUrl ?? "https://api.zkp2p.xyz").replace(/\/$/, "");
8180
8339
  const apiResponses = await Promise.all(
8181
- depositDetails.map(
8182
- (req) => apiPostDepositDetails(
8183
- req,
8184
- baseApiUrl,
8185
- this.apiTimeoutMs,
8186
- this.apiKey,
8187
- this.authorizationToken
8188
- )
8189
- )
8340
+ depositDetails.map((req) => apiPostDepositDetails(req, baseApiUrl, this.apiTimeoutMs))
8190
8341
  );
8191
8342
  if (!apiResponses.every((r) => r?.success)) {
8192
8343
  const failed = apiResponses.find((r) => !r?.success);
@@ -8383,12 +8534,64 @@ var Zkp2pClient = class {
8383
8534
  const quotes = quote?.responseObject?.quotes ?? [];
8384
8535
  for (const q of quotes) {
8385
8536
  const maker = q?.maker;
8386
- if (maker?.depositData && typeof q === "object") {
8387
- q.payeeData = maker.depositData;
8537
+ const payeeData = normalizeQuotePayeeData(maker);
8538
+ if (payeeData && typeof q === "object") {
8539
+ q.payeeData = payeeData;
8388
8540
  }
8389
8541
  }
8390
8542
  return appendReferrerFeeDisplayFields(quote, referrerFeeConfig);
8391
8543
  }
8544
+ /**
8545
+ * **Supporting Method** - Fetches the best available quote per supported payment platform.
8546
+ *
8547
+ * Returns one quote per platform when available. When authenticated, the API
8548
+ * returns payee details in each platform's best quote.
8549
+ *
8550
+ * @param req - Best-by-platform quote request parameters
8551
+ * @param opts - Optional overrides for API URL and timeout
8552
+ * @returns Best-by-platform quote response
8553
+ */
8554
+ async getQuotesBestByPlatform(req, opts) {
8555
+ const referrerFeeConfig = assertValidReferrerFeeConfig(
8556
+ req.referrerFeeConfig,
8557
+ "getQuotesBestByPlatform"
8558
+ );
8559
+ const baseApiUrl = (opts?.baseApiUrl ?? this.baseApiUrl ?? "https://api.zkp2p.xyz").replace(
8560
+ /\/$/,
8561
+ ""
8562
+ );
8563
+ const timeoutMs = opts?.timeoutMs ?? this.apiTimeoutMs;
8564
+ const reqWithEscrow = { ...req };
8565
+ if (!reqWithEscrow.escrowAddresses || reqWithEscrow.escrowAddresses.length === 0) {
8566
+ const configuredEscrows = this.escrowAddresses.length > 0 ? [...this.escrowAddresses] : this.escrowAddress ? [this.escrowAddress] : [];
8567
+ if (configuredEscrows.length > 0) {
8568
+ reqWithEscrow.escrowAddresses = configuredEscrows;
8569
+ }
8570
+ }
8571
+ const quote = await apiGetQuotesBestByPlatform(
8572
+ reqWithEscrow,
8573
+ baseApiUrl,
8574
+ timeoutMs,
8575
+ this.apiKey,
8576
+ this.authorizationToken
8577
+ );
8578
+ const enrichedQuote = quote ? {
8579
+ ...quote,
8580
+ responseObject: {
8581
+ ...quote.responseObject,
8582
+ platformQuotes: (quote.responseObject?.platformQuotes ?? []).map((platformQuote) => {
8583
+ const bestQuote = platformQuote?.bestQuote;
8584
+ const payeeData = normalizeQuotePayeeData(bestQuote?.maker);
8585
+ if (!bestQuote || !payeeData) return platformQuote;
8586
+ return {
8587
+ ...platformQuote,
8588
+ bestQuote: { ...bestQuote, payeeData }
8589
+ };
8590
+ })
8591
+ }
8592
+ } : quote;
8593
+ return appendReferrerFeeDisplayFieldsToBestByPlatform(enrichedQuote, referrerFeeConfig);
8594
+ }
8392
8595
  // ───────────────────────────────────────────────────────────────────────────
8393
8596
  // SUPPORTING: TAKER TIER
8394
8597
  // (Used by frontends to display taker limits)
@@ -8408,7 +8611,7 @@ var Zkp2pClient = class {
8408
8611
  ""
8409
8612
  );
8410
8613
  const timeoutMs = opts?.timeoutMs ?? this.apiTimeoutMs;
8411
- return apiGetTakerTier(req, this.apiKey, baseApiUrl, timeoutMs);
8614
+ return apiGetTakerTier(req, void 0, baseApiUrl, timeoutMs);
8412
8615
  }
8413
8616
  // ╔═══════════════════════════════════════════════════════════════════════════╗
8414
8617
  // ║ CORE: ON-CHAIN DEPOSIT VIEWS ║
@@ -8838,6 +9041,7 @@ exports.ZKP2P_IOS_REFERRER = ZKP2P_IOS_REFERRER;
8838
9041
  exports.Zkp2pClient = Zkp2pClient;
8839
9042
  exports.apiGetOwnerDeposits = apiGetOwnerDeposits;
8840
9043
  exports.apiGetPayeeDetails = apiGetPayeeDetails;
9044
+ exports.apiGetQuotesBestByPlatform = apiGetQuotesBestByPlatform;
8841
9045
  exports.apiGetTakerTier = apiGetTakerTier;
8842
9046
  exports.apiPostDepositDetails = apiPostDepositDetails;
8843
9047
  exports.apiValidatePayeeDetails = apiValidatePayeeDetails;