@zkp2p/pay-shared 4.0.1 → 5.0.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/dist/types.d.ts CHANGED
@@ -62,6 +62,7 @@ export type CheckoutMethodType = typeof CheckoutMethod[keyof typeof CheckoutMeth
62
62
  export declare const FeePayer: {
63
63
  readonly MERCHANT: "MERCHANT";
64
64
  readonly PAYEE: "PAYEE";
65
+ readonly SPLIT: "SPLIT";
65
66
  };
66
67
  export type FeePayerType = typeof FeePayer[keyof typeof FeePayer];
67
68
  export declare const MerchantPaymentFlowMode: {
@@ -147,11 +148,95 @@ export type SettlementReferralFeeEntry = {
147
148
  recipient: string;
148
149
  feeUsdc: string;
149
150
  };
151
+ /** FIXED orders carry an amount from creation; OPEN orders get one when the buyer starts a payment. */
152
+ export declare const OrderAmountMode: {
153
+ readonly FIXED: "FIXED";
154
+ readonly OPEN: "OPEN";
155
+ };
156
+ export type OrderAmountModeType = typeof OrderAmountMode[keyof typeof OrderAmountMode];
157
+ /**
158
+ * Why the buyer can no longer change an open order's amount. Precedence when several apply:
159
+ * PAID, then PAYMENT_MAY_SETTLE, then PAYMENT_IN_PROGRESS.
160
+ */
161
+ export declare const AmountLockReason: {
162
+ /** Only CREATED non-Zcash payments lock the amount; cancelling them unlocks it. */
163
+ readonly PAYMENT_IN_PROGRESS: "PAYMENT_IN_PROGRESS";
164
+ /** An EXPIRED payment, a locking Zcash payment or a reopenable FAILED Relay payment can still settle; cancelling cannot unlock it. */
165
+ readonly PAYMENT_MAY_SETTLE: "PAYMENT_MAY_SETTLE";
166
+ /** A SETTLED payment exists. */
167
+ readonly PAID: "PAID";
168
+ };
169
+ export type AmountLockReasonType = typeof AmountLockReason[keyof typeof AmountLockReason];
170
+ export declare const OpenAmountErrorCode: {
171
+ readonly OPEN_AMOUNT_INVALID: "OPEN_AMOUNT_INVALID";
172
+ readonly OPEN_AMOUNT_DISABLED: "OPEN_AMOUNT_DISABLED";
173
+ readonly AMOUNT_REQUIRED: "AMOUNT_REQUIRED";
174
+ readonly AMOUNT_NOT_ALLOWED: "AMOUNT_NOT_ALLOWED";
175
+ readonly AMOUNT_OUT_OF_RANGE: "AMOUNT_OUT_OF_RANGE";
176
+ readonly AMOUNT_LOCKED: "AMOUNT_LOCKED";
177
+ readonly AMOUNT_CONFLICT: "AMOUNT_CONFLICT";
178
+ readonly RESIZE_NOT_SUPPORTED: "RESIZE_NOT_SUPPORTED";
179
+ };
180
+ export type OpenAmountErrorCodeType = typeof OpenAmountErrorCode[keyof typeof OpenAmountErrorCode];
181
+ /** Merchant request shape. Amounts are positive decimals in `currency` with at most 2 decimals. */
182
+ export type OpenAmountInput = {
183
+ currency: string;
184
+ minAmount?: string;
185
+ maxAmount?: string;
186
+ presets?: string[];
187
+ };
188
+ /** Stored + API shape (normalized: upper-case currency, 2-dp decimal strings, presets sorted asc, unique). */
189
+ export type OpenAmountConfig = {
190
+ currency: string;
191
+ minAmount: string | null;
192
+ maxAmount: string | null;
193
+ presets: string[];
194
+ };
195
+ /** The buyer's saved amount and the currency they typed it in (the checkout's selected currency, which may differ from `openAmount.currency`). */
196
+ export type OpenAmountSavedInput = {
197
+ amount: string;
198
+ currency: string;
199
+ };
200
+ /**
201
+ * Platform-quotes `openAmountDisplay` (amendment 2026-10-05): an unlocked open order's range and
202
+ * presets in the request's `fiatCurrency`. In the order's own currency the merchant's values are
203
+ * exact, cents kept; in any other currency they are whole units (minimum rounded up, maximum down,
204
+ * presets half-up and clamped into the range). The bounds and `currencyPerOrderUnit` are null, and
205
+ * `presets` is empty, when an exchange rate is unavailable.
206
+ */
207
+ export type OpenAmountDisplay = {
208
+ currency: string;
209
+ effectiveMin: string | null;
210
+ effectiveMax: string | null;
211
+ presets: string[];
212
+ /** Units of `currency` one unit of `openAmount.currency` buys at the rates used, as a decimal string; null when unavailable. */
213
+ currencyPerOrderUnit: string | null;
214
+ };
215
+ /** Hosted (checkout) only. */
216
+ export type HostedOpenAmount = OpenAmountConfig & {
217
+ /** In `currency`, 2 dp, rounded UP. Null while locked, once FULFILLED or CANCELLED, or when the live rate is unavailable. */
218
+ effectiveMin: string | null;
219
+ /** In `currency`, 2 dp, rounded DOWN. Null while locked, once FULFILLED or CANCELLED, or when the live rate is unavailable. */
220
+ effectiveMax: string | null;
221
+ /** The buyer's saved amount in the currency they typed it in, or null before the first payment start. */
222
+ savedInput: OpenAmountSavedInput | null;
223
+ };
224
+ /** `ORDER_AMOUNT_SET` webhook detail. */
225
+ export type OrderAmountChange = {
226
+ previousAmountUsdc: string | null;
227
+ newAmountUsdc: string;
228
+ /** The amount the buyer typed, in the currency they typed it in (the checkout's selected currency). */
229
+ fiat: OpenAmountSavedInput;
230
+ amountVersion: number;
231
+ };
150
232
  type CreateOrderRequestBase = {
233
+ idempotencyKey?: string;
151
234
  destinationAddress?: string;
152
235
  destinationToken?: string;
153
236
  destinationChainId?: number;
154
237
  feePayer?: FeePayerType;
238
+ /** SPLIT buyer share of total fees, in basis points (0–10000, steps of 1000). */
239
+ buyerFeeShareBps?: number;
155
240
  enabledRails?: string[];
156
241
  dynamicOrdersEnabled?: boolean;
157
242
  successUrl?: string | null;
@@ -162,13 +247,21 @@ type CreateOrderRequestWithUsdc = CreateOrderRequestBase & {
162
247
  requestedUsdcAmount: string;
163
248
  requestedFiatAmount?: never;
164
249
  requestedFiatCurrency?: never;
250
+ openAmount?: never;
165
251
  };
166
252
  type CreateOrderRequestWithFiat = CreateOrderRequestBase & {
167
253
  requestedUsdcAmount?: never;
168
254
  requestedFiatAmount: string;
169
255
  requestedFiatCurrency: string;
256
+ openAmount?: never;
170
257
  };
171
- export type CreateOrderRequest = CreateOrderRequestWithUsdc | CreateOrderRequestWithFiat;
258
+ type CreateOrderRequestWithOpenAmount = CreateOrderRequestBase & {
259
+ requestedUsdcAmount?: never;
260
+ requestedFiatAmount?: never;
261
+ requestedFiatCurrency?: never;
262
+ openAmount: OpenAmountInput;
263
+ };
264
+ export type CreateOrderRequest = CreateOrderRequestWithUsdc | CreateOrderRequestWithFiat | CreateOrderRequestWithOpenAmount;
172
265
  export type CheckoutRequest = CreateOrderRequest;
173
266
  export type MerchantCheckoutTheme = {
174
267
  presetName?: 'default' | 'dark' | 'light' | 'custom';
@@ -196,7 +289,7 @@ export type CheckoutMerchant = {
196
289
  /** Whether the merchant has been verified by ZKP2P. */
197
290
  verified: boolean;
198
291
  };
199
- export type CheckoutOrder = {
292
+ type CheckoutOrderBase = {
200
293
  id: string;
201
294
  merchantId: string;
202
295
  status: CheckoutOrderStatusType;
@@ -208,12 +301,18 @@ export type CheckoutOrder = {
208
301
  refundTransactionHash: string | null;
209
302
  refundMetadata: unknown | null;
210
303
  inPersonCheckout: boolean;
211
- requestedUsdcAmount: string;
212
- remainingUsdcAmount: string;
304
+ /**
305
+ * USDC the customer would be charged for the current outstanding balance if they
306
+ * paid by Apple Pay, grossed up by the merchant's Apple Pay fee when the payer
307
+ * owes it. Hosted aggregates only; null when Apple Pay is disabled or pricing
308
+ * cannot be resolved. Checkout hides Apple Pay when it is above the 2,500 USDC cap.
309
+ */
310
+ applePayChargeUsdcAmount?: string | null;
213
311
  destinationAddress: string;
214
312
  destinationToken: string;
215
313
  destinationChainId: string;
216
314
  feePayer: FeePayerType;
315
+ buyerFeeShareBps: number;
217
316
  enabledRails: string[];
218
317
  successUrl: string | null;
219
318
  cancelUrl: string | null;
@@ -231,7 +330,34 @@ export type CheckoutOrder = {
231
330
  createdAt: string;
232
331
  updatedAt: string | null;
233
332
  };
333
+ export type FixedAmountCheckoutOrder = CheckoutOrderBase & {
334
+ amountMode: typeof OrderAmountMode.FIXED;
335
+ requestedUsdcAmount: string;
336
+ remainingUsdcAmount: string;
337
+ };
338
+ /** Amounts stay null until the buyer starts the first payment; `amountVersion` is 0 until then. */
339
+ export type OpenAmountCheckoutOrder = CheckoutOrderBase & {
340
+ amountMode: typeof OrderAmountMode.OPEN;
341
+ requestedUsdcAmount: string | null;
342
+ remainingUsdcAmount: string | null;
343
+ openAmount: OpenAmountConfig;
344
+ amountVersion: number;
345
+ };
346
+ /** Narrow on `amountMode` before reading amounts. */
347
+ export type CheckoutOrder = FixedAmountCheckoutOrder | OpenAmountCheckoutOrder;
348
+ /** Hosted aggregate shape of an open order: effective range, saved input and lock state. */
349
+ export type HostedOpenAmountCheckoutOrder = Omit<OpenAmountCheckoutOrder, 'openAmount'> & {
350
+ openAmount: HostedOpenAmount;
351
+ /** Computed server-side from the order's payments; null means the buyer may change the amount. */
352
+ amountLock: AmountLockReasonType | null;
353
+ };
354
+ export type HostedCheckoutOrder = FixedAmountCheckoutOrder | HostedOpenAmountCheckoutOrder;
234
355
  export type CheckoutPaymentQuote = {
356
+ /** Full-size economics when Peer funds a smaller executable intent. */
357
+ amountAdjustment?: {
358
+ requestedSignalAmountRaw: string;
359
+ buyerFiatAmount: string;
360
+ };
235
361
  conversionRate?: string;
236
362
  signalIntent: {
237
363
  processorName: string;
@@ -266,6 +392,8 @@ export type CheckoutNearbySuggestion = {
266
392
  tokenAmount: string;
267
393
  percentDifference: string;
268
394
  rail: string;
395
+ /** Open-amount orders only: the suggestion in the quote's `fiatCurrency`, 2 dp, rounded down. */
396
+ inputAmount?: string;
269
397
  };
270
398
  export type CheckoutNearbySuggestions = {
271
399
  status: 'suggestions' | 'none' | 'ineligible' | 'unavailable';
@@ -308,6 +436,31 @@ export type CheckoutQuotes = {
308
436
  fiatCurrency: string;
309
437
  platforms: CheckoutQuoteEntry[];
310
438
  nearbySuggestions?: CheckoutNearbySuggestions;
439
+ /** Open order with no saved amount and no `amount` query parameter: `platforms` is empty. */
440
+ amountRequired?: true;
441
+ /** Open orders, when `amount` (in `fiatCurrency`) was sent: the draft converted to USDC. */
442
+ amountUsdc?: string;
443
+ /** Open orders, when `amount` was sent: Apple Pay pricing of the draft. */
444
+ applePay?: {
445
+ chargeUsdcAmount: string | null;
446
+ eligible: boolean;
447
+ };
448
+ /** Unlocked open orders that are not fulfilled or cancelled, with or without `amount`: the range and presets in `fiatCurrency`. */
449
+ openAmountDisplay?: OpenAmountDisplay;
450
+ };
451
+ export declare const PaymentPenaltyKind: {
452
+ readonly PURCHASE_PROTECTION: "PURCHASE_PROTECTION";
453
+ readonly CROSS_CURRENCY: "CROSS_CURRENCY";
454
+ };
455
+ export type PaymentPenaltyKindType = (typeof PaymentPenaltyKind)[keyof typeof PaymentPenaltyKind];
456
+ /** One attestation-applied reduction of the credited fiat amount. Amounts are in the payment's `currency`. */
457
+ export type PaymentPenalty = {
458
+ kind: PaymentPenaltyKindType;
459
+ penaltyBps: number;
460
+ /** Pre-penalty amount in `payment.currency`, 2-decimal string. */
461
+ originalAmount: string;
462
+ /** Post-penalty amount actually credited, same units. */
463
+ attestedAmount: string;
311
464
  };
312
465
  export type CheckoutPayment = {
313
466
  id: string;
@@ -315,6 +468,7 @@ export type CheckoutPayment = {
315
468
  status: CheckoutPaymentStatusType;
316
469
  chargebackStatus: PaymentChargebackStatusType;
317
470
  chargeback: PaymentChargebackFact | null;
471
+ penalties: PaymentPenalty[];
318
472
  rail: string;
319
473
  paymentMethodId: string | null;
320
474
  proofMode: ProofMode;
@@ -346,15 +500,25 @@ export type CheckoutAggregatePayment = Omit<CheckoutPayment, 'paymentMethodId'>
346
500
  paymentMethodId?: string | null;
347
501
  };
348
502
  export type CheckoutAggregate = {
349
- order: CheckoutOrder;
503
+ order: HostedCheckoutOrder;
350
504
  merchant: CheckoutMerchant;
351
505
  currentPayment: CheckoutAggregatePayment | null;
352
506
  };
507
+ /** Public GET /api/v1/orders/:orderId responseObject. */
508
+ export type HostedCheckoutResponse = CheckoutAggregate & {
509
+ paymentCreationPaused: boolean;
510
+ };
353
511
  export type CreateOrderResponse = {
354
512
  order: CheckoutOrder;
513
+ } & ({
355
514
  orderToken: string;
356
- };
357
- export type CreatePaymentRequest = {
515
+ idempotentReplay?: never;
516
+ } | {
517
+ orderToken: null;
518
+ idempotentReplay: true;
519
+ });
520
+ type CreatePaymentRequestBase = {
521
+ onrampProvider?: 'coinbase_apple_pay';
358
522
  rail: string;
359
523
  paymentMethodId?: string;
360
524
  fiatCurrency?: string;
@@ -364,6 +528,23 @@ export type CreatePaymentRequest = {
364
528
  excludedPayToValues?: string[];
365
529
  refundTo?: string;
366
530
  };
531
+ /**
532
+ * Open-amount orders: `amount`, the fiat `amountCurrency` it is typed in (the checkout's selected
533
+ * currency, sent on crypto and Apple Pay starts too) and the `amountVersion` the buyer loaded travel
534
+ * together, or not at all.
535
+ * On fiat rails, starts with `amount` require `fiatCurrency` to equal `amountCurrency`;
536
+ * omitted `fiatCurrency` means USD. A mismatch returns HTTP 400. Crypto and Apple Pay
537
+ * starts are exempt from this check.
538
+ */
539
+ export type CreatePaymentRequest = CreatePaymentRequestBase & ({
540
+ amount?: never;
541
+ amountCurrency?: never;
542
+ expectedAmountVersion?: never;
543
+ } | {
544
+ amount: string;
545
+ amountCurrency: string;
546
+ expectedAmountVersion: number;
547
+ });
367
548
  export type CheckoutPaymentCreationResponse = CheckoutPayment & {
368
549
  relayerTransactionId?: string;
369
550
  recipientRecovery?: 'matched' | 'missed' | 'not_applicable';
@@ -371,9 +552,9 @@ export type CheckoutPaymentCreationResponse = CheckoutPayment & {
371
552
  export type PaymentDeeplinkResponse = {
372
553
  paymentId: string;
373
554
  orderId: string;
374
- intentHash: string;
555
+ intentHash: string | null;
375
556
  url: string;
376
- proofSubmissionUrl: string;
557
+ proofSubmissionUrl: string | null;
377
558
  checkoutReturnUrl: string;
378
559
  linkKind?: 'app_clip' | 'deeplink';
379
560
  };
@@ -382,7 +563,9 @@ export type MerchantConfig = {
382
563
  id: string;
383
564
  merchantId: string;
384
565
  feePayer: FeePayerType;
566
+ buyerFeeShareBps: number;
385
567
  enabledRails: string[];
568
+ applePayAvailable: boolean;
386
569
  defaultPaymentCurrency: string | null;
387
570
  destinationChainId: string;
388
571
  destinationToken: string;
@@ -393,15 +576,27 @@ export type MerchantConfig = {
393
576
  platformReferralFeeConfig: ReferralFeeConfig | null;
394
577
  referralSplitConfig: ReferralSplitConfig | null;
395
578
  flatFeePricing: boolean;
579
+ /** Admin-managed: this merchant may create Master Merchant Account sub-merchants. */
580
+ masterMerchantEnabled: boolean;
581
+ /** Admin-managed cap, in bps, for the master merchant fee on this merchant's sub-merchants; null means no Master Merchant Account-specific cap. */
582
+ masterMerchantMaxFeeBps: number | null;
396
583
  createdAt: string;
397
584
  updatedAt: string | null;
398
585
  };
586
+ export declare const MerchantUserRole: {
587
+ readonly OWNER: "OWNER";
588
+ readonly MANAGER: "MANAGER";
589
+ readonly CASHIER: "CASHIER";
590
+ };
591
+ export type MerchantUserRoleType = typeof MerchantUserRole[keyof typeof MerchantUserRole];
399
592
  export type MerchantUser = {
400
593
  id: string;
401
594
  email: string | null;
402
595
  privyUserId: string | null;
403
596
  v1PrivyUserId: string | null;
404
- role: 'OWNER' | 'MANAGER' | 'CASHIER';
597
+ role: MerchantUserRoleType;
598
+ /** Master Merchant Account seat after an ownership transfer: it cannot be removed by merchant users, only by an admin. */
599
+ removalLocked: boolean;
405
600
  merchantId: string | null;
406
601
  createdAt: string;
407
602
  updatedAt: string | null;
@@ -417,6 +612,8 @@ export type MerchantProfile = {
417
612
  onboardingCompletedAt: string | null;
418
613
  onboardingSkippedAt: string | null;
419
614
  apiKey: string;
615
+ /** Canonical IPv4/IPv6 CIDR entries allowed to use the API key; empty means the allowlist is off. */
616
+ apiKeyIpAllowlist: string[];
420
617
  environment: MerchantEnvironmentType;
421
618
  sandboxMerchantId: string | null;
422
619
  inPersonCheckoutEnabled: boolean;
@@ -425,12 +622,16 @@ export type MerchantProfile = {
425
622
  v1EvmWalletAddress: string | null;
426
623
  v1SolanaWalletAddress: string | null;
427
624
  tier: MerchantTierName | null;
625
+ /** The Master Merchant Account merchant that created this sub-merchant; null for every other merchant. */
626
+ masterMerchantId: string | null;
428
627
  createdAt: string;
429
628
  updatedAt: string | null;
430
629
  merchantConfig: MerchantConfig | null;
431
630
  merchantUsers: MerchantUser[];
432
631
  };
632
+ export declare const PAYMENT_CREATION_PAUSED_MESSAGE = "Payments are temporarily paused. Please try again shortly.";
433
633
  export declare const OrderErrorCode: {
634
+ readonly PAYMENTS_PAUSED: "PAYMENTS_PAUSED";
434
635
  readonly PROOF_INVALID: "PROOF_INVALID";
435
636
  readonly PROOF_EXPIRED: "PROOF_EXPIRED";
436
637
  readonly PROOF_RECIPIENT_MISMATCH: "PROOF_RECIPIENT_MISMATCH";
@@ -443,6 +644,7 @@ export declare const OrderErrorCode: {
443
644
  readonly ATTESTATION_ERROR: "ATTESTATION_ERROR";
444
645
  readonly BRIDGE_TIMEOUT: "BRIDGE_TIMEOUT";
445
646
  readonly FEE_THRESHOLD_EXCEEDED: "FEE_THRESHOLD_EXCEEDED";
647
+ readonly INTENT_ABOVE_MAX: "INTENT_ABOVE_MAX";
446
648
  readonly SDK_ERROR: "SDK_ERROR";
447
649
  readonly UNKNOWN_ERROR: "UNKNOWN_ERROR";
448
650
  };
@@ -691,7 +893,14 @@ export type StartSessionRequest = {
691
893
  originToken: PayCryptoTokenSymbol;
692
894
  };
693
895
  export type RelayCryptoPaymentStatus = 'refund' | 'delayed' | 'waiting' | 'failure' | 'pending' | 'success';
896
+ export type NearIntentsPaymentDetails = {
897
+ status: 'PENDING_DEPOSIT' | 'KNOWN_DEPOSIT_TX' | 'INCOMPLETE_DEPOSIT' | 'PROCESSING' | 'SUCCESS' | 'REFUNDED' | 'FAILED';
898
+ deadline: string;
899
+ refundAddress: string;
900
+ refundedAmount?: string;
901
+ };
694
902
  export type CheckoutCryptoPayment = {
903
+ nearIntents?: NearIntentsPaymentDetails;
695
904
  requestId: string;
696
905
  status: RelayCryptoPaymentStatus;
697
906
  depositAddress: string;
@@ -788,6 +997,12 @@ export type OnboardingStepState = {
788
997
  status: OnboardingStepStatusValue;
789
998
  verifiedBy: OnboardingStepVerifiedByValue;
790
999
  };
1000
+ /**
1001
+ * responseObject of GET /api/v1/merchants/dashboard/me/onboarding,
1002
+ * POST /api/v1/merchants/dashboard/me/onboarding/steps/:stepId/ack, and
1003
+ * POST /api/v1/merchants/dashboard/me/onboarding/skip.
1004
+ * For POST routes, this is the state after the write is applied.
1005
+ */
791
1006
  export type MerchantOnboardingResponse = {
792
1007
  path: MerchantIntegrationPathValue | null;
793
1008
  sandboxApiKey: string | null;
@@ -795,11 +1010,25 @@ export type MerchantOnboardingResponse = {
795
1010
  skippedAt: string | null;
796
1011
  steps: OnboardingStepState[];
797
1012
  };
1013
+ export declare const MERCHANT_REFERRAL_FEE_BPS_BY_TIER: Readonly<Record<MerchantTierName, number>>;
1014
+ export type MerchantReferralReferredMerchant = {
1015
+ id: string;
1016
+ name: string;
1017
+ createdAt: string;
1018
+ };
1019
+ export type MerchantReferralProgramResponse = {
1020
+ code: string;
1021
+ referralFeeBpsByTier: Readonly<Record<MerchantTierName, number>>;
1022
+ recipientAddress: string;
1023
+ totalReferred: number;
1024
+ referredMerchants: MerchantReferralReferredMerchant[];
1025
+ };
798
1026
  export declare const WebhookEventType: {
799
1027
  readonly ORDER_CREATED: "ORDER_CREATED";
800
1028
  readonly ORDER_FULFILLED: "ORDER_FULFILLED";
801
1029
  readonly ORDER_CANCELLED: "ORDER_CANCELLED";
802
1030
  readonly ORDER_RESIZED: "ORDER_RESIZED";
1031
+ readonly ORDER_AMOUNT_SET: "ORDER_AMOUNT_SET";
803
1032
  readonly PAYMENT_CREATED: "PAYMENT_CREATED";
804
1033
  readonly PAYMENT_SETTLED: "PAYMENT_SETTLED";
805
1034
  readonly PAYMENT_CANCELLED: "PAYMENT_CANCELLED";
@@ -868,6 +1097,8 @@ export type WebhookPayload = {
868
1097
  previousAmountUsdc: string;
869
1098
  newAmountUsdc: string;
870
1099
  };
1100
+ /** Only on `ORDER_AMOUNT_SET`. */
1101
+ amountChange?: OrderAmountChange;
871
1102
  };
872
1103
  };
873
1104
  export type CreateWebhookRequest = {
@@ -897,4 +1128,77 @@ export type TestWebhookResponse = {
897
1128
  responseCode?: number | null;
898
1129
  error?: string | null;
899
1130
  };
1131
+ /**
1132
+ * Wallet-snapshot fence rejections (ownership-transfer era rule). PR 4-6 add keys to this object.
1133
+ * MERCHANT_OWNERSHIP_CHANGED is retryable: an order insert lost the era it read its wallet in.
1134
+ * ORDER_FROM_PREVIOUS_OWNER is final: the order belongs to an earlier owner's era.
1135
+ */
1136
+ export declare const MerchantOwnershipErrorCode: {
1137
+ readonly MERCHANT_OWNERSHIP_CHANGED: "MERCHANT_OWNERSHIP_CHANGED";
1138
+ readonly ORDER_FROM_PREVIOUS_OWNER: "ORDER_FROM_PREVIOUS_OWNER";
1139
+ readonly MEMBER_LOCKED: "MEMBER_LOCKED";
1140
+ /** 403: the current merchant is not an enabled, LIVE, eligible Master Merchant Account. */
1141
+ readonly MASTER_MERCHANT_NOT_ENABLED: "MASTER_MERCHANT_NOT_ENABLED";
1142
+ /** 422: the master merchant fee is above the Master Merchant Account's masterMerchantMaxFeeBps, only when the Master Merchant Account has a cap. */
1143
+ readonly MASTER_MERCHANT_FEE_EXCEEDS_CAP: "MASTER_MERCHANT_FEE_EXCEEDS_CAP";
1144
+ /** 422: a payment method's configured fees for some amount band would exceed the max fee. */
1145
+ readonly MASTER_MERCHANT_FEE_EXCEEDS_MAX_FEE: "MASTER_MERCHANT_FEE_EXCEEDS_MAX_FEE";
1146
+ /** 409: the Master Merchant Account can no longer change this sub merchant's fee (transferred, or a transfer is pending). */
1147
+ readonly MASTER_MERCHANT_FEE_LOCKED: "MASTER_MERCHANT_FEE_LOCKED";
1148
+ readonly TRANSFER_ALREADY_PENDING: "TRANSFER_ALREADY_PENDING";
1149
+ readonly WALLET_SETUP_REQUIRED: "WALLET_SETUP_REQUIRED";
1150
+ readonly TERMS_CHANGED: "TERMS_CHANGED";
1151
+ readonly TRANSFER_NOT_FOUND: "TRANSFER_NOT_FOUND";
1152
+ readonly TRANSFER_EMAIL_MISMATCH: "TRANSFER_EMAIL_MISMATCH";
1153
+ readonly TRANSFER_UNAVAILABLE: "TRANSFER_UNAVAILABLE";
1154
+ };
1155
+ export type MerchantOwnershipErrorCodeType = typeof MerchantOwnershipErrorCode[keyof typeof MerchantOwnershipErrorCode];
1156
+ export declare const MERCHANT_OWNERSHIP_CHANGED_MESSAGE = "The merchant account changed owners while this order was being created. Retry to create it for the new owner.";
1157
+ export declare const ORDER_FROM_PREVIOUS_OWNER_MESSAGE = "This order was created before the merchant account changed owners. Ask the merchant for a new payment link.";
1158
+ export declare const ORDER_FROM_PREVIOUS_OWNER_REFUND_MESSAGE = "This order was created before the merchant account changed owners, so it cannot be refunded from this account.";
1159
+ /** Response copy for MEMBER_LOCKED: the Master Merchant Account seat after an ownership transfer can only be removed by an admin. */
1160
+ export declare const MEMBER_LOCKED_MESSAGE = "Locked merchant member can only be removed by an admin";
1161
+ export type OwnershipTransferErrorCodeType = typeof MerchantOwnershipErrorCode.TRANSFER_ALREADY_PENDING | typeof MerchantOwnershipErrorCode.WALLET_SETUP_REQUIRED | typeof MerchantOwnershipErrorCode.TERMS_CHANGED | typeof MerchantOwnershipErrorCode.TRANSFER_NOT_FOUND | typeof MerchantOwnershipErrorCode.TRANSFER_EMAIL_MISMATCH | typeof MerchantOwnershipErrorCode.TRANSFER_UNAVAILABLE;
1162
+ /** One user-facing message per ownership-transfer error; the API and the CLI simulator both send these. */
1163
+ export declare const OWNERSHIP_TRANSFER_ERROR_MESSAGES: Readonly<Record<OwnershipTransferErrorCodeType, string>>;
1164
+ /**
1165
+ * Routing states POST /auth/login returns (HTTP 200, `merchant: null`) instead of auto-claiming an
1166
+ * invite or auto-creating a merchant, while an ownership transfer applies to a user with no merchant.
1167
+ */
1168
+ export declare const OwnershipTransferLoginState: {
1169
+ readonly PENDING_OWNERSHIP_TRANSFER: "PENDING_OWNERSHIP_TRANSFER";
1170
+ readonly OWNERSHIP_TRANSFER_EMAIL_MISMATCH: "OWNERSHIP_TRANSFER_EMAIL_MISMATCH";
1171
+ readonly OWNERSHIP_TRANSFER_UNAVAILABLE: "OWNERSHIP_TRANSFER_UNAVAILABLE";
1172
+ };
1173
+ export type OwnershipTransferLoginStateType = typeof OwnershipTransferLoginState[keyof typeof OwnershipTransferLoginState];
1174
+ /** Discriminator of POST /auth/ownership-transfers/preview. EMAIL_MISMATCH is the spec's `emailMatches: false`. */
1175
+ export declare const OwnershipTransferPreviewState: {
1176
+ readonly PENDING: "PENDING";
1177
+ readonly EMAIL_MISMATCH: "EMAIL_MISMATCH";
1178
+ readonly ACCEPTED: "ACCEPTED";
1179
+ };
1180
+ export type OwnershipTransferPreviewStateType = typeof OwnershipTransferPreviewState[keyof typeof OwnershipTransferPreviewState];
1181
+ /** Mirrors the Prisma enum MerchantOwnershipTransferStatus for pure (Prisma-free) wire schemas. */
1182
+ export declare const OwnershipTransferStatus: {
1183
+ readonly PENDING: "PENDING";
1184
+ readonly ACCEPTED: "ACCEPTED";
1185
+ readonly CANCELLED: "CANCELLED";
1186
+ readonly EXPIRED: "EXPIRED";
1187
+ };
1188
+ export type OwnershipTransferStatusType = typeof OwnershipTransferStatus[keyof typeof OwnershipTransferStatus];
1189
+ export declare const MerchantOwnershipTransferCancelReason: {
1190
+ readonly MASTER_MERCHANT_CANCELLED: "MASTER_MERCHANT_CANCELLED";
1191
+ readonly TERMS_CHANGED: "TERMS_CHANGED";
1192
+ readonly MASTER_MERCHANT_FLAG_REMOVED: "MASTER_MERCHANT_FLAG_REMOVED";
1193
+ };
1194
+ export type MerchantOwnershipTransferCancelReasonType = typeof MerchantOwnershipTransferCancelReason[keyof typeof MerchantOwnershipTransferCancelReason];
1195
+ export declare const OwnershipTransferMasterMerchantPermission: {
1196
+ readonly CHECKOUT_CONFIG: "CHECKOUT_CONFIG";
1197
+ readonly TEAM: "TEAM";
1198
+ };
1199
+ export type OwnershipTransferMasterMerchantPermissionType = typeof OwnershipTransferMasterMerchantPermission[keyof typeof OwnershipTransferMasterMerchantPermission];
1200
+ /** What the Master Merchant Account's locked MANAGER seat keeps after a transfer (spec decisions 2 and 9; refunds are OWNER-only); the accept page lists exactly these. */
1201
+ export declare const OWNERSHIP_TRANSFER_MASTER_MERCHANT_PERMISSIONS: readonly OwnershipTransferMasterMerchantPermissionType[];
1202
+ /** "alice@example.com" → "a•••@example.com". The input is a validated, lowercased address. */
1203
+ export declare function maskOwnershipTransferEmail(email: string): string;
900
1204
  export {};
package/dist/types.js CHANGED
@@ -60,6 +60,7 @@ export const CheckoutMethod = {
60
60
  export const FeePayer = {
61
61
  MERCHANT: 'MERCHANT',
62
62
  PAYEE: 'PAYEE',
63
+ SPLIT: 'SPLIT',
63
64
  };
64
65
  export const MerchantPaymentFlowMode = {
65
66
  EXCLUSIVE_SAR: 'EXCLUSIVE_SAR',
@@ -112,8 +113,47 @@ export const CheckoutPaymentMemoPolicy = {
112
113
  REQUIRED: 'REQUIRED',
113
114
  EMPTY: 'EMPTY',
114
115
  };
116
+ // ============ Open-amount orders ============
117
+ /** FIXED orders carry an amount from creation; OPEN orders get one when the buyer starts a payment. */
118
+ export const OrderAmountMode = {
119
+ FIXED: 'FIXED',
120
+ OPEN: 'OPEN',
121
+ };
122
+ /**
123
+ * Why the buyer can no longer change an open order's amount. Precedence when several apply:
124
+ * PAID, then PAYMENT_MAY_SETTLE, then PAYMENT_IN_PROGRESS.
125
+ */
126
+ export const AmountLockReason = {
127
+ /** Only CREATED non-Zcash payments lock the amount; cancelling them unlocks it. */
128
+ PAYMENT_IN_PROGRESS: 'PAYMENT_IN_PROGRESS',
129
+ /** An EXPIRED payment, a locking Zcash payment or a reopenable FAILED Relay payment can still settle; cancelling cannot unlock it. */
130
+ PAYMENT_MAY_SETTLE: 'PAYMENT_MAY_SETTLE',
131
+ /** A SETTLED payment exists. */
132
+ PAID: 'PAID',
133
+ };
134
+ export const OpenAmountErrorCode = {
135
+ OPEN_AMOUNT_INVALID: 'OPEN_AMOUNT_INVALID',
136
+ OPEN_AMOUNT_DISABLED: 'OPEN_AMOUNT_DISABLED',
137
+ AMOUNT_REQUIRED: 'AMOUNT_REQUIRED',
138
+ AMOUNT_NOT_ALLOWED: 'AMOUNT_NOT_ALLOWED',
139
+ AMOUNT_OUT_OF_RANGE: 'AMOUNT_OUT_OF_RANGE',
140
+ AMOUNT_LOCKED: 'AMOUNT_LOCKED',
141
+ AMOUNT_CONFLICT: 'AMOUNT_CONFLICT',
142
+ RESIZE_NOT_SUPPORTED: 'RESIZE_NOT_SUPPORTED',
143
+ };
144
+ export const PaymentPenaltyKind = {
145
+ PURCHASE_PROTECTION: 'PURCHASE_PROTECTION',
146
+ CROSS_CURRENCY: 'CROSS_CURRENCY',
147
+ };
148
+ export const MerchantUserRole = {
149
+ OWNER: 'OWNER',
150
+ MANAGER: 'MANAGER',
151
+ CASHIER: 'CASHIER',
152
+ };
115
153
  // Structured error codes for Order failures
154
+ export const PAYMENT_CREATION_PAUSED_MESSAGE = 'Payments are temporarily paused. Please try again shortly.';
116
155
  export const OrderErrorCode = {
156
+ PAYMENTS_PAUSED: 'PAYMENTS_PAUSED',
117
157
  // Proof verification errors
118
158
  PROOF_INVALID: 'PROOF_INVALID', // Proof data failed attestation verification
119
159
  PROOF_EXPIRED: 'PROOF_EXPIRED', // Proof timestamp too old
@@ -131,6 +171,8 @@ export const OrderErrorCode = {
131
171
  BRIDGE_TIMEOUT: 'BRIDGE_TIMEOUT', // Bridge fill timed out
132
172
  // Fee threshold errors (exact-fiat mode)
133
173
  FEE_THRESHOLD_EXCEEDED: 'FEE_THRESHOLD_EXCEEDED', // Quote fee exceeds merchant's max
174
+ // Payment start limits
175
+ INTENT_ABOVE_MAX: 'INTENT_ABOVE_MAX', // On-chain intent above the per-payment limit (fees included)
134
176
  // Generic
135
177
  SDK_ERROR: 'SDK_ERROR', // Unknown SDK error
136
178
  UNKNOWN_ERROR: 'UNKNOWN_ERROR', // Uncategorized error
@@ -163,12 +205,18 @@ export const OnboardingStepVerifiedBy = {
163
205
  AUTO: 'auto',
164
206
  MANUAL: 'manual',
165
207
  };
208
+ export const MERCHANT_REFERRAL_FEE_BPS_BY_TIER = {
209
+ BASE: 30,
210
+ PRO: 50,
211
+ CONCIERGE: 100,
212
+ };
166
213
  // ============ Webhook Types ============
167
214
  export const WebhookEventType = {
168
215
  ORDER_CREATED: 'ORDER_CREATED',
169
216
  ORDER_FULFILLED: 'ORDER_FULFILLED',
170
217
  ORDER_CANCELLED: 'ORDER_CANCELLED',
171
218
  ORDER_RESIZED: 'ORDER_RESIZED',
219
+ ORDER_AMOUNT_SET: 'ORDER_AMOUNT_SET',
172
220
  PAYMENT_CREATED: 'PAYMENT_CREATED',
173
221
  PAYMENT_SETTLED: 'PAYMENT_SETTLED',
174
222
  PAYMENT_CANCELLED: 'PAYMENT_CANCELLED',
@@ -189,3 +237,84 @@ export const WebhookDeliveryStatus = {
189
237
  DELIVERED: 'DELIVERED',
190
238
  FAILED: 'FAILED',
191
239
  };
240
+ /**
241
+ * Wallet-snapshot fence rejections (ownership-transfer era rule). PR 4-6 add keys to this object.
242
+ * MERCHANT_OWNERSHIP_CHANGED is retryable: an order insert lost the era it read its wallet in.
243
+ * ORDER_FROM_PREVIOUS_OWNER is final: the order belongs to an earlier owner's era.
244
+ */
245
+ export const MerchantOwnershipErrorCode = {
246
+ MERCHANT_OWNERSHIP_CHANGED: 'MERCHANT_OWNERSHIP_CHANGED',
247
+ ORDER_FROM_PREVIOUS_OWNER: 'ORDER_FROM_PREVIOUS_OWNER',
248
+ MEMBER_LOCKED: 'MEMBER_LOCKED',
249
+ /** 403: the current merchant is not an enabled, LIVE, eligible Master Merchant Account. */
250
+ MASTER_MERCHANT_NOT_ENABLED: 'MASTER_MERCHANT_NOT_ENABLED',
251
+ /** 422: the master merchant fee is above the Master Merchant Account's masterMerchantMaxFeeBps, only when the Master Merchant Account has a cap. */
252
+ MASTER_MERCHANT_FEE_EXCEEDS_CAP: 'MASTER_MERCHANT_FEE_EXCEEDS_CAP',
253
+ /** 422: a payment method's configured fees for some amount band would exceed the max fee. */
254
+ MASTER_MERCHANT_FEE_EXCEEDS_MAX_FEE: 'MASTER_MERCHANT_FEE_EXCEEDS_MAX_FEE',
255
+ /** 409: the Master Merchant Account can no longer change this sub merchant's fee (transferred, or a transfer is pending). */
256
+ MASTER_MERCHANT_FEE_LOCKED: 'MASTER_MERCHANT_FEE_LOCKED',
257
+ TRANSFER_ALREADY_PENDING: 'TRANSFER_ALREADY_PENDING',
258
+ WALLET_SETUP_REQUIRED: 'WALLET_SETUP_REQUIRED',
259
+ TERMS_CHANGED: 'TERMS_CHANGED',
260
+ TRANSFER_NOT_FOUND: 'TRANSFER_NOT_FOUND',
261
+ TRANSFER_EMAIL_MISMATCH: 'TRANSFER_EMAIL_MISMATCH',
262
+ TRANSFER_UNAVAILABLE: 'TRANSFER_UNAVAILABLE',
263
+ };
264
+ export const MERCHANT_OWNERSHIP_CHANGED_MESSAGE = 'The merchant account changed owners while this order was being created. Retry to create it for the new owner.';
265
+ export const ORDER_FROM_PREVIOUS_OWNER_MESSAGE = 'This order was created before the merchant account changed owners. Ask the merchant for a new payment link.';
266
+ export const ORDER_FROM_PREVIOUS_OWNER_REFUND_MESSAGE = 'This order was created before the merchant account changed owners, so it cannot be refunded from this account.';
267
+ /** Response copy for MEMBER_LOCKED: the Master Merchant Account seat after an ownership transfer can only be removed by an admin. */
268
+ export const MEMBER_LOCKED_MESSAGE = 'Locked merchant member can only be removed by an admin';
269
+ /** One user-facing message per ownership-transfer error; the API and the CLI simulator both send these. */
270
+ export const OWNERSHIP_TRANSFER_ERROR_MESSAGES = {
271
+ TRANSFER_ALREADY_PENDING: 'A transfer is already pending for this merchant account',
272
+ WALLET_SETUP_REQUIRED: 'Set up your wallet in the dashboard before accepting this transfer',
273
+ TERMS_CHANGED: 'The transfer terms changed; review them again before accepting',
274
+ TRANSFER_NOT_FOUND: 'Ownership transfer not found',
275
+ TRANSFER_EMAIL_MISMATCH: 'This transfer is for a different email',
276
+ TRANSFER_UNAVAILABLE: 'This transfer was withdrawn or expired',
277
+ };
278
+ /**
279
+ * Routing states POST /auth/login returns (HTTP 200, `merchant: null`) instead of auto-claiming an
280
+ * invite or auto-creating a merchant, while an ownership transfer applies to a user with no merchant.
281
+ */
282
+ export const OwnershipTransferLoginState = {
283
+ PENDING_OWNERSHIP_TRANSFER: 'PENDING_OWNERSHIP_TRANSFER',
284
+ OWNERSHIP_TRANSFER_EMAIL_MISMATCH: 'OWNERSHIP_TRANSFER_EMAIL_MISMATCH',
285
+ OWNERSHIP_TRANSFER_UNAVAILABLE: 'OWNERSHIP_TRANSFER_UNAVAILABLE',
286
+ };
287
+ /** Discriminator of POST /auth/ownership-transfers/preview. EMAIL_MISMATCH is the spec's `emailMatches: false`. */
288
+ export const OwnershipTransferPreviewState = {
289
+ PENDING: 'PENDING',
290
+ EMAIL_MISMATCH: 'EMAIL_MISMATCH',
291
+ ACCEPTED: 'ACCEPTED',
292
+ };
293
+ /** Mirrors the Prisma enum MerchantOwnershipTransferStatus for pure (Prisma-free) wire schemas. */
294
+ export const OwnershipTransferStatus = {
295
+ PENDING: 'PENDING',
296
+ ACCEPTED: 'ACCEPTED',
297
+ CANCELLED: 'CANCELLED',
298
+ EXPIRED: 'EXPIRED',
299
+ };
300
+ export const MerchantOwnershipTransferCancelReason = {
301
+ MASTER_MERCHANT_CANCELLED: 'MASTER_MERCHANT_CANCELLED',
302
+ TERMS_CHANGED: 'TERMS_CHANGED',
303
+ MASTER_MERCHANT_FLAG_REMOVED: 'MASTER_MERCHANT_FLAG_REMOVED',
304
+ };
305
+ export const OwnershipTransferMasterMerchantPermission = {
306
+ CHECKOUT_CONFIG: 'CHECKOUT_CONFIG',
307
+ TEAM: 'TEAM',
308
+ };
309
+ /** What the Master Merchant Account's locked MANAGER seat keeps after a transfer (spec decisions 2 and 9; refunds are OWNER-only); the accept page lists exactly these. */
310
+ export const OWNERSHIP_TRANSFER_MASTER_MERCHANT_PERMISSIONS = [
311
+ OwnershipTransferMasterMerchantPermission.CHECKOUT_CONFIG,
312
+ OwnershipTransferMasterMerchantPermission.TEAM,
313
+ ];
314
+ /** "alice@example.com" → "a•••@example.com". The input is a validated, lowercased address. */
315
+ export function maskOwnershipTransferEmail(email) {
316
+ const at = email.indexOf('@');
317
+ if (at < 1)
318
+ throw new Error('Cannot mask an address without a local part');
319
+ return `${email.slice(0, 1)}•••${email.slice(at)}`;
320
+ }