@zkp2p/pay-shared 4.0.0 → 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.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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zkp2p/pay-shared",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Shared TypeScript types, enums, and chain utilities used by ZKP2P Pay API, SDK, and frontend apps.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -39,7 +39,7 @@
39
39
  "lint": "eslint . --ext .ts,.tsx",
40
40
  "test": "vitest run",
41
41
  "prepack": "npm run build",
42
- "prepublishOnly": "npm pack --dry-run"
42
+ "prepublishOnly": "npm run lint"
43
43
  },
44
44
  "devDependencies": {
45
45
  "vitest": "^1.6.1"