@provex/utils 1.0.16 → 1.2.3
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/src/chain.d.ts +436 -4
- package/dist/src/chain.js +80 -0
- package/dist/src/chain.test.d.ts +1 -0
- package/dist/src/chain.test.js +112 -0
- package/dist/src/contracts.d.ts +196 -20
- package/dist/src/contracts.js +245 -17
- package/dist/src/contracts.test.d.ts +1 -0
- package/dist/src/contracts.test.js +243 -0
- package/dist/src/conversionRates.d.ts +99 -8
- package/dist/src/conversionRates.js +74 -4
- package/dist/src/conversionRates.test.d.ts +1 -0
- package/dist/src/conversionRates.test.js +473 -0
- package/dist/src/currencies.d.ts +113 -9
- package/dist/src/currencies.js +119 -38
- package/dist/src/currencies.test.d.ts +1 -0
- package/dist/src/currencies.test.js +343 -0
- package/dist/src/data/countries.json +166 -166
- package/dist/src/deposit.d.ts +69 -1
- package/dist/src/deposit.js +52 -1
- package/dist/src/depositKeys.d.ts +154 -0
- package/dist/src/depositKeys.js +104 -0
- package/dist/src/depositKeys.test.d.ts +1 -0
- package/dist/src/depositKeys.test.js +231 -0
- package/dist/src/endpoints.d.ts +51 -0
- package/dist/src/endpoints.js +70 -0
- package/dist/src/endpoints.test.d.ts +1 -0
- package/dist/src/endpoints.test.js +54 -0
- package/dist/src/events.d.ts +40 -2
- package/dist/src/events.js +86 -10
- package/dist/src/events.test.d.ts +1 -0
- package/dist/src/events.test.js +111 -0
- package/dist/src/fees.d.ts +136 -0
- package/dist/src/fees.js +178 -0
- package/dist/src/fees.test.d.ts +1 -0
- package/dist/src/fees.test.js +165 -0
- package/dist/src/ids.d.ts +125 -22
- package/dist/src/ids.js +211 -61
- package/dist/src/ids.test.d.ts +1 -0
- package/dist/src/ids.test.js +607 -0
- package/dist/src/index.d.ts +30 -1
- package/dist/src/index.js +30 -1
- package/dist/src/input.d.ts +23 -4
- package/dist/src/input.js +23 -4
- package/dist/src/intent.d.ts +38 -2
- package/dist/src/intent.js +28 -1
- package/dist/src/intent.test.d.ts +1 -0
- package/dist/src/intent.test.js +119 -0
- package/dist/src/json.d.ts +38 -1
- package/dist/src/json.js +38 -2
- package/dist/src/normalization.d.ts +224 -0
- package/dist/src/normalization.js +119 -0
- package/dist/src/normalization.test.d.ts +1 -0
- package/dist/src/normalization.test.js +284 -0
- package/dist/src/participants.d.ts +19 -4
- package/dist/src/participants.js +19 -4
- package/dist/src/payment.d.ts +333 -16
- package/dist/src/payment.js +768 -58
- package/dist/src/payment.test.d.ts +1 -0
- package/dist/src/payment.test.js +272 -0
- package/dist/src/peer-types.d.ts +327 -0
- package/dist/src/peer-types.js +169 -0
- package/dist/src/profit.d.ts +26 -5
- package/dist/src/profit.js +31 -8
- package/dist/src/profit.test.d.ts +1 -0
- package/dist/src/profit.test.js +315 -0
- package/dist/src/reputation.d.ts +125 -0
- package/dist/src/reputation.js +188 -0
- package/dist/src/reputation.test.d.ts +1 -0
- package/dist/src/reputation.test.js +156 -0
- package/dist/src/sort.d.ts +49 -10
- package/dist/src/sort.js +40 -9
- package/dist/src/sort.test.d.ts +1 -0
- package/dist/src/sort.test.js +216 -0
- package/dist/src/stateKey.d.ts +35 -0
- package/dist/src/stateKey.js +36 -0
- package/dist/src/stats.d.ts +55 -1
- package/dist/src/stats.js +46 -1
- package/dist/src/stats.test.d.ts +1 -0
- package/dist/src/stats.test.js +104 -0
- package/dist/src/time.d.ts +59 -9
- package/dist/src/time.js +71 -15
- package/dist/src/time.test.d.ts +1 -0
- package/dist/src/time.test.js +231 -0
- package/dist/src/tokens.d.ts +11972 -145
- package/dist/src/tokens.js +98 -17
- package/dist/src/tokens.test.d.ts +1 -0
- package/dist/src/tokens.test.js +193 -0
- package/dist/src/units.d.ts +183 -0
- package/dist/src/units.js +206 -6
- package/dist/src/units.test.d.ts +1 -0
- package/dist/src/units.test.js +327 -0
- package/dist/src/zkp2p-types.d.ts +273 -4
- package/dist/src/zkp2p-types.js +169 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +116 -26
- package/scripts/convert-svg.ts +0 -22
- package/src/chain.ts +0 -27
- package/src/contracts.ts +0 -89
- package/src/conversionRates.ts +0 -356
- package/src/currencies.ts +0 -286
- package/src/data/countries.json +0 -1099
- package/src/deposit.ts +0 -2
- package/src/events.ts +0 -21
- package/src/flags/eur.svg +0 -4
- package/src/flags/usd.svg +0 -25
- package/src/flags.ts +0 -4
- package/src/global.d.ts +0 -9
- package/src/ids.ts +0 -137
- package/src/index.ts +0 -16
- package/src/input.ts +0 -35
- package/src/intent.ts +0 -15
- package/src/json.ts +0 -42
- package/src/participants.ts +0 -14
- package/src/payment.ts +0 -573
- package/src/profit.ts +0 -55
- package/src/sort.ts +0 -49
- package/src/stats.ts +0 -10
- package/src/time.ts +0 -123
- package/src/tokens.ts +0 -159
- package/src/units.ts +0 -120
- package/src/zkp2p-types.ts +0 -55
- package/tsconfig.json +0 -18
package/dist/src/payment.js
CHANGED
|
@@ -1,8 +1,113 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Payment provider definitions and utilities for Provex protocol.
|
|
3
|
+
*
|
|
4
|
+
* This module is the single source of truth for all supported payment methods,
|
|
5
|
+
* including their contract IDs, icons, risk levels, and tier requirements.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* **Supported Payment Providers:**
|
|
9
|
+
* - US: Venmo, Zelle (Chase/BoFA/Citi), CashApp, PayPal, Chime
|
|
10
|
+
* - International: Revolut, Wise, Monzo, N26, Alipay, MercadoPago, RBC
|
|
11
|
+
*
|
|
12
|
+
* **Provider Identification:**
|
|
13
|
+
* - V2: Per-provider verifier contract addresses
|
|
14
|
+
* - V3: keccak256(providerKey) as bytes32 payment method ID
|
|
15
|
+
*
|
|
16
|
+
* **Risk Levels (Base chain only):**
|
|
17
|
+
* - Low risk (Revolut, Wise, Monzo, MercadoPago): 5x cap multiplier, no cooldown
|
|
18
|
+
* - Medium risk (Zelle): 1.5x cap multiplier, cooldown applies
|
|
19
|
+
* - High risk (Venmo, CashApp): 1x cap multiplier, cooldown applies
|
|
20
|
+
* - Highest risk (PayPal): 0.75x cap multiplier, requires Peer Plus tier
|
|
21
|
+
*
|
|
22
|
+
* @see {@link reputation} for tier system
|
|
23
|
+
* @see {@link currencies} for supported currencies per provider
|
|
24
|
+
*/
|
|
25
|
+
import { getAddress, parseUnits, zeroAddress, keccak256, stringToHex, isAddress } from "viem";
|
|
26
|
+
/**
|
|
27
|
+
* Read an env var from Vite (browser) or Node, returning empty string if not set.
|
|
28
|
+
*/
|
|
29
|
+
function readEnv(name) {
|
|
30
|
+
const viteVal = typeof import.meta !== 'undefined'
|
|
31
|
+
? import.meta.env?.[`VITE_${name}`]
|
|
32
|
+
: undefined;
|
|
33
|
+
const nodeVal = typeof process !== 'undefined'
|
|
34
|
+
? process.env?.[name] ?? process.env?.[`VITE_${name}`]
|
|
35
|
+
: undefined;
|
|
36
|
+
return viteVal ?? nodeVal ?? '';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Parse a comma-separated list of provider keys from an env var.
|
|
40
|
+
*
|
|
41
|
+
* VITE_DISABLED_PROVIDERS / DISABLED_PROVIDERS — providers to hide (takes precedence).
|
|
42
|
+
* VITE_ENABLED_PROVIDERS / ENABLED_PROVIDERS — providers to force-show (overrides `disabled: true` in config).
|
|
43
|
+
*
|
|
44
|
+
* Examples:
|
|
45
|
+
* VITE_DISABLED_PROVIDERS=paypal,n26 → hides PayPal and N26
|
|
46
|
+
* VITE_ENABLED_PROVIDERS=paypal → shows PayPal even if config has disabled:true
|
|
47
|
+
* (both set: disabled list wins)
|
|
48
|
+
*
|
|
49
|
+
* If neither is set, falls back to the `disabled` field on the config.
|
|
50
|
+
*/
|
|
51
|
+
let _disabledSet = null;
|
|
52
|
+
let _enabledSet = null;
|
|
53
|
+
function parseProviderLists() {
|
|
54
|
+
if (_disabledSet !== null)
|
|
55
|
+
return;
|
|
56
|
+
const disabled = readEnv('DISABLED_PROVIDERS').toLowerCase().split(',').map(s => s.trim()).filter(Boolean);
|
|
57
|
+
const enabled = readEnv('ENABLED_PROVIDERS').toLowerCase().split(',').map(s => s.trim()).filter(Boolean);
|
|
58
|
+
_disabledSet = new Set(disabled);
|
|
59
|
+
_enabledSet = new Set(enabled);
|
|
60
|
+
}
|
|
61
|
+
/** Returns true if a provider should be hidden from user-facing flows. */
|
|
62
|
+
export function isProviderDisabled(key, configDisabled) {
|
|
63
|
+
parseProviderLists();
|
|
64
|
+
const k = key.toLowerCase();
|
|
65
|
+
// Explicit disable list takes priority
|
|
66
|
+
if (_disabledSet.has(k))
|
|
67
|
+
return true;
|
|
68
|
+
// Explicit enable list overrides config
|
|
69
|
+
if (_enabledSet.has(k))
|
|
70
|
+
return false;
|
|
71
|
+
// Fall back to config field
|
|
72
|
+
return configDisabled ?? false;
|
|
73
|
+
}
|
|
2
74
|
import { base, pulsechain } from "viem/chains";
|
|
3
|
-
import {
|
|
75
|
+
import { contracts } from "./contracts.js";
|
|
4
76
|
import { formatUnits } from "./units.js";
|
|
5
77
|
import { SUPPORTED_CURRENCIES } from "./currencies.js";
|
|
78
|
+
/**
|
|
79
|
+
* Generate a contract ID (keccak256 hash) for a provider key.
|
|
80
|
+
* Used to identify payment methods on-chain (e.g., 'venmo' → bytes32).
|
|
81
|
+
*
|
|
82
|
+
* @param key - The provider key (e.g., 'venmo', 'zelle')
|
|
83
|
+
* @returns The contract ID as a hex string
|
|
84
|
+
*/
|
|
85
|
+
export const providerKeyToContractId = (key) => {
|
|
86
|
+
return keccak256(stringToHex(key));
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Compute the payeeDetailsHash for a plaintext payment identifier.
|
|
90
|
+
* This is the on-chain hash stored in deposit verifier records.
|
|
91
|
+
*
|
|
92
|
+
* The depositor passes this hash when creating a deposit. Buyers look it up
|
|
93
|
+
* via an API (or custom storage) to get the plaintext back.
|
|
94
|
+
*
|
|
95
|
+
* Uses `keccak256(utf8bytes(identifier))` — matches the contract and API convention.
|
|
96
|
+
*
|
|
97
|
+
* @param identifier - Plaintext payment ID (e.g., '@myvenmo', 'user@email.com', '+1234567890')
|
|
98
|
+
* @returns The payeeDetailsHash as a hex string
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* import { computePayeeDetailsHash } from '@provex/utils/payment'
|
|
103
|
+
*
|
|
104
|
+
* const hash = computePayeeDetailsHash('@myvenmo')
|
|
105
|
+
* // Use in createDeposit({ paymentMethodData: [{ payeeDetails: hash, ... }] })
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export const computePayeeDetailsHash = (identifier) => {
|
|
109
|
+
return keccak256(stringToHex(identifier));
|
|
110
|
+
};
|
|
6
111
|
/**
|
|
7
112
|
* Payment providers, including manual
|
|
8
113
|
*/
|
|
@@ -16,13 +121,76 @@ export const providers = {
|
|
|
16
121
|
MANUAL: 'manual',
|
|
17
122
|
PAYPAL: 'paypal',
|
|
18
123
|
MONZO: 'monzo',
|
|
124
|
+
N26: 'n26',
|
|
125
|
+
ALIPAY: 'alipay',
|
|
126
|
+
CHIME: 'chime',
|
|
127
|
+
ROYALBANKCANADA: 'royalbankcanada',
|
|
128
|
+
IDFC: 'idfc',
|
|
19
129
|
};
|
|
20
130
|
/** Distinct keys for payment sub-providers (currently only used by Zelle) */
|
|
21
131
|
export const subProviders = {
|
|
132
|
+
CHASE: 'zelle-chase',
|
|
133
|
+
BANK_OF_AMERICA: 'zelle-bofa',
|
|
134
|
+
CITI: 'zelle-citi',
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Extension platform keys - the platform identifiers used by the PeerAuth extension.
|
|
138
|
+
* For Zelle sub-providers, these are the bank names without the 'zelle-' prefix.
|
|
139
|
+
* Must match the folder names in @zkp2p/providers package.
|
|
140
|
+
*/
|
|
141
|
+
export const extensionPlatforms = {
|
|
22
142
|
CHASE: 'chase',
|
|
23
|
-
|
|
143
|
+
BOFA: 'bankofamerica',
|
|
24
144
|
CITI: 'citi',
|
|
25
145
|
};
|
|
146
|
+
/**
|
|
147
|
+
* Universal taker tier names for the reputation system.
|
|
148
|
+
* Use this const instead of string literals wherever a tier is referenced.
|
|
149
|
+
*/
|
|
150
|
+
export const tiers = {
|
|
151
|
+
PEASANT: 'peasant',
|
|
152
|
+
NEUTRAL: 'neutral',
|
|
153
|
+
PLUS: 'plus',
|
|
154
|
+
PRO: 'pro',
|
|
155
|
+
PLATINUM: 'platinum',
|
|
156
|
+
/** Manually assigned VIP tier — cannot be reached via volume alone */
|
|
157
|
+
PRESIDENT: 'president',
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Mapping from universal tier names to peer-specific tier names
|
|
161
|
+
*/
|
|
162
|
+
export const tierToPeerTier = {
|
|
163
|
+
[tiers.PEASANT]: 'peer_peasant',
|
|
164
|
+
[tiers.NEUTRAL]: 'peer',
|
|
165
|
+
[tiers.PLUS]: 'peer_plus',
|
|
166
|
+
[tiers.PRO]: 'peer_pro',
|
|
167
|
+
[tiers.PLATINUM]: 'peer_platinum',
|
|
168
|
+
[tiers.PRESIDENT]: 'peer_president',
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Mapping from peer tier names to universal tier names
|
|
172
|
+
*/
|
|
173
|
+
export const peerTierToTier = {
|
|
174
|
+
peer_peasant: tiers.PEASANT,
|
|
175
|
+
peer: tiers.NEUTRAL,
|
|
176
|
+
peer_plus: tiers.PLUS,
|
|
177
|
+
peer_pro: tiers.PRO,
|
|
178
|
+
peer_platinum: tiers.PLATINUM,
|
|
179
|
+
peer_president: tiers.PRESIDENT,
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Convert a peer tier name to universal tier name
|
|
183
|
+
* @param peerTier - peer tier name (e.g., 'peer_peasant')
|
|
184
|
+
* @returns Universal tier name
|
|
185
|
+
* @throws Error if peerTier is not a valid peer tier
|
|
186
|
+
*/
|
|
187
|
+
export function fromPeerTier(peerTier) {
|
|
188
|
+
const tier = peerTierToTier[peerTier];
|
|
189
|
+
if (!tier) {
|
|
190
|
+
throw new Error(`Invalid peer tier: ${peerTier}`);
|
|
191
|
+
}
|
|
192
|
+
return tier;
|
|
193
|
+
}
|
|
26
194
|
/** Provider key to validation key */
|
|
27
195
|
export const providerKeyToValidationKey = {
|
|
28
196
|
venmo: 'venmoUsername',
|
|
@@ -33,6 +201,11 @@ export const providerKeyToValidationKey = {
|
|
|
33
201
|
mercadopago: 'cvu',
|
|
34
202
|
paypal: 'paypalEmail',
|
|
35
203
|
monzo: 'monzoMeUsername',
|
|
204
|
+
n26: 'n26Email',
|
|
205
|
+
alipay: 'alipayId',
|
|
206
|
+
chime: 'chimesign',
|
|
207
|
+
royalbankcanada: 'interacEmail',
|
|
208
|
+
idfc: 'idfcAccountNumber',
|
|
36
209
|
};
|
|
37
210
|
/** Data encoding for zelle urls */
|
|
38
211
|
export const dataEncoding = (data) => {
|
|
@@ -48,25 +221,28 @@ export const defaultZelleSendLink = (options) => (!options.username ? null
|
|
|
48
221
|
/** Global configuration for all supported sub-providers. Other modules can import this directly. */
|
|
49
222
|
export const subProviderConfigs = {
|
|
50
223
|
zelle: {
|
|
51
|
-
chase: {
|
|
224
|
+
'zelle-chase': {
|
|
52
225
|
paymentMethod: 0,
|
|
53
226
|
key: subProviders.CHASE,
|
|
54
227
|
name: 'Chase',
|
|
55
228
|
icon: 'simple-icons:chase',
|
|
56
|
-
|
|
229
|
+
extensionPlatform: extensionPlatforms.CHASE,
|
|
230
|
+
v2Verifiers: (chain) => contracts.v2[chain].zelleChaseReclaimVerifier,
|
|
57
231
|
sendLink: (opts) => {
|
|
58
232
|
if (opts.qrCode) {
|
|
59
233
|
return defaultZelleSendLink(opts);
|
|
60
234
|
}
|
|
235
|
+
// return 'https://secure.chase.com/web/auth/dashboard#/dashboard/singleDoor/payments/activity;params=qp,sentactivity'
|
|
61
236
|
return 'https://secure.chase.com/web/auth/dashboard#/dashboard/singleDoor/singleDoorController/index';
|
|
62
237
|
},
|
|
63
238
|
},
|
|
64
|
-
|
|
239
|
+
'zelle-bofa': {
|
|
65
240
|
paymentMethod: 1,
|
|
66
241
|
key: subProviders.BANK_OF_AMERICA,
|
|
67
242
|
name: 'Bank of America',
|
|
68
243
|
icon: 'simple-icons:bankofamerica',
|
|
69
|
-
|
|
244
|
+
extensionPlatform: extensionPlatforms.BOFA,
|
|
245
|
+
v2Verifiers: (chain) => contracts.v2[chain].zelleBoAReclaimVerifier,
|
|
70
246
|
sendLink: (opts) => {
|
|
71
247
|
if (opts.qrCode) {
|
|
72
248
|
return `https://www.bankofamerica.com/movemoney`;
|
|
@@ -74,12 +250,13 @@ export const subProviderConfigs = {
|
|
|
74
250
|
return 'https://www.bankofamerica.com/';
|
|
75
251
|
},
|
|
76
252
|
},
|
|
77
|
-
citi: {
|
|
253
|
+
'zelle-citi': {
|
|
78
254
|
paymentMethod: 2,
|
|
79
255
|
key: subProviders.CITI,
|
|
80
256
|
name: 'Citi',
|
|
81
257
|
icon: 'arcticons:citi-mobile',
|
|
82
|
-
|
|
258
|
+
extensionPlatform: extensionPlatforms.CITI,
|
|
259
|
+
v2Verifiers: (chain) => contracts.v2[chain].zelleCitiReclaimVerifier,
|
|
83
260
|
sendLink: (opts) => {
|
|
84
261
|
if (opts.qrCode) {
|
|
85
262
|
return defaultZelleSendLink(opts);
|
|
@@ -91,16 +268,37 @@ export const subProviderConfigs = {
|
|
|
91
268
|
};
|
|
92
269
|
/** Payment method icon mappings */
|
|
93
270
|
export const providerConfigs = (chainId) => {
|
|
94
|
-
const
|
|
271
|
+
const v2Contracts = contracts.v2[chainId];
|
|
272
|
+
const v3Contracts = contracts.v3[chainId];
|
|
273
|
+
/**
|
|
274
|
+
* Get v2 verifier addresses for a payment method.
|
|
275
|
+
* Prioritizes v2-specific verifiers over v3 unified verifier.
|
|
276
|
+
* This ensures v2 historical data is correctly categorized even on chains with both v2 and v3 contracts.
|
|
277
|
+
*/
|
|
278
|
+
const getV2Verifiers = (verifierKey) => {
|
|
279
|
+
// First check if v2 contracts have specific verifiers for this method
|
|
280
|
+
if (v2Contracts && verifierKey in v2Contracts) {
|
|
281
|
+
const value = v2Contracts[verifierKey];
|
|
282
|
+
return (Array.isArray(value) ? value : []);
|
|
283
|
+
}
|
|
284
|
+
// Fall back to v3 unified verifier (for v3-only chains or v3-only payment methods)
|
|
285
|
+
if (v3Contracts && 'unifiedPaymentVerifier' in v3Contracts) {
|
|
286
|
+
return v3Contracts.unifiedPaymentVerifier || [];
|
|
287
|
+
}
|
|
288
|
+
return [];
|
|
289
|
+
};
|
|
95
290
|
return {
|
|
96
291
|
venmo: {
|
|
97
292
|
key: providers.VENMO,
|
|
293
|
+
contractId: providerKeyToContractId(providers.VENMO),
|
|
98
294
|
icon: 'ion:logo-venmo',
|
|
99
295
|
name: 'Venmo',
|
|
100
296
|
usernameType: 'Venmo Username',
|
|
101
297
|
validationKey: providerKeyToValidationKey.venmo,
|
|
102
298
|
color: 'rgb(0, 116, 222)',
|
|
103
|
-
|
|
299
|
+
chartColorLight: '#0074de',
|
|
300
|
+
chartColorDark: '#4da5ff',
|
|
301
|
+
v2Verifiers: getV2Verifiers('venmoReclaimVerifier'),
|
|
104
302
|
limits: {
|
|
105
303
|
min: 1.0,
|
|
106
304
|
},
|
|
@@ -114,22 +312,26 @@ export const providerConfigs = (chainId) => {
|
|
|
114
312
|
list: [
|
|
115
313
|
SUPPORTED_CURRENCIES.USD.contractId,
|
|
116
314
|
],
|
|
315
|
+
// High risk - 1x multiplier, has cooldown
|
|
316
|
+
riskLevel: 'high',
|
|
317
|
+
capMultiplier: 1,
|
|
318
|
+
hasCooldown: true,
|
|
319
|
+
minimumTier: null,
|
|
117
320
|
},
|
|
118
321
|
zelle: {
|
|
119
322
|
key: providers.ZELLE,
|
|
323
|
+
contractId: providerKeyToContractId(providers.ZELLE),
|
|
120
324
|
icon: 'simple-icons:zelle',
|
|
121
325
|
name: 'Zelle',
|
|
122
326
|
color: '#6d1fd4',
|
|
123
327
|
usernameType: 'Zelle Email',
|
|
124
328
|
validationKey: providerKeyToValidationKey.zelle,
|
|
125
|
-
|
|
329
|
+
v2Verifiers: getV2Verifiers('zelleBaseVerifier'),
|
|
126
330
|
limits: {
|
|
127
331
|
min: 1.0,
|
|
128
332
|
},
|
|
129
333
|
subProviders: new Set([
|
|
130
|
-
subProviderConfigs.zelle
|
|
131
|
-
subProviderConfigs.zelle[subProviders.BANK_OF_AMERICA],
|
|
132
|
-
subProviderConfigs.zelle[subProviders.CITI],
|
|
334
|
+
...Object.values(subProviderConfigs.zelle),
|
|
133
335
|
]),
|
|
134
336
|
// Delegate to sub-provider specific link when provided, otherwise fall back to generic QR URL
|
|
135
337
|
sendLink: (options) => {
|
|
@@ -141,15 +343,23 @@ export const providerConfigs = (chainId) => {
|
|
|
141
343
|
list: [
|
|
142
344
|
SUPPORTED_CURRENCIES.USD.contractId,
|
|
143
345
|
],
|
|
346
|
+
// Medium risk - 1.5x multiplier, has cooldown
|
|
347
|
+
riskLevel: 'medium',
|
|
348
|
+
capMultiplier: 1.5,
|
|
349
|
+
hasCooldown: true,
|
|
350
|
+
minimumTier: null,
|
|
144
351
|
},
|
|
145
352
|
cashapp: {
|
|
146
353
|
key: providers.CASHAPP,
|
|
354
|
+
contractId: providerKeyToContractId(providers.CASHAPP),
|
|
147
355
|
icon: 'simple-icons:cashapp',
|
|
148
356
|
name: 'Cash App',
|
|
149
357
|
color: 'rgba(0,224,19,1.0)',
|
|
358
|
+
chartColorLight: '#00e013',
|
|
359
|
+
chartColorDark: '#4dff6a',
|
|
150
360
|
usernameType: 'CashTag',
|
|
151
361
|
validationKey: providerKeyToValidationKey.cashapp,
|
|
152
|
-
|
|
362
|
+
v2Verifiers: getV2Verifiers('cashappReclaimVerifier'),
|
|
153
363
|
limits: {
|
|
154
364
|
min: 1.0,
|
|
155
365
|
},
|
|
@@ -161,15 +371,25 @@ export const providerConfigs = (chainId) => {
|
|
|
161
371
|
const u = options.username.startsWith('$') ? options.username : `$${options.username}`;
|
|
162
372
|
return `https://cash.app/qr/${u}?size=288&margin=0`;
|
|
163
373
|
},
|
|
374
|
+
// High risk - 1x multiplier, has cooldown
|
|
375
|
+
riskLevel: 'high',
|
|
376
|
+
capMultiplier: 1,
|
|
377
|
+
hasCooldown: true,
|
|
378
|
+
minimumTier: null,
|
|
164
379
|
},
|
|
165
380
|
revolut: {
|
|
166
381
|
key: providers.REVOLUT,
|
|
382
|
+
contractId: providerKeyToContractId(providers.REVOLUT),
|
|
167
383
|
icon: 'simple-icons:revolut',
|
|
168
384
|
name: 'Revolut',
|
|
169
385
|
color: '#191c1f',
|
|
386
|
+
// Chart-friendly color to ensure distinction in stacked bar palette
|
|
387
|
+
chartColorLight: '#8b5cf6',
|
|
388
|
+
chartColorDark: '#c4b5fd',
|
|
389
|
+
backgroundColor: '#ffffff',
|
|
170
390
|
usernameType: 'RevTag',
|
|
171
391
|
validationKey: providerKeyToValidationKey.revolut,
|
|
172
|
-
|
|
392
|
+
v2Verifiers: getV2Verifiers('revolutReclaimVerifier'),
|
|
173
393
|
limits: {
|
|
174
394
|
min: 1.0,
|
|
175
395
|
},
|
|
@@ -179,29 +399,45 @@ export const providerConfigs = (chainId) => {
|
|
|
179
399
|
SUPPORTED_CURRENCIES.USD.contractId,
|
|
180
400
|
SUPPORTED_CURRENCIES.EUR.contractId,
|
|
181
401
|
SUPPORTED_CURRENCIES.GBP.contractId,
|
|
402
|
+
SUPPORTED_CURRENCIES.SGD.contractId,
|
|
403
|
+
SUPPORTED_CURRENCIES.NZD.contractId,
|
|
182
404
|
SUPPORTED_CURRENCIES.AUD.contractId,
|
|
183
405
|
SUPPORTED_CURRENCIES.CAD.contractId,
|
|
184
406
|
SUPPORTED_CURRENCIES.HKD.contractId,
|
|
185
407
|
SUPPORTED_CURRENCIES.MXN.contractId,
|
|
186
|
-
SUPPORTED_CURRENCIES.NZD.contractId,
|
|
187
|
-
SUPPORTED_CURRENCIES.PLN.contractId,
|
|
188
408
|
SUPPORTED_CURRENCIES.SAR.contractId,
|
|
189
|
-
SUPPORTED_CURRENCIES.
|
|
190
|
-
SUPPORTED_CURRENCIES.ZAR.contractId,
|
|
191
|
-
SUPPORTED_CURRENCIES.CHF.contractId,
|
|
409
|
+
SUPPORTED_CURRENCIES.AED.contractId,
|
|
192
410
|
SUPPORTED_CURRENCIES.THB.contractId,
|
|
193
411
|
SUPPORTED_CURRENCIES.TRY.contractId,
|
|
194
|
-
SUPPORTED_CURRENCIES.
|
|
412
|
+
SUPPORTED_CURRENCIES.PLN.contractId,
|
|
413
|
+
SUPPORTED_CURRENCIES.CHF.contractId,
|
|
414
|
+
SUPPORTED_CURRENCIES.ZAR.contractId,
|
|
415
|
+
SUPPORTED_CURRENCIES.JPY.contractId,
|
|
416
|
+
SUPPORTED_CURRENCIES.CZK.contractId,
|
|
417
|
+
SUPPORTED_CURRENCIES.CNY.contractId,
|
|
418
|
+
SUPPORTED_CURRENCIES.DKK.contractId,
|
|
419
|
+
SUPPORTED_CURRENCIES.HUF.contractId,
|
|
420
|
+
SUPPORTED_CURRENCIES.NOK.contractId,
|
|
421
|
+
SUPPORTED_CURRENCIES.RON.contractId,
|
|
422
|
+
SUPPORTED_CURRENCIES.SEK.contractId,
|
|
195
423
|
],
|
|
424
|
+
// Low risk - 5x multiplier, no cooldown
|
|
425
|
+
riskLevel: 'low',
|
|
426
|
+
capMultiplier: 5,
|
|
427
|
+
hasCooldown: false,
|
|
428
|
+
minimumTier: null,
|
|
429
|
+
// Revolut sends amounts as integer cents (e.g. 5000 for $50.00)
|
|
430
|
+
amountInCents: true,
|
|
196
431
|
},
|
|
197
432
|
wise: {
|
|
198
433
|
key: providers.WISE,
|
|
434
|
+
contractId: providerKeyToContractId(providers.WISE),
|
|
199
435
|
icon: 'simple-icons:wise',
|
|
200
436
|
name: 'Wise',
|
|
201
437
|
color: '#9fe870',
|
|
202
438
|
usernameType: 'WiseTag',
|
|
203
439
|
validationKey: providerKeyToValidationKey.wise,
|
|
204
|
-
|
|
440
|
+
v2Verifiers: getV2Verifiers('wiseReclaimVerifier'),
|
|
205
441
|
limits: {
|
|
206
442
|
min: 1.0,
|
|
207
443
|
},
|
|
@@ -209,38 +445,54 @@ export const providerConfigs = (chainId) => {
|
|
|
209
445
|
sendLink: (options) => `https://wise.com/pay/me/${options.username}`,
|
|
210
446
|
list: [
|
|
211
447
|
SUPPORTED_CURRENCIES.USD.contractId,
|
|
448
|
+
SUPPORTED_CURRENCIES.CNY.contractId,
|
|
212
449
|
SUPPORTED_CURRENCIES.EUR.contractId,
|
|
213
450
|
SUPPORTED_CURRENCIES.GBP.contractId,
|
|
214
451
|
SUPPORTED_CURRENCIES.AUD.contractId,
|
|
452
|
+
SUPPORTED_CURRENCIES.NZD.contractId,
|
|
215
453
|
SUPPORTED_CURRENCIES.CAD.contractId,
|
|
216
|
-
SUPPORTED_CURRENCIES.
|
|
217
|
-
SUPPORTED_CURRENCIES.
|
|
218
|
-
SUPPORTED_CURRENCIES.
|
|
454
|
+
SUPPORTED_CURRENCIES.AED.contractId,
|
|
455
|
+
SUPPORTED_CURRENCIES.CHF.contractId,
|
|
456
|
+
SUPPORTED_CURRENCIES.ZAR.contractId,
|
|
457
|
+
SUPPORTED_CURRENCIES.SGD.contractId,
|
|
219
458
|
SUPPORTED_CURRENCIES.ILS.contractId,
|
|
459
|
+
SUPPORTED_CURRENCIES.HKD.contractId,
|
|
220
460
|
SUPPORTED_CURRENCIES.JPY.contractId,
|
|
461
|
+
SUPPORTED_CURRENCIES.PLN.contractId,
|
|
462
|
+
SUPPORTED_CURRENCIES.TRY.contractId,
|
|
463
|
+
SUPPORTED_CURRENCIES.IDR.contractId,
|
|
221
464
|
SUPPORTED_CURRENCIES.KES.contractId,
|
|
222
465
|
SUPPORTED_CURRENCIES.MYR.contractId,
|
|
223
466
|
SUPPORTED_CURRENCIES.MXN.contractId,
|
|
224
|
-
SUPPORTED_CURRENCIES.NZD.contractId,
|
|
225
|
-
SUPPORTED_CURRENCIES.PLN.contractId,
|
|
226
|
-
SUPPORTED_CURRENCIES.SGD.contractId,
|
|
227
|
-
SUPPORTED_CURRENCIES.ZAR.contractId,
|
|
228
|
-
SUPPORTED_CURRENCIES.CHF.contractId,
|
|
229
467
|
SUPPORTED_CURRENCIES.THB.contractId,
|
|
230
|
-
SUPPORTED_CURRENCIES.TRY.contractId,
|
|
231
|
-
SUPPORTED_CURRENCIES.UGX.contractId,
|
|
232
|
-
SUPPORTED_CURRENCIES.AED.contractId,
|
|
233
468
|
SUPPORTED_CURRENCIES.VND.contractId,
|
|
469
|
+
SUPPORTED_CURRENCIES.UGX.contractId,
|
|
470
|
+
SUPPORTED_CURRENCIES.CZK.contractId,
|
|
471
|
+
SUPPORTED_CURRENCIES.DKK.contractId,
|
|
472
|
+
SUPPORTED_CURRENCIES.HUF.contractId,
|
|
473
|
+
SUPPORTED_CURRENCIES.INR.contractId,
|
|
474
|
+
SUPPORTED_CURRENCIES.NOK.contractId,
|
|
475
|
+
SUPPORTED_CURRENCIES.PHP.contractId,
|
|
476
|
+
SUPPORTED_CURRENCIES.RON.contractId,
|
|
477
|
+
SUPPORTED_CURRENCIES.SEK.contractId,
|
|
234
478
|
],
|
|
479
|
+
// Low risk - 5x multiplier, no cooldown
|
|
480
|
+
riskLevel: 'low',
|
|
481
|
+
capMultiplier: 5,
|
|
482
|
+
hasCooldown: false,
|
|
483
|
+
minimumTier: null,
|
|
484
|
+
depositRequiresApproval: true,
|
|
485
|
+
approvalFormUrl: 'https://forms.gle/9N36Wd4iKS8PwLyFA',
|
|
235
486
|
},
|
|
236
487
|
mercadopago: {
|
|
237
488
|
key: providers.MERCADOPAGO,
|
|
489
|
+
contractId: providerKeyToContractId(providers.MERCADOPAGO),
|
|
238
490
|
icon: 'simple-icons:mercadopago',
|
|
239
491
|
name: 'Mercado Pago',
|
|
240
492
|
usernameType: 'Mercado Pago / Bank CVU',
|
|
241
493
|
color: '#ffe600',
|
|
242
494
|
validationKey: providerKeyToValidationKey.mercadopago,
|
|
243
|
-
|
|
495
|
+
v2Verifiers: getV2Verifiers('mercadopagoReclaimVerifier'),
|
|
244
496
|
limits: {
|
|
245
497
|
min: 1.0,
|
|
246
498
|
},
|
|
@@ -249,19 +501,26 @@ export const providerConfigs = (chainId) => {
|
|
|
249
501
|
list: [
|
|
250
502
|
SUPPORTED_CURRENCIES.ARS.contractId,
|
|
251
503
|
],
|
|
504
|
+
// Low risk - instant settlement, no chargebacks (per peer.xyz docs)
|
|
505
|
+
riskLevel: 'low',
|
|
506
|
+
capMultiplier: 5,
|
|
507
|
+
hasCooldown: false,
|
|
508
|
+
minimumTier: null,
|
|
252
509
|
},
|
|
253
510
|
paypal: {
|
|
254
511
|
key: providers.PAYPAL,
|
|
512
|
+
contractId: providerKeyToContractId(providers.PAYPAL),
|
|
255
513
|
icon: 'simple-icons:paypal',
|
|
256
514
|
name: 'PayPal',
|
|
257
515
|
usernameType: 'PayPal Email',
|
|
258
516
|
validationKey: providerKeyToValidationKey.paypal,
|
|
259
|
-
|
|
517
|
+
v2Verifiers: getV2Verifiers('paypalReclaimVerifier'),
|
|
260
518
|
limits: {
|
|
261
519
|
min: 1.0,
|
|
262
520
|
},
|
|
263
521
|
subProviders: new Set(),
|
|
264
522
|
color: '#0070BA',
|
|
523
|
+
chartColor: '#f59e0b',
|
|
265
524
|
sendLink: (options) => {
|
|
266
525
|
if (options.qrCode) {
|
|
267
526
|
return `paypal://`;
|
|
@@ -277,14 +536,20 @@ export const providerConfigs = (chainId) => {
|
|
|
277
536
|
SUPPORTED_CURRENCIES.CAD.contractId,
|
|
278
537
|
SUPPORTED_CURRENCIES.SGD.contractId,
|
|
279
538
|
],
|
|
539
|
+
riskLevel: 'highest',
|
|
540
|
+
capMultiplier: 0.75,
|
|
541
|
+
hasCooldown: true,
|
|
542
|
+
minimumTier: tiers.PLUS,
|
|
543
|
+
disabled: true,
|
|
280
544
|
},
|
|
281
545
|
monzo: {
|
|
282
546
|
key: providers.MONZO,
|
|
547
|
+
contractId: providerKeyToContractId(providers.MONZO),
|
|
283
548
|
icon: 'simple-icons:monzo',
|
|
284
549
|
name: 'Monzo',
|
|
285
550
|
usernameType: 'Monzo Me Username',
|
|
286
551
|
validationKey: providerKeyToValidationKey.monzo,
|
|
287
|
-
|
|
552
|
+
v2Verifiers: getV2Verifiers('monzoReclaimVerifier'),
|
|
288
553
|
limits: {
|
|
289
554
|
min: 1.0,
|
|
290
555
|
},
|
|
@@ -294,35 +559,281 @@ export const providerConfigs = (chainId) => {
|
|
|
294
559
|
SUPPORTED_CURRENCIES.GBP.contractId,
|
|
295
560
|
],
|
|
296
561
|
color: '#FC427B',
|
|
562
|
+
// Low risk - instant settlement, no chargebacks (per peer.xyz docs)
|
|
563
|
+
riskLevel: 'low',
|
|
564
|
+
capMultiplier: 5,
|
|
565
|
+
hasCooldown: false,
|
|
566
|
+
minimumTier: null,
|
|
567
|
+
},
|
|
568
|
+
n26: {
|
|
569
|
+
key: providers.N26,
|
|
570
|
+
contractId: providerKeyToContractId(providers.N26),
|
|
571
|
+
icon: 'simple-icons:n26',
|
|
572
|
+
name: 'N26',
|
|
573
|
+
usernameType: 'N26 Email',
|
|
574
|
+
validationKey: providerKeyToValidationKey.n26,
|
|
575
|
+
v2Verifiers: [],
|
|
576
|
+
limits: {
|
|
577
|
+
min: 1.0,
|
|
578
|
+
},
|
|
579
|
+
subProviders: new Set(),
|
|
580
|
+
sendLink: (options) => {
|
|
581
|
+
if (options.qrCode) {
|
|
582
|
+
return 'number26://';
|
|
583
|
+
}
|
|
584
|
+
return 'https://app.n26.com/';
|
|
585
|
+
},
|
|
586
|
+
list: [
|
|
587
|
+
SUPPORTED_CURRENCIES.EUR.contractId,
|
|
588
|
+
],
|
|
589
|
+
color: '#088177',
|
|
590
|
+
riskLevel: 'medium',
|
|
591
|
+
capMultiplier: 1,
|
|
592
|
+
hasCooldown: true,
|
|
593
|
+
minimumTier: null,
|
|
594
|
+
disabled: true,
|
|
595
|
+
},
|
|
596
|
+
alipay: {
|
|
597
|
+
key: providers.ALIPAY,
|
|
598
|
+
contractId: providerKeyToContractId(providers.ALIPAY),
|
|
599
|
+
icon: 'simple-icons:alipay',
|
|
600
|
+
name: 'Alipay',
|
|
601
|
+
usernameType: 'Alipay ID',
|
|
602
|
+
validationKey: providerKeyToValidationKey.alipay,
|
|
603
|
+
v2Verifiers: [],
|
|
604
|
+
limits: {
|
|
605
|
+
min: 1.0,
|
|
606
|
+
},
|
|
607
|
+
subProviders: new Set(),
|
|
608
|
+
sendLink: (options) => {
|
|
609
|
+
if (options.qrCode) {
|
|
610
|
+
return 'alipays://';
|
|
611
|
+
}
|
|
612
|
+
return 'https://www.alipay.com/';
|
|
613
|
+
},
|
|
614
|
+
list: [
|
|
615
|
+
SUPPORTED_CURRENCIES.CNY.contractId,
|
|
616
|
+
],
|
|
617
|
+
color: '#1677FF',
|
|
618
|
+
riskLevel: 'medium',
|
|
619
|
+
capMultiplier: 1,
|
|
620
|
+
hasCooldown: true,
|
|
621
|
+
minimumTier: null,
|
|
622
|
+
depositRequiresApproval: true,
|
|
623
|
+
approvalFormUrl: 'https://forms.gle/9N36Wd4iKS8PwLyFA?hl=zh-CN',
|
|
624
|
+
disabled: true,
|
|
625
|
+
},
|
|
626
|
+
chime: {
|
|
627
|
+
key: providers.CHIME,
|
|
628
|
+
contractId: providerKeyToContractId(providers.CHIME),
|
|
629
|
+
icon: 'arcticons:chime',
|
|
630
|
+
name: 'Chime',
|
|
631
|
+
usernameType: '$ChimeSign',
|
|
632
|
+
validationKey: providerKeyToValidationKey.chime,
|
|
633
|
+
v2Verifiers: [],
|
|
634
|
+
limits: {
|
|
635
|
+
min: 0.1,
|
|
636
|
+
},
|
|
637
|
+
subProviders: new Set(),
|
|
638
|
+
sendLink: (options) => {
|
|
639
|
+
if (options.qrCode) {
|
|
640
|
+
return `https://app.chime.com/link/qr?u=${options.username}`;
|
|
641
|
+
}
|
|
642
|
+
return 'https://app.chime.com/login';
|
|
643
|
+
},
|
|
644
|
+
list: [
|
|
645
|
+
SUPPORTED_CURRENCIES.USD.contractId,
|
|
646
|
+
],
|
|
647
|
+
color: '#1EC677',
|
|
648
|
+
riskLevel: 'medium',
|
|
649
|
+
capMultiplier: 1,
|
|
650
|
+
hasCooldown: true,
|
|
651
|
+
minimumTier: null,
|
|
652
|
+
disabled: true,
|
|
653
|
+
},
|
|
654
|
+
royalbankcanada: {
|
|
655
|
+
key: providers.ROYALBANKCANADA,
|
|
656
|
+
contractId: providerKeyToContractId(providers.ROYALBANKCANADA),
|
|
657
|
+
icon: 'arcticons:rbcmobile',
|
|
658
|
+
name: 'Royal Bank of Canada',
|
|
659
|
+
usernameType: 'Interac Email',
|
|
660
|
+
validationKey: providerKeyToValidationKey.royalbankcanada,
|
|
661
|
+
v2Verifiers: [],
|
|
662
|
+
limits: {
|
|
663
|
+
min: 1.0,
|
|
664
|
+
},
|
|
665
|
+
subProviders: new Set(),
|
|
666
|
+
sendLink: () => 'https://www.rbcroyalbank.com/ways-to-bank/interac-e-transfer.html',
|
|
667
|
+
list: [
|
|
668
|
+
SUPPORTED_CURRENCIES.CAD.contractId,
|
|
669
|
+
],
|
|
670
|
+
color: '#4A5568',
|
|
671
|
+
riskLevel: 'medium',
|
|
672
|
+
capMultiplier: 1,
|
|
673
|
+
hasCooldown: true,
|
|
674
|
+
minimumTier: null,
|
|
675
|
+
disabled: true,
|
|
676
|
+
},
|
|
677
|
+
idfc: {
|
|
678
|
+
key: providers.IDFC,
|
|
679
|
+
contractId: providerKeyToContractId(providers.IDFC),
|
|
680
|
+
icon: 'mdi:bank',
|
|
681
|
+
name: 'IDFC Bank',
|
|
682
|
+
usernameType: 'IDFC Account Number',
|
|
683
|
+
validationKey: providerKeyToValidationKey.idfc,
|
|
684
|
+
v2Verifiers: [],
|
|
685
|
+
limits: {
|
|
686
|
+
min: 1.0,
|
|
687
|
+
},
|
|
688
|
+
subProviders: new Set(),
|
|
689
|
+
sendLink: () => 'https://www.idfcfirstbank.com/',
|
|
690
|
+
list: [
|
|
691
|
+
SUPPORTED_CURRENCIES.INR.contractId,
|
|
692
|
+
],
|
|
693
|
+
color: '#2D3748',
|
|
694
|
+
riskLevel: 'medium',
|
|
695
|
+
capMultiplier: 1,
|
|
696
|
+
hasCooldown: true,
|
|
697
|
+
minimumTier: null,
|
|
698
|
+
disabled: true,
|
|
297
699
|
},
|
|
298
700
|
manual: {
|
|
299
701
|
key: providers.MANUAL,
|
|
702
|
+
contractId: providerKeyToContractId(providers.MANUAL),
|
|
300
703
|
icon: 'mdi:help-circle',
|
|
301
|
-
name: 'Manual
|
|
704
|
+
name: 'Manual',
|
|
302
705
|
color: 'gray',
|
|
303
706
|
usernameType: '',
|
|
304
707
|
validationKey: null,
|
|
305
|
-
|
|
708
|
+
v2Verifiers: [zeroAddress],
|
|
306
709
|
limits: {
|
|
307
710
|
min: 0.0,
|
|
308
711
|
},
|
|
309
712
|
subProviders: new Set(),
|
|
310
713
|
list: [],
|
|
714
|
+
// Manual verification - no reputation restrictions
|
|
715
|
+
riskLevel: 'low',
|
|
716
|
+
capMultiplier: 5,
|
|
717
|
+
hasCooldown: false,
|
|
718
|
+
minimumTier: null,
|
|
311
719
|
},
|
|
312
720
|
};
|
|
313
721
|
};
|
|
314
|
-
/**
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
722
|
+
/**
|
|
723
|
+
* Default platform risk configuration for providers not explicitly configured
|
|
724
|
+
* Assumes medium risk as a safe default
|
|
725
|
+
*/
|
|
726
|
+
export const DEFAULT_PLATFORM_RISK = {
|
|
727
|
+
riskLevel: 'medium',
|
|
728
|
+
capMultiplier: 1,
|
|
729
|
+
hasCooldown: true,
|
|
730
|
+
minimumTier: null,
|
|
731
|
+
};
|
|
732
|
+
/**
|
|
733
|
+
* Get the risk configuration for a payment platform
|
|
734
|
+
* @param chainId - The chain ID
|
|
735
|
+
* @param providerKey - The provider key
|
|
736
|
+
* @returns Platform risk configuration
|
|
737
|
+
*/
|
|
738
|
+
export function getPlatformRisk(chainId, providerKey) {
|
|
739
|
+
const config = providerConfigs(chainId)[providerKey];
|
|
740
|
+
return {
|
|
741
|
+
riskLevel: config?.riskLevel ?? DEFAULT_PLATFORM_RISK.riskLevel,
|
|
742
|
+
capMultiplier: config?.capMultiplier ?? DEFAULT_PLATFORM_RISK.capMultiplier,
|
|
743
|
+
hasCooldown: config?.hasCooldown ?? DEFAULT_PLATFORM_RISK.hasCooldown,
|
|
744
|
+
minimumTier: config?.minimumTier ?? DEFAULT_PLATFORM_RISK.minimumTier,
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Payment verifier to key map
|
|
749
|
+
* Includes both main providers and flattened sub-providers
|
|
750
|
+
*/
|
|
751
|
+
export const paymentVerifierToKey = (chainId) => {
|
|
752
|
+
const chainIds = chainId ? [chainId] : Object.keys(contracts.v2).map(Number);
|
|
753
|
+
const entries = chainIds.flatMap(cId => Object.values(providerConfigs(cId)).flatMap(config => [
|
|
754
|
+
// Main provider: V2 verifier addresses -> key
|
|
755
|
+
...config.v2Verifiers.map(verifier => [getAddress(verifier), config.key]),
|
|
756
|
+
// Main provider: contract ID -> key
|
|
757
|
+
[config.contractId.toLowerCase(), config.key],
|
|
758
|
+
// Sub-providers
|
|
759
|
+
...Array.from(config.subProviders).flatMap(subProvider => [
|
|
760
|
+
...subProvider.v2Verifiers(cId).map(verifier => [getAddress(verifier), subProvider.key]),
|
|
761
|
+
[providerKeyToContractId(subProvider.key).toLowerCase(), subProvider.key]
|
|
762
|
+
])
|
|
763
|
+
]));
|
|
764
|
+
return new Map(entries);
|
|
765
|
+
};
|
|
766
|
+
/**
|
|
767
|
+
* Provider contractId to config map (reverse lookup by keccak256 hash)
|
|
768
|
+
* Includes both main providers and flattened sub-providers with their own contract IDs
|
|
769
|
+
* Note: Keys are stored as lowercase for case-insensitive lookup
|
|
770
|
+
*/
|
|
771
|
+
export const providerByContractId = (chainId) => {
|
|
772
|
+
const configs = Object.values(providerConfigs(chainId));
|
|
773
|
+
const entries = [
|
|
774
|
+
// Main providers
|
|
775
|
+
...configs.map(config => [config.contractId.toLowerCase(), config]),
|
|
776
|
+
// Sub-providers with synthetic configs
|
|
777
|
+
...configs.flatMap(config => Array.from(config.subProviders).map(subProvider => {
|
|
778
|
+
const contractId = providerKeyToContractId(subProvider.key).toLowerCase();
|
|
779
|
+
const subConfig = {
|
|
780
|
+
...config,
|
|
781
|
+
key: subProvider.key,
|
|
782
|
+
contractId: providerKeyToContractId(subProvider.key),
|
|
783
|
+
name: subProvider.name,
|
|
784
|
+
icon: subProvider.icon || config.icon,
|
|
785
|
+
color: subProvider.color || config.color,
|
|
786
|
+
usernameType: subProvider.usernameType || config.usernameType,
|
|
787
|
+
v2Verifiers: subProvider.v2Verifiers(chainId),
|
|
788
|
+
subProviders: new Set(),
|
|
789
|
+
};
|
|
790
|
+
return [contractId, subConfig];
|
|
791
|
+
}))
|
|
792
|
+
];
|
|
793
|
+
return new Map(entries);
|
|
794
|
+
};
|
|
795
|
+
/**
|
|
796
|
+
* Get provider config by contractId (keccak256 hash)
|
|
797
|
+
* Supports both main providers and sub-providers (e.g., zelle-chase, zelle-bofa, zelle-citi)
|
|
798
|
+
* @param chainId - The chain ID
|
|
799
|
+
* @param contractId - The contract ID (keccak256 hash) to lookup
|
|
800
|
+
* @returns PaymentConfig or null if not found
|
|
801
|
+
*/
|
|
802
|
+
export const getProviderByContractId = (chainId, contractId) => {
|
|
803
|
+
const normalizedId = contractId.toLowerCase();
|
|
804
|
+
return providerByContractId(chainId).get(normalizedId) ?? null;
|
|
805
|
+
};
|
|
806
|
+
/**
|
|
807
|
+
* Get provider name by contractId (keccak256 hash)
|
|
808
|
+
* Supports both main providers and sub-providers
|
|
809
|
+
* @param chainId - The chain ID
|
|
810
|
+
* @param contractId - The contract ID (keccak256 hash) to lookup
|
|
811
|
+
* @returns Provider name or the contract ID if not found
|
|
812
|
+
*/
|
|
813
|
+
export const getProviderNameByContractId = (chainId, contractId) => {
|
|
814
|
+
return getProviderByContractId(chainId, contractId)?.name ?? contractId;
|
|
815
|
+
};
|
|
816
|
+
/** Provider key to V2 verifiers map (legacy, for backward compatibility) */
|
|
817
|
+
export const providerKeyToVerifiersMap = (chainId) => (new Map(Object.entries(providerConfigs(chainId)).map(([key, config]) => [key, config.v2Verifiers])));
|
|
320
818
|
/** Provider key to verifiers */
|
|
321
819
|
export const providerKeyToVerifiers = (chainId, providerKey) => {
|
|
322
820
|
return providerKeyToVerifiersMap(chainId).get(providerKey) ?? null;
|
|
323
821
|
};
|
|
324
822
|
/** Verifier gets key */
|
|
325
823
|
export const verifierGetsKey = (chainId, verifierAddress) => {
|
|
824
|
+
// If this is a 32-byte hash (66 chars including 0x), look it up directly in the map
|
|
825
|
+
if (verifierAddress?.length === 66) {
|
|
826
|
+
const key = paymentVerifierToKey(chainId).get(verifierAddress.toLowerCase());
|
|
827
|
+
if (key)
|
|
828
|
+
return key;
|
|
829
|
+
// Fallback: try looking it up via contractId
|
|
830
|
+
const contractProvider = getProviderByContractId(chainId ?? base.id, verifierAddress);
|
|
831
|
+
if (contractProvider) {
|
|
832
|
+
return contractProvider.key;
|
|
833
|
+
}
|
|
834
|
+
return providers.MANUAL;
|
|
835
|
+
}
|
|
836
|
+
// Otherwise treat it as an address
|
|
326
837
|
try {
|
|
327
838
|
return paymentVerifierToKey(chainId).get(getAddress(verifierAddress)) ?? providers.MANUAL;
|
|
328
839
|
}
|
|
@@ -332,12 +843,21 @@ export const verifierGetsKey = (chainId, verifierAddress) => {
|
|
|
332
843
|
};
|
|
333
844
|
/**
|
|
334
845
|
* Utility function to get payment method icon
|
|
335
|
-
* @param key - The provider key
|
|
846
|
+
* @param key - The provider key (main provider or sub-provider like 'zelle-chase')
|
|
336
847
|
* @returns The icon string used for iconify
|
|
337
848
|
*/
|
|
338
849
|
export const getPaymentIcon = (chainId, key) => {
|
|
339
850
|
const config = providerConfigs(chainId ?? pulsechain.id);
|
|
340
|
-
|
|
851
|
+
// Check main providers first
|
|
852
|
+
if (config[key]?.icon) {
|
|
853
|
+
return config[key].icon;
|
|
854
|
+
}
|
|
855
|
+
// Check sub-providers directly (e.g., 'zelle-chase', 'zelle-bofa', 'zelle-citi')
|
|
856
|
+
const zelleSubConfig = subProviderConfigs.zelle?.[key];
|
|
857
|
+
if (zelleSubConfig?.icon) {
|
|
858
|
+
return zelleSubConfig.icon;
|
|
859
|
+
}
|
|
860
|
+
return config[providers.MANUAL].icon;
|
|
341
861
|
};
|
|
342
862
|
/**
|
|
343
863
|
* Utility function to get payment method configuration by verifier address
|
|
@@ -345,7 +865,16 @@ export const getPaymentIcon = (chainId, key) => {
|
|
|
345
865
|
* @returns The payment method configuration
|
|
346
866
|
*/
|
|
347
867
|
export const getPaymentMethodConfig = (chainId, verifierAddress) => {
|
|
348
|
-
|
|
868
|
+
// When verifierAddress is a payment-method hash (bytes32), compare via contractId
|
|
869
|
+
if (!isAddress(verifierAddress)) {
|
|
870
|
+
if (verifierAddress.length === 66) {
|
|
871
|
+
return getProviderByContractId(chainId ?? base.id, verifierAddress);
|
|
872
|
+
}
|
|
873
|
+
return null;
|
|
874
|
+
}
|
|
875
|
+
const normalized = getAddress(verifierAddress);
|
|
876
|
+
const chainIdsToCheck = chainId ? [chainId] : [...Object.keys(contracts.v2).map((id) => Number(id))];
|
|
877
|
+
return chainIdsToCheck.reduce((result, chain) => (result ?? Object.values(providerConfigs(chain)).reduce((r, config) => (r ?? (config.v2Verifiers.some((addr) => getAddress(addr) === normalized) ? config : null)), result)), null);
|
|
349
878
|
};
|
|
350
879
|
/**
|
|
351
880
|
* Utility function to get payment method minimum limit by verifier address
|
|
@@ -357,7 +886,8 @@ export const getPaymentMethodMinimum = (chainId, key) => {
|
|
|
357
886
|
return config?.limits?.min ?? 0;
|
|
358
887
|
};
|
|
359
888
|
/**
|
|
360
|
-
* Utility function to get payment method name by verifier address
|
|
889
|
+
* Utility function to get payment method name by verifier address or provider key
|
|
890
|
+
* Handles both main providers and sub-providers (e.g., 'zelle-chase')
|
|
361
891
|
*/
|
|
362
892
|
export const getPaymentMethodName = (chainId, verifierAddress) => {
|
|
363
893
|
const providerKey = verifierAddress;
|
|
@@ -365,7 +895,23 @@ export const getPaymentMethodName = (chainId, verifierAddress) => {
|
|
|
365
895
|
if (providerConfig) {
|
|
366
896
|
return providerConfig.name;
|
|
367
897
|
}
|
|
368
|
-
|
|
898
|
+
// Check sub-providers directly (e.g., 'zelle-chase', 'zelle-bofa', 'zelle-citi')
|
|
899
|
+
// Sub-providers are nested under their parent provider key (e.g., subProviderConfigs.zelle['zelle-chase'])
|
|
900
|
+
const zelleSubConfig = subProviderConfigs.zelle?.[providerKey];
|
|
901
|
+
if (zelleSubConfig?.name) {
|
|
902
|
+
return zelleSubConfig.name;
|
|
903
|
+
}
|
|
904
|
+
if (typeof verifierAddress === 'string' && verifierAddress.length === 66) {
|
|
905
|
+
const contractProvider = getProviderByContractId(chainId ?? base.id, verifierAddress);
|
|
906
|
+
if (contractProvider) {
|
|
907
|
+
return contractProvider.name;
|
|
908
|
+
}
|
|
909
|
+
return 'Unknown';
|
|
910
|
+
}
|
|
911
|
+
const config = providerConfigs(chainId ?? base.id)[verifierAddress]
|
|
912
|
+
?? (typeof verifierAddress === 'string' && verifierAddress.length === 42
|
|
913
|
+
? getPaymentMethodConfig(chainId ?? base.id, verifierAddress)
|
|
914
|
+
: null);
|
|
369
915
|
return config?.name || 'Unknown';
|
|
370
916
|
};
|
|
371
917
|
/**
|
|
@@ -415,7 +961,37 @@ export function getPaymentProviderMinimum(chainId, key) {
|
|
|
415
961
|
return getPaymentMethodMinimum(chainId, key) ?? 0;
|
|
416
962
|
}
|
|
417
963
|
/**
|
|
418
|
-
*
|
|
964
|
+
* External/unregistered payment methods that are known but not in providerConfigs.
|
|
965
|
+
* These are payment methods registered by external parties (e.g., other protocols).
|
|
966
|
+
* Maps payment method ID to metadata to prevent error logging.
|
|
967
|
+
*/
|
|
968
|
+
export const externalPaymentMethods = {
|
|
969
|
+
// Pendle - registered on Base
|
|
970
|
+
'0x5908bb0c9b87763ac6171d4104847667e7f02b4c47b574fe890c1f439ed128bb': {
|
|
971
|
+
name: 'pendle',
|
|
972
|
+
originTxHash: '0x3ba1e1ae196ff5e29e09b934966e25faa34b7ec7edc371e6ef275916a9ce1f39',
|
|
973
|
+
chainId: 8453,
|
|
974
|
+
description: 'Pendle Finance payment method',
|
|
975
|
+
},
|
|
976
|
+
};
|
|
977
|
+
/**
|
|
978
|
+
* Check if a payment method is an external/unregistered payment method
|
|
979
|
+
* @param paymentMethodId - The payment method ID
|
|
980
|
+
* @returns True if the payment method is external, false otherwise
|
|
981
|
+
*/
|
|
982
|
+
export const isExternalPaymentMethod = (paymentMethodId) => {
|
|
983
|
+
return paymentMethodId in externalPaymentMethods;
|
|
984
|
+
};
|
|
985
|
+
/**
|
|
986
|
+
* Get external payment method info
|
|
987
|
+
* @param paymentMethodId - The payment method ID
|
|
988
|
+
* @returns The external payment method info or undefined
|
|
989
|
+
*/
|
|
990
|
+
export const getExternalPaymentMethod = (paymentMethodId) => {
|
|
991
|
+
return externalPaymentMethods[paymentMethodId];
|
|
992
|
+
};
|
|
993
|
+
/**
|
|
994
|
+
* Check if a payment method is known (either in providerConfigs or external)
|
|
419
995
|
* @param chainId - The chain ID
|
|
420
996
|
* @param verifierAddress - The verifier address
|
|
421
997
|
* @returns True if the payment method is known, false otherwise
|
|
@@ -424,16 +1000,150 @@ export const isPaymentMethodKnown = (chainId, verifierAddress) => {
|
|
|
424
1000
|
return !!getPaymentMethodConfig(chainId, verifierAddress);
|
|
425
1001
|
};
|
|
426
1002
|
/**
|
|
427
|
-
*
|
|
1003
|
+
* Check if a payment method ID is known (either in providerConfigs or external)
|
|
1004
|
+
* @param chainId - The chain ID
|
|
1005
|
+
* @param paymentMethodId - The payment method ID
|
|
1006
|
+
* @param verifierAddress - Optional verifier address for checking providerConfigs
|
|
1007
|
+
* @returns True if the payment method is known, false otherwise
|
|
1008
|
+
*/
|
|
1009
|
+
export const isPaymentMethodIdKnown = (chainId, paymentMethodId, verifierAddress) => {
|
|
1010
|
+
// Check if it's an external payment method first
|
|
1011
|
+
if (isExternalPaymentMethod(paymentMethodId)) {
|
|
1012
|
+
return true;
|
|
1013
|
+
}
|
|
1014
|
+
// Fall back to checking providerConfigs if verifierAddress is provided
|
|
1015
|
+
if (verifierAddress) {
|
|
1016
|
+
return isPaymentMethodKnown(chainId, verifierAddress);
|
|
1017
|
+
}
|
|
1018
|
+
return false;
|
|
1019
|
+
};
|
|
1020
|
+
/**
|
|
1021
|
+
* Get all payment methods including sub-providers
|
|
1022
|
+
* @param includeSubProviders - Whether to include sub-providers as separate entries (default: false)
|
|
428
1023
|
* @returns All payment methods
|
|
429
1024
|
*/
|
|
430
|
-
export const getAllPaymentMethods = (chainId) => {
|
|
431
|
-
|
|
1025
|
+
export const getAllPaymentMethods = (chainId, includeSubProviders = false) => {
|
|
1026
|
+
const configs = providerConfigs(chainId);
|
|
1027
|
+
const mainProviders = Object.keys(configs)
|
|
1028
|
+
.filter(key => !isProviderDisabled(key, configs[key].disabled));
|
|
1029
|
+
if (!includeSubProviders) {
|
|
1030
|
+
return mainProviders;
|
|
1031
|
+
}
|
|
1032
|
+
const allProviders = [...mainProviders];
|
|
1033
|
+
for (const key of mainProviders) {
|
|
1034
|
+
const config = configs[key];
|
|
1035
|
+
if (config.subProviders.size > 0) {
|
|
1036
|
+
config.subProviders.forEach(subProvider => {
|
|
1037
|
+
allProviders.push(subProvider.key);
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
return allProviders;
|
|
432
1042
|
};
|
|
433
1043
|
/**
|
|
434
|
-
* Get all verifiable payment methods
|
|
1044
|
+
* Get all verifiable payment methods including sub-providers
|
|
1045
|
+
* @param includeSubProviders - Whether to include sub-providers as separate entries (default: false)
|
|
435
1046
|
* @returns All verifiable payment methods
|
|
436
1047
|
*/
|
|
437
|
-
export const verifiablePaymentMethods = (chainId) => {
|
|
438
|
-
return getAllPaymentMethods(chainId).filter(key => key !== providers.MANUAL);
|
|
1048
|
+
export const verifiablePaymentMethods = (chainId, includeSubProviders = false) => {
|
|
1049
|
+
return getAllPaymentMethods(chainId, includeSubProviders).filter(key => key !== providers.MANUAL);
|
|
439
1050
|
};
|
|
1051
|
+
/**
|
|
1052
|
+
* Get supported currencies for a payment provider.
|
|
1053
|
+
* Returns only the currencies that are in the provider's supported list.
|
|
1054
|
+
*
|
|
1055
|
+
* @param config - The payment provider configuration
|
|
1056
|
+
* @returns Array of Currency objects supported by this provider
|
|
1057
|
+
*
|
|
1058
|
+
* @example
|
|
1059
|
+
* ```ts
|
|
1060
|
+
* const zelle = providerConfigs(base.id).zelle
|
|
1061
|
+
* const currencies = getCurrenciesForProvider(zelle)
|
|
1062
|
+
* // Returns [Currency(USD)] - Zelle only supports USD
|
|
1063
|
+
*
|
|
1064
|
+
* const revolut = providerConfigs(base.id).revolut
|
|
1065
|
+
* const currencies = getCurrenciesForProvider(revolut)
|
|
1066
|
+
* // Returns [Currency(USD), Currency(EUR), Currency(GBP), ...] - Revolut supports many
|
|
1067
|
+
* ```
|
|
1068
|
+
*/
|
|
1069
|
+
export function getCurrenciesForProvider(config) {
|
|
1070
|
+
const supportedIds = new Set(config.list);
|
|
1071
|
+
return Object.values(SUPPORTED_CURRENCIES).filter((currency) => supportedIds.has(currency.contractId));
|
|
1072
|
+
}
|
|
1073
|
+
/** Set of all sub-provider keys for fast lookup */
|
|
1074
|
+
const subProviderKeySet = new Set(Object.values(subProviders));
|
|
1075
|
+
/** Set of all main provider keys for fast lookup */
|
|
1076
|
+
const providerKeySet = new Set(Object.values(providers));
|
|
1077
|
+
/**
|
|
1078
|
+
* Check if a provider key is a sub-provider (e.g., 'zelle-chase', 'zelle-bofa')
|
|
1079
|
+
* @param key - The provider key to check
|
|
1080
|
+
* @returns True if the key is a sub-provider
|
|
1081
|
+
*/
|
|
1082
|
+
export function isSubProviderKey(key) {
|
|
1083
|
+
return subProviderKeySet.has(key);
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Get the parent provider key for a sub-provider.
|
|
1087
|
+
* Returns null if the key is not a sub-provider.
|
|
1088
|
+
* @param key - The sub-provider key (e.g., 'zelle-chase')
|
|
1089
|
+
* @returns The parent provider key (e.g., 'zelle') or null
|
|
1090
|
+
*/
|
|
1091
|
+
export function getParentProviderKey(key) {
|
|
1092
|
+
if (!isSubProviderKey(key)) {
|
|
1093
|
+
return null;
|
|
1094
|
+
}
|
|
1095
|
+
// Sub-provider keys follow the pattern '{parent}-{subName}'
|
|
1096
|
+
const parentKey = key.split('-')[0];
|
|
1097
|
+
if (parentKey && providerKeySet.has(parentKey)) {
|
|
1098
|
+
return parentKey;
|
|
1099
|
+
}
|
|
1100
|
+
return null;
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Get the extension platform key for a provider or sub-provider.
|
|
1104
|
+
* For sub-providers like 'zelle-chase', returns the extensionPlatform from config (e.g., 'chase').
|
|
1105
|
+
* For main providers, returns the provider key itself.
|
|
1106
|
+
* @param key - The provider or sub-provider key
|
|
1107
|
+
* @returns The platform key to use with the PeerAuth extension
|
|
1108
|
+
*/
|
|
1109
|
+
export function getExtensionPlatform(key) {
|
|
1110
|
+
const parentKey = getParentProviderKey(key);
|
|
1111
|
+
if (parentKey) {
|
|
1112
|
+
// It's a sub-provider - look up the extensionPlatform from config
|
|
1113
|
+
const subConfig = subProviderConfigs[parentKey]?.[key];
|
|
1114
|
+
if (subConfig?.extensionPlatform) {
|
|
1115
|
+
return subConfig.extensionPlatform;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
// Main provider - use the key as the platform
|
|
1119
|
+
return key;
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Get icon and color info for both parent and sub-provider.
|
|
1123
|
+
* Returns array of icon configs: [parent, subProvider] for sub-providers, [provider] for main providers.
|
|
1124
|
+
* @param chainId - The chain ID for config lookup
|
|
1125
|
+
* @param key - The provider or sub-provider key
|
|
1126
|
+
* @returns Array of icon configs with icon string and optional color
|
|
1127
|
+
*/
|
|
1128
|
+
export function getProviderIconStack(chainId, key) {
|
|
1129
|
+
const configs = providerConfigs(chainId);
|
|
1130
|
+
// Check if this is a sub-provider
|
|
1131
|
+
const parentKey = getParentProviderKey(key);
|
|
1132
|
+
if (parentKey) {
|
|
1133
|
+
const parentConfig = configs[parentKey];
|
|
1134
|
+
const subConfig = subProviderConfigs[parentKey]?.[key];
|
|
1135
|
+
if (parentConfig && subConfig) {
|
|
1136
|
+
return [
|
|
1137
|
+
{ icon: parentConfig.icon, color: parentConfig.color, name: parentConfig.name },
|
|
1138
|
+
{ icon: subConfig.icon ?? parentConfig.icon, color: subConfig.color ?? parentConfig.color, name: subConfig.name },
|
|
1139
|
+
];
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
// Main provider - return single icon
|
|
1143
|
+
const config = configs[key];
|
|
1144
|
+
if (config) {
|
|
1145
|
+
return [{ icon: config.icon, color: config.color, name: config.name }];
|
|
1146
|
+
}
|
|
1147
|
+
// Fallback to manual
|
|
1148
|
+
return [{ icon: configs.manual.icon, color: configs.manual.color, name: 'Unknown' }];
|
|
1149
|
+
}
|