@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/README.md +2 -2
- package/dist/addressValidators.d.ts +2 -0
- package/dist/addressValidators.js +12 -1
- package/dist/chains.js +9 -0
- package/dist/clientTelemetry.d.ts +25 -0
- package/dist/clientTelemetry.js +30 -0
- package/dist/conciergeIntake.d.ts +56 -0
- package/dist/conciergeIntake.js +15 -0
- package/dist/crypto.d.ts +4 -2
- package/dist/crypto.js +13 -0
- package/dist/fees.d.ts +2 -0
- package/dist/fees.js +10 -0
- package/dist/fiatAmount.d.ts +9 -4
- package/dist/fiatAmount.js +40 -4
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/llmIntegration.d.ts +0 -4
- package/dist/masterMerchantSubMerchants.d.ts +74 -0
- package/dist/masterMerchantSubMerchants.js +20 -0
- package/dist/onboarding.js +7 -6
- package/dist/payeeFeeCap.d.ts +10 -0
- package/dist/payeeFeeCap.js +20 -0
- package/dist/paymentRecovery.d.ts +26 -0
- package/dist/paymentRecovery.js +27 -0
- package/dist/rails.d.ts +20 -2
- package/dist/rails.js +42 -4
- package/dist/sandboxPricing.d.ts +30 -0
- package/dist/sandboxPricing.js +53 -0
- package/dist/tiers.d.ts +13 -2
- package/dist/tiers.js +12 -2
- package/dist/types.d.ts +316 -11
- package/dist/types.js +129 -0
- package/package.json +2 -2
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Fiat payTo is a protocol hash; the saved quote owns the readable recipient. */
|
|
2
|
+
export function paymentRecoveryRecipient(payment) {
|
|
3
|
+
const quote = payment.quote;
|
|
4
|
+
if (typeof quote === 'object' && quote !== null && 'maker' in quote) {
|
|
5
|
+
const maker = quote.maker;
|
|
6
|
+
if (typeof maker === 'object' && maker !== null && 'depositData' in maker) {
|
|
7
|
+
const data = maker.depositData;
|
|
8
|
+
if (typeof data === 'object' && data !== null && 'offchainId' in data) {
|
|
9
|
+
const recipient = data.offchainId;
|
|
10
|
+
if (typeof recipient === 'string' && recipient.trim() !== '')
|
|
11
|
+
return recipient;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// Historical rows can lack maker data. Never present a bytes32 hash as a name.
|
|
16
|
+
return /^0x[\da-f]{64}$/i.test(payment.payTo) ? 'Recipient unavailable' : payment.payTo;
|
|
17
|
+
}
|
|
18
|
+
/** Old attempts without a snapshot have no reliable historical requested amount. */
|
|
19
|
+
export function paymentRecoveryAmount(payment) {
|
|
20
|
+
if (payment.status === 'SETTLED')
|
|
21
|
+
return Number(payment.paymentAmount) > 0 ? payment.paymentAmount : null;
|
|
22
|
+
const quote = payment.quote;
|
|
23
|
+
if (typeof quote !== 'object' || quote === null || !('recoveryDisplayAmount' in quote))
|
|
24
|
+
return null;
|
|
25
|
+
const amount = quote.recoveryDisplayAmount;
|
|
26
|
+
return typeof amount === 'string' && /^\d+(\.\d+)?$/.test(amount) && Number(amount) > 0 ? amount : null;
|
|
27
|
+
}
|
package/dist/rails.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
export declare const ZCASH_RAIL = "near_intents_133701";
|
|
1
2
|
export declare enum SupportedRail {
|
|
3
|
+
NEAR_INTENTS_ZCASH = "near_intents_133701",
|
|
4
|
+
APPLE_PAY = "apple_pay",
|
|
2
5
|
VENMO = "venmo",
|
|
3
6
|
CASHAPP = "cashapp",
|
|
4
7
|
REVOLUT = "revolut",
|
|
@@ -14,6 +17,7 @@ export declare enum SupportedRail {
|
|
|
14
17
|
RELAY_137 = "relay_137",
|
|
15
18
|
RELAY_480 = "relay_480",
|
|
16
19
|
RELAY_999 = "relay_999",
|
|
20
|
+
RELAY_5042 = "relay_5042",
|
|
17
21
|
RELAY_8453 = "relay_8453",
|
|
18
22
|
RELAY_42161 = "relay_42161",
|
|
19
23
|
RELAY_8253038 = "relay_8253038",
|
|
@@ -33,6 +37,7 @@ export declare enum SupportedRelayRail {
|
|
|
33
37
|
RELAY_137 = "relay_137",
|
|
34
38
|
RELAY_480 = "relay_480",
|
|
35
39
|
RELAY_999 = "relay_999",
|
|
40
|
+
RELAY_5042 = "relay_5042",
|
|
36
41
|
RELAY_8453 = "relay_8453",
|
|
37
42
|
RELAY_42161 = "relay_42161",
|
|
38
43
|
RELAY_8253038 = "relay_8253038",
|
|
@@ -43,6 +48,16 @@ export declare const DEFAULT_FIAT_RAILS: readonly SupportedRail[];
|
|
|
43
48
|
export declare const SUPPORTED_RAILS: readonly SupportedRail[];
|
|
44
49
|
export declare const SUPPORTED_RELAY_RAILS: readonly SupportedRelayRail[];
|
|
45
50
|
export declare const FIAT_SUPPORTED_RAILS: readonly ["venmo", "cashapp", "revolut", "wise", "zelle", "paypal", "monzo", "n26", "chime"];
|
|
51
|
+
/**
|
|
52
|
+
* Coinbase Apple Pay. A third rail category: it is not a fiat rail (no fiat
|
|
53
|
+
* payment and no attestation) and not a crypto rail (the customer never sends
|
|
54
|
+
* crypto). Merchants enable it like any other method, but the resulting payment
|
|
55
|
+
* is recorded against the Relay rail it settles on, not against this key.
|
|
56
|
+
*/
|
|
57
|
+
export declare const APPLE_PAY_RAIL = SupportedRail.APPLE_PAY;
|
|
58
|
+
export declare const APPLE_PAY_MAX_AMOUNT_USDC_BASE_UNITS = 2500000000n;
|
|
59
|
+
export declare const APPLE_PAY_LIMIT_MESSAGE = "This order exceeds the Apple Pay limit. Choose another payment method.";
|
|
60
|
+
export declare function isOnrampRail(rail: string | null | undefined): boolean;
|
|
46
61
|
export type FiatSupportedRail = typeof FIAT_SUPPORTED_RAILS[number];
|
|
47
62
|
export declare const PAYMENT_PLATFORM_LABELS: Record<string, string>;
|
|
48
63
|
export declare const FIAT_RAIL_DISPLAY_NAMES: Record<FiatSupportedRail, string>;
|
|
@@ -82,9 +97,12 @@ export declare function setRuntimeDisabledFiatRails(rails: readonly string[]): v
|
|
|
82
97
|
export declare function getRuntimeDisabledFiatRails(): string[];
|
|
83
98
|
/** Returns true when the rail targets a crypto chain (legacy numeric or relay-prefixed format). */
|
|
84
99
|
export declare function isCryptoRail(rail: string | null | undefined): boolean;
|
|
100
|
+
/** A rail the customer pays on with fiat: excludes crypto rails and onramp
|
|
101
|
+
* rails such as Apple Pay, whose payments settle on a Relay rail instead. */
|
|
102
|
+
export declare function isFiatPaymentRail(rail: string | null | undefined): boolean;
|
|
85
103
|
/** Formats a chain id into the canonical relay rail string: `relay_<chainId>`. */
|
|
86
104
|
export declare function formatRelayRail(chainId: number): string;
|
|
87
|
-
/** Normalizes
|
|
105
|
+
/** Normalizes a crypto rail into its canonical provider format (or null for non-crypto rails). */
|
|
88
106
|
export declare function normalizeCryptoRail(rail: string | null | undefined): string | null;
|
|
89
107
|
/** Returns the canonical base fiat rail for base rails and supported variants such as `zelle-chase`. */
|
|
90
108
|
export declare function normalizeFiatRail(rail: string | null | undefined): string | null;
|
|
@@ -104,7 +122,7 @@ export declare function isSarSupportedFiatRail(rail: string | null | undefined):
|
|
|
104
122
|
* rails (e.g. `zelle`, `revolut`, incl. variants like `zelle-chase`) are dropped
|
|
105
123
|
* while crypto rails and SAR rails (venmo/cashapp/wise/paypal) are kept.
|
|
106
124
|
*/
|
|
107
|
-
export declare function filterRailsForExclusiveSar(rails: readonly
|
|
125
|
+
export declare function filterRailsForExclusiveSar<T extends string>(rails: readonly T[]): T[];
|
|
108
126
|
/** Canonical Zelle paymentMethodId -> attestation-service actionType suffix. */
|
|
109
127
|
export declare const ZELLE_METHOD_ACTION_SUFFIX: Record<string, string>;
|
|
110
128
|
/** Strict create-boundary set for Zelle method ids and transitional variant rails. */
|
package/dist/rails.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { ZCASH_CHAIN_ID } from './crypto.js';
|
|
1
2
|
const RELAY_RAIL_PREFIX = 'relay_';
|
|
3
|
+
export const ZCASH_RAIL = 'near_intents_133701';
|
|
2
4
|
export var SupportedRail;
|
|
3
5
|
(function (SupportedRail) {
|
|
6
|
+
SupportedRail["NEAR_INTENTS_ZCASH"] = "near_intents_133701";
|
|
7
|
+
SupportedRail["APPLE_PAY"] = "apple_pay";
|
|
4
8
|
SupportedRail["VENMO"] = "venmo";
|
|
5
9
|
SupportedRail["CASHAPP"] = "cashapp";
|
|
6
10
|
SupportedRail["REVOLUT"] = "revolut";
|
|
@@ -16,6 +20,7 @@ export var SupportedRail;
|
|
|
16
20
|
SupportedRail["RELAY_137"] = "relay_137";
|
|
17
21
|
SupportedRail["RELAY_480"] = "relay_480";
|
|
18
22
|
SupportedRail["RELAY_999"] = "relay_999";
|
|
23
|
+
SupportedRail["RELAY_5042"] = "relay_5042";
|
|
19
24
|
SupportedRail["RELAY_8453"] = "relay_8453";
|
|
20
25
|
SupportedRail["RELAY_42161"] = "relay_42161";
|
|
21
26
|
SupportedRail["RELAY_8253038"] = "relay_8253038";
|
|
@@ -36,6 +41,7 @@ export var SupportedRelayRail;
|
|
|
36
41
|
SupportedRelayRail["RELAY_137"] = "relay_137";
|
|
37
42
|
SupportedRelayRail["RELAY_480"] = "relay_480";
|
|
38
43
|
SupportedRelayRail["RELAY_999"] = "relay_999";
|
|
44
|
+
SupportedRelayRail["RELAY_5042"] = "relay_5042";
|
|
39
45
|
SupportedRelayRail["RELAY_8453"] = "relay_8453";
|
|
40
46
|
SupportedRelayRail["RELAY_42161"] = "relay_42161";
|
|
41
47
|
SupportedRelayRail["RELAY_8253038"] = "relay_8253038";
|
|
@@ -68,6 +74,19 @@ export const FIAT_SUPPORTED_RAILS = [
|
|
|
68
74
|
'n26',
|
|
69
75
|
'chime',
|
|
70
76
|
];
|
|
77
|
+
/**
|
|
78
|
+
* Coinbase Apple Pay. A third rail category: it is not a fiat rail (no fiat
|
|
79
|
+
* payment and no attestation) and not a crypto rail (the customer never sends
|
|
80
|
+
* crypto). Merchants enable it like any other method, but the resulting payment
|
|
81
|
+
* is recorded against the Relay rail it settles on, not against this key.
|
|
82
|
+
*/
|
|
83
|
+
export const APPLE_PAY_RAIL = SupportedRail.APPLE_PAY;
|
|
84
|
+
// Peer Pay per-order ceiling, in USDC base units. Coinbase may allow less per buyer.
|
|
85
|
+
export const APPLE_PAY_MAX_AMOUNT_USDC_BASE_UNITS = 2500000000n;
|
|
86
|
+
export const APPLE_PAY_LIMIT_MESSAGE = 'This order exceeds the Apple Pay limit. Choose another payment method.';
|
|
87
|
+
export function isOnrampRail(rail) {
|
|
88
|
+
return rail === APPLE_PAY_RAIL;
|
|
89
|
+
}
|
|
71
90
|
const PAYMENT_PLATFORM_LABEL_ENTRIES = {
|
|
72
91
|
[SupportedRail.VENMO]: 'Venmo',
|
|
73
92
|
[SupportedRail.CASHAPP]: 'Cash App',
|
|
@@ -79,7 +98,10 @@ const PAYMENT_PLATFORM_LABEL_ENTRIES = {
|
|
|
79
98
|
[SupportedRail.N26]: 'N26',
|
|
80
99
|
[SupportedRail.CHIME]: 'Chime',
|
|
81
100
|
};
|
|
82
|
-
export const PAYMENT_PLATFORM_LABELS =
|
|
101
|
+
export const PAYMENT_PLATFORM_LABELS = {
|
|
102
|
+
...PAYMENT_PLATFORM_LABEL_ENTRIES,
|
|
103
|
+
[SupportedRail.APPLE_PAY]: 'Apple Pay',
|
|
104
|
+
};
|
|
83
105
|
export const FIAT_RAIL_DISPLAY_NAMES = PAYMENT_PLATFORM_LABEL_ENTRIES;
|
|
84
106
|
// Shared FE/BE minimum so queries too short for the pg_trgm trigram index are no-ops.
|
|
85
107
|
export const ORDER_SEARCH_MIN_QUERY_LENGTH = 3;
|
|
@@ -100,6 +122,7 @@ export const RELAY_CHAIN_DISPLAY_NAMES = {
|
|
|
100
122
|
137: 'Polygon',
|
|
101
123
|
480: 'World Chain',
|
|
102
124
|
999: 'Hyperliquid',
|
|
125
|
+
5042: 'Arc',
|
|
103
126
|
8453: 'Base',
|
|
104
127
|
42161: 'Arbitrum',
|
|
105
128
|
8253038: 'Bitcoin',
|
|
@@ -107,6 +130,8 @@ export const RELAY_CHAIN_DISPLAY_NAMES = {
|
|
|
107
130
|
792703809: 'Solana',
|
|
108
131
|
};
|
|
109
132
|
const CRYPTO_METHOD_ALIASES = [
|
|
133
|
+
'zcash',
|
|
134
|
+
'zec',
|
|
110
135
|
'crypto',
|
|
111
136
|
'usdc',
|
|
112
137
|
'usdt',
|
|
@@ -134,20 +159,22 @@ export function parseCryptoRailChainId(rail) {
|
|
|
134
159
|
return null;
|
|
135
160
|
}
|
|
136
161
|
const trimmed = rail.trim();
|
|
162
|
+
if (trimmed === ZCASH_RAIL)
|
|
163
|
+
return ZCASH_CHAIN_ID;
|
|
137
164
|
if (trimmed === '') {
|
|
138
165
|
return null;
|
|
139
166
|
}
|
|
140
167
|
const numericMatch = /^\d+$/.exec(trimmed);
|
|
141
168
|
if (numericMatch !== null) {
|
|
142
169
|
const parsed = Number(trimmed);
|
|
143
|
-
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
|
|
170
|
+
return Number.isSafeInteger(parsed) && parsed > 0 && parsed !== ZCASH_CHAIN_ID ? parsed : null;
|
|
144
171
|
}
|
|
145
172
|
const prefixedMatch = /^relay_(\d+)$/i.exec(trimmed);
|
|
146
173
|
if (prefixedMatch === null) {
|
|
147
174
|
return null;
|
|
148
175
|
}
|
|
149
176
|
const parsed = Number(prefixedMatch[1]);
|
|
150
|
-
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
|
|
177
|
+
return Number.isSafeInteger(parsed) && parsed > 0 && parsed !== ZCASH_CHAIN_ID ? parsed : null;
|
|
151
178
|
}
|
|
152
179
|
export function isSupportedRail(rail) {
|
|
153
180
|
return SUPPORTED_RAIL_SET.has(rail);
|
|
@@ -195,6 +222,11 @@ export function getRuntimeDisabledFiatRails() {
|
|
|
195
222
|
export function isCryptoRail(rail) {
|
|
196
223
|
return parseCryptoRailChainId(rail) !== null;
|
|
197
224
|
}
|
|
225
|
+
/** A rail the customer pays on with fiat: excludes crypto rails and onramp
|
|
226
|
+
* rails such as Apple Pay, whose payments settle on a Relay rail instead. */
|
|
227
|
+
export function isFiatPaymentRail(rail) {
|
|
228
|
+
return !isCryptoRail(rail) && !isOnrampRail(rail);
|
|
229
|
+
}
|
|
198
230
|
/** Formats a chain id into the canonical relay rail string: `relay_<chainId>`. */
|
|
199
231
|
export function formatRelayRail(chainId) {
|
|
200
232
|
if (!Number.isSafeInteger(chainId) || chainId <= 0) {
|
|
@@ -202,8 +234,10 @@ export function formatRelayRail(chainId) {
|
|
|
202
234
|
}
|
|
203
235
|
return `${RELAY_RAIL_PREFIX}${chainId}`;
|
|
204
236
|
}
|
|
205
|
-
/** Normalizes
|
|
237
|
+
/** Normalizes a crypto rail into its canonical provider format (or null for non-crypto rails). */
|
|
206
238
|
export function normalizeCryptoRail(rail) {
|
|
239
|
+
if (rail?.trim() === ZCASH_RAIL)
|
|
240
|
+
return ZCASH_RAIL;
|
|
207
241
|
const chainId = parseCryptoRailChainId(rail);
|
|
208
242
|
return chainId === null ? null : formatRelayRail(chainId);
|
|
209
243
|
}
|
|
@@ -307,7 +341,11 @@ export function getRailDisplayName(rail) {
|
|
|
307
341
|
if (trimmed === '') {
|
|
308
342
|
return 'Unknown';
|
|
309
343
|
}
|
|
344
|
+
if (trimmed === ZCASH_RAIL)
|
|
345
|
+
return 'Zcash (NEAR Intents)';
|
|
310
346
|
const normalized = trimmed.toLowerCase();
|
|
347
|
+
if (isOnrampRail(normalized))
|
|
348
|
+
return PAYMENT_PLATFORM_LABELS[APPLE_PAY_RAIL];
|
|
311
349
|
if (isFiatSupportedRail(normalized)) {
|
|
312
350
|
return FIAT_RAIL_DISPLAY_NAMES[normalized];
|
|
313
351
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Applies a deterministic per-rail spread (±3%) on top of the live fiat-per-USD
|
|
3
|
+
* rate so sandbox quotes vary by payment method. The spread is hashed from the
|
|
4
|
+
* rail identifier + currency so refreshes are stable and different merchants
|
|
5
|
+
* see consistent rates, without any rail getting an unrealistic 0% spread.
|
|
6
|
+
*/
|
|
7
|
+
export declare function applySandboxRailSpread(baseRate: number, rail: string, currency: string): number;
|
|
8
|
+
/** Deterministic sandbox maker spread and fee-share sizing, shared with the CLI. */
|
|
9
|
+
export declare function buildSandboxSplitFiatAmounts(input: {
|
|
10
|
+
principalUsd: string;
|
|
11
|
+
currencyPerUsdRate: string;
|
|
12
|
+
rail: string;
|
|
13
|
+
fiatCurrency: string;
|
|
14
|
+
buyerFeeShareBps: number;
|
|
15
|
+
totalReferralFeeBps: number;
|
|
16
|
+
}): {
|
|
17
|
+
paymentAmount: string;
|
|
18
|
+
grossUsdcAmount: string;
|
|
19
|
+
conversionRate: string;
|
|
20
|
+
signalIntentAmountBaseUnits: string;
|
|
21
|
+
};
|
|
22
|
+
/** Preserve the saved signal for a full payment; scale a partial fiat payment at its saved maker rate. */
|
|
23
|
+
export declare function settleSandboxSplitFiatAmounts(input: {
|
|
24
|
+
signalIntentAmountBaseUnits: string;
|
|
25
|
+
conversionRateDecimal: string;
|
|
26
|
+
paidFiatAmount?: string;
|
|
27
|
+
}): {
|
|
28
|
+
paymentAmount: string;
|
|
29
|
+
grossUsdcAmount: string;
|
|
30
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { computeDisplayedFiatAmount } from './fiatAmount.js';
|
|
2
|
+
const MAX_RAIL_SPREAD = 0.03; // ±3% around the live FX rate
|
|
3
|
+
const SPREAD_BUCKETS = 601; // integer granularity for the deterministic hash
|
|
4
|
+
/**
|
|
5
|
+
* Applies a deterministic per-rail spread (±3%) on top of the live fiat-per-USD
|
|
6
|
+
* rate so sandbox quotes vary by payment method. The spread is hashed from the
|
|
7
|
+
* rail identifier + currency so refreshes are stable and different merchants
|
|
8
|
+
* see consistent rates, without any rail getting an unrealistic 0% spread.
|
|
9
|
+
*/
|
|
10
|
+
export function applySandboxRailSpread(baseRate, rail, currency) {
|
|
11
|
+
const seed = `${rail.trim().toLowerCase()}|${currency.trim().toUpperCase()}`;
|
|
12
|
+
let hash = 0;
|
|
13
|
+
for (let i = 0; i < seed.length; i += 1) {
|
|
14
|
+
hash = ((hash * 31) + seed.charCodeAt(i)) | 0;
|
|
15
|
+
}
|
|
16
|
+
const bucket = Math.abs(hash) % SPREAD_BUCKETS; // [0, 600]
|
|
17
|
+
const normalized = (bucket - (SPREAD_BUCKETS - 1) / 2) / ((SPREAD_BUCKETS - 1) / 2); // [-1, 1]
|
|
18
|
+
const spread = normalized * MAX_RAIL_SPREAD;
|
|
19
|
+
return baseRate * (1 + spread);
|
|
20
|
+
}
|
|
21
|
+
function decimalUnits(value, decimals) {
|
|
22
|
+
const [whole, fraction = ''] = value.split('.');
|
|
23
|
+
return BigInt(whole) * 10n ** BigInt(decimals) + BigInt(fraction.slice(0, decimals).padEnd(decimals, '0'));
|
|
24
|
+
}
|
|
25
|
+
function usdFromUnits(units) {
|
|
26
|
+
return `${units / 1000000n}.${(units % 1000000n).toString().padStart(6, '0')}`;
|
|
27
|
+
}
|
|
28
|
+
/** Deterministic sandbox maker spread and fee-share sizing, shared with the CLI. */
|
|
29
|
+
export function buildSandboxSplitFiatAmounts(input) {
|
|
30
|
+
const rawRate = String(applySandboxRailSpread(Number(input.currencyPerUsdRate), input.rail, input.fiatCurrency));
|
|
31
|
+
const [whole, fraction = ''] = rawRate.split('.');
|
|
32
|
+
const conversionRate = fraction === '' ? whole : `${whole}.${fraction.slice(0, 6)}`;
|
|
33
|
+
const rate = decimalUnits(conversionRate, 18);
|
|
34
|
+
const peg = decimalUnits(input.currencyPerUsdRate, 18);
|
|
35
|
+
const share = BigInt(input.buyerFeeShareBps);
|
|
36
|
+
const denominator = (10000n - share) * rate * 10000n + share * (10000n - BigInt(input.totalReferralFeeBps)) * peg;
|
|
37
|
+
if (denominator <= 0n)
|
|
38
|
+
throw new Error('Split sandbox quote has no positive principal contribution');
|
|
39
|
+
const numerator = decimalUnits(input.principalUsd, 6) * 100000000n * peg;
|
|
40
|
+
const signalIntentAmountBaseUnits = ((numerator + denominator - 1n) / denominator).toString();
|
|
41
|
+
return { conversionRate, signalIntentAmountBaseUnits,
|
|
42
|
+
...settleSandboxSplitFiatAmounts({ signalIntentAmountBaseUnits, conversionRateDecimal: conversionRate }) };
|
|
43
|
+
}
|
|
44
|
+
/** Preserve the saved signal for a full payment; scale a partial fiat payment at its saved maker rate. */
|
|
45
|
+
export function settleSandboxSplitFiatAmounts(input) {
|
|
46
|
+
const paymentAmount = input.paidFiatAmount ?? computeDisplayedFiatAmount({
|
|
47
|
+
feePayer: 'SPLIT', signalIntentAmountBaseUnits: input.signalIntentAmountBaseUnits,
|
|
48
|
+
conversionRateDecimal: input.conversionRateDecimal, remainingUsdcAmount: '1', currencyPerUsdRate: '1', paymentAmountFallback: '0',
|
|
49
|
+
});
|
|
50
|
+
const grossUnits = input.paidFiatAmount === undefined ? BigInt(input.signalIntentAmountBaseUnits)
|
|
51
|
+
: decimalUnits(paymentAmount, 18) * 1000000n / decimalUnits(input.conversionRateDecimal, 18);
|
|
52
|
+
return { paymentAmount, grossUsdcAmount: usdFromUnits(grossUnits) };
|
|
53
|
+
}
|
package/dist/tiers.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { type FeeTranche, type MerchantPaymentFlowModeType, type MerchantTierName } from './types.js';
|
|
1
|
+
import { type FeeTranche, type MerchantEnvironmentType, type MerchantPaymentFlowModeType, type MerchantTierName } from './types.js';
|
|
2
2
|
export type { MerchantTierName } from './types.js';
|
|
3
3
|
export declare const TierChangeSource: {
|
|
4
4
|
readonly SELF_SERVE: "SELF_SERVE";
|
|
5
5
|
readonly ADMIN: "ADMIN";
|
|
6
6
|
readonly MIGRATION: "MIGRATION";
|
|
7
|
+
/** A Master Merchant Account sub-merchant copied its Master Merchant Account's tier at creation. */
|
|
8
|
+
readonly SUB_MERCHANT: "SUB_MERCHANT";
|
|
7
9
|
};
|
|
8
10
|
export type TierChangeSourceType = typeof TierChangeSource[keyof typeof TierChangeSource];
|
|
9
11
|
/**
|
|
@@ -51,7 +53,16 @@ export declare const TIER_DEFINITIONS: Readonly<Record<MerchantTierName, TierDef
|
|
|
51
53
|
/** Server-side allowlist for self-serve tier selection — the only authority; `features` copy gates nothing. */
|
|
52
54
|
export declare const SELF_SERVE_TIERS: readonly MerchantTierName[];
|
|
53
55
|
/**
|
|
54
|
-
*
|
|
56
|
+
* Scan to Pay depends on seller automated release, which is available to Pro and Concierge merchants.
|
|
57
|
+
* Sandbox stays available so merchants can complete the no-value onboarding demo
|
|
58
|
+
* before choosing a live plan.
|
|
59
|
+
*/
|
|
60
|
+
export declare function canUseScanToPay(input: {
|
|
61
|
+
readonly tier: MerchantTierName | null | undefined;
|
|
62
|
+
readonly environment: MerchantEnvironmentType;
|
|
63
|
+
}): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Formats a tier's monthly caps for display; caps count fiat-paid orders only. `volumeUsdc` is a whole-USDC decimal string;
|
|
55
66
|
* exact thousands render as `$10K`, anything else as `$2,500`.
|
|
56
67
|
*/
|
|
57
68
|
export declare function formatTierMonthlyLimitsCopy(limits: TierMonthlyLimits | null): string;
|
package/dist/tiers.js
CHANGED
|
@@ -3,6 +3,8 @@ export const TierChangeSource = {
|
|
|
3
3
|
SELF_SERVE: 'SELF_SERVE',
|
|
4
4
|
ADMIN: 'ADMIN',
|
|
5
5
|
MIGRATION: 'MIGRATION',
|
|
6
|
+
/** A Master Merchant Account sub-merchant copied its Master Merchant Account's tier at creation. */
|
|
7
|
+
SUB_MERCHANT: 'SUB_MERCHANT',
|
|
6
8
|
};
|
|
7
9
|
export const TIER_DEFINITIONS = {
|
|
8
10
|
BASE: {
|
|
@@ -42,7 +44,15 @@ export const TIER_DEFINITIONS = {
|
|
|
42
44
|
/** Server-side allowlist for self-serve tier selection — the only authority; `features` copy gates nothing. */
|
|
43
45
|
export const SELF_SERVE_TIERS = ['BASE', 'PRO'];
|
|
44
46
|
/**
|
|
45
|
-
*
|
|
47
|
+
* Scan to Pay depends on seller automated release, which is available to Pro and Concierge merchants.
|
|
48
|
+
* Sandbox stays available so merchants can complete the no-value onboarding demo
|
|
49
|
+
* before choosing a live plan.
|
|
50
|
+
*/
|
|
51
|
+
export function canUseScanToPay(input) {
|
|
52
|
+
return input.environment === 'SANDBOX' || input.tier === 'PRO' || input.tier === 'CONCIERGE';
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Formats a tier's monthly caps for display; caps count fiat-paid orders only. `volumeUsdc` is a whole-USDC decimal string;
|
|
46
56
|
* exact thousands render as `$10K`, anything else as `$2,500`.
|
|
47
57
|
*/
|
|
48
58
|
export function formatTierMonthlyLimitsCopy(limits) {
|
|
@@ -53,5 +63,5 @@ export function formatTierMonthlyLimitsCopy(limits) {
|
|
|
53
63
|
const volume = whole.length > 3 && /^\d+000$/.test(whole)
|
|
54
64
|
? `$${whole.slice(0, -3)}K`
|
|
55
65
|
: `$${whole.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}`;
|
|
56
|
-
return `Up to ${volume} volume and ${limits.orderCount} orders per month`;
|
|
66
|
+
return `Up to ${volume} fiat volume and ${limits.orderCount} fiat orders per month`;
|
|
57
67
|
}
|