@provex/utils 1.0.16 → 1.2.4
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/chain.d.ts +446 -0
- package/dist/chain.js +98 -0
- package/dist/chain.test.js +112 -0
- package/dist/contracts.d.ts +206 -0
- package/dist/contracts.js +292 -0
- package/dist/contracts.test.js +243 -0
- package/dist/conversionRates.d.ts +215 -0
- package/dist/{src/conversionRates.js → conversionRates.js} +74 -4
- package/dist/conversionRates.test.js +473 -0
- package/dist/currencies.d.ts +248 -0
- package/dist/{src/currencies.js → currencies.js} +119 -38
- package/dist/currencies.test.js +343 -0
- package/dist/data/countries.json +1099 -0
- package/dist/deposit.d.ts +69 -0
- package/dist/deposit.js +52 -0
- package/dist/depositKeys.d.ts +154 -0
- package/dist/depositKeys.js +104 -0
- package/dist/depositKeys.test.d.ts +1 -0
- package/dist/depositKeys.test.js +231 -0
- package/dist/events.d.ts +41 -0
- package/dist/events.js +92 -0
- package/dist/events.test.d.ts +1 -0
- package/dist/events.test.js +111 -0
- package/dist/fees.d.ts +136 -0
- package/dist/fees.js +178 -0
- package/dist/fees.test.d.ts +1 -0
- package/dist/fees.test.js +165 -0
- package/dist/ids.d.ts +175 -0
- package/dist/ids.js +231 -0
- package/dist/ids.test.d.ts +1 -0
- package/dist/ids.test.js +607 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +45 -0
- package/dist/input.d.ts +26 -0
- package/dist/{src/input.js → input.js} +23 -4
- package/dist/intent.d.ts +50 -0
- package/dist/intent.js +28 -0
- package/dist/intent.test.d.ts +1 -0
- package/dist/intent.test.js +119 -0
- package/dist/json.d.ts +55 -0
- package/dist/json.js +80 -0
- package/dist/participants.d.ts +22 -0
- package/dist/participants.js +28 -0
- package/dist/payment.d.ts +481 -0
- package/dist/payment.js +1149 -0
- package/dist/payment.test.d.ts +1 -0
- package/dist/payment.test.js +272 -0
- package/dist/peer-types.d.ts +327 -0
- package/dist/peer-types.js +169 -0
- package/dist/profit.d.ts +49 -0
- package/dist/profit.js +57 -0
- package/dist/profit.test.d.ts +1 -0
- package/dist/profit.test.js +315 -0
- package/dist/reputation.d.ts +125 -0
- package/dist/reputation.js +188 -0
- package/dist/reputation.test.d.ts +1 -0
- package/dist/reputation.test.js +156 -0
- package/dist/sort.d.ts +75 -0
- package/dist/sort.js +70 -0
- package/dist/sort.test.d.ts +1 -0
- package/dist/sort.test.js +216 -0
- package/dist/stateKey.d.ts +35 -0
- package/dist/stateKey.js +36 -0
- package/dist/stats.d.ts +61 -0
- package/dist/stats.js +53 -0
- package/dist/stats.test.d.ts +1 -0
- package/dist/stats.test.js +104 -0
- package/dist/time.d.ts +104 -0
- package/dist/time.js +162 -0
- package/dist/time.test.d.ts +1 -0
- package/dist/time.test.js +231 -0
- package/dist/tokens.d.ts +15502 -0
- package/dist/{src/tokens.js → tokens.js} +98 -17
- package/dist/tokens.test.d.ts +1 -0
- package/dist/tokens.test.js +193 -0
- package/dist/units.d.ts +200 -0
- package/dist/units.js +279 -0
- package/dist/units.test.d.ts +1 -0
- package/dist/units.test.js +327 -0
- package/package.json +119 -29
- package/dist/scripts/convert-svg.js +0 -17
- package/dist/src/chain.d.ts +0 -14
- package/dist/src/chain.js +0 -18
- package/dist/src/contracts.d.ts +0 -30
- package/dist/src/contracts.js +0 -64
- package/dist/src/conversionRates.d.ts +0 -124
- package/dist/src/currencies.d.ts +0 -144
- package/dist/src/data/countries.json +0 -1099
- package/dist/src/deposit.d.ts +0 -1
- package/dist/src/events.d.ts +0 -3
- package/dist/src/events.js +0 -16
- package/dist/src/ids.d.ts +0 -72
- package/dist/src/ids.js +0 -81
- package/dist/src/index.d.ts +0 -16
- package/dist/src/index.js +0 -16
- package/dist/src/input.d.ts +0 -7
- package/dist/src/intent.d.ts +0 -14
- package/dist/src/json.d.ts +0 -18
- package/dist/src/json.js +0 -44
- package/dist/src/participants.d.ts +0 -7
- package/dist/src/participants.js +0 -13
- package/dist/src/payment.d.ts +0 -164
- package/dist/src/payment.js +0 -439
- package/dist/src/profit.d.ts +0 -28
- package/dist/src/profit.js +0 -34
- package/dist/src/sort.d.ts +0 -36
- package/dist/src/sort.js +0 -39
- package/dist/src/stats.d.ts +0 -7
- package/dist/src/stats.js +0 -8
- package/dist/src/time.d.ts +0 -54
- package/dist/src/time.js +0 -106
- package/dist/src/tokens.d.ts +0 -3675
- package/dist/src/units.d.ts +0 -17
- package/dist/src/units.js +0 -79
- package/dist/src/zkp2p-types.d.ts +0 -48
- package/dist/tsconfig.tsbuildinfo +0 -1
- 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/{scripts/convert-svg.d.ts → chain.test.d.ts} +0 -0
- /package/dist/{src/deposit.js → contracts.test.d.ts} +0 -0
- /package/dist/{src/intent.js → conversionRates.test.d.ts} +0 -0
- /package/dist/{src/zkp2p-types.js → currencies.test.d.ts} +0 -0
- /package/dist/{src/flags.d.ts → flags.d.ts} +0 -0
- /package/dist/{src/flags.js → flags.js} +0 -0
package/dist/payment.js
ADDED
|
@@ -0,0 +1,1149 @@
|
|
|
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
|
+
}
|
|
74
|
+
import { base, pulsechain } from "viem/chains";
|
|
75
|
+
import { contracts } from "./contracts.js";
|
|
76
|
+
import { formatUnits } from "./units.js";
|
|
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
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Payment providers, including manual
|
|
113
|
+
*/
|
|
114
|
+
export const providers = {
|
|
115
|
+
VENMO: 'venmo',
|
|
116
|
+
ZELLE: 'zelle',
|
|
117
|
+
CASHAPP: 'cashapp',
|
|
118
|
+
REVOLUT: 'revolut',
|
|
119
|
+
WISE: 'wise',
|
|
120
|
+
MERCADOPAGO: 'mercadopago',
|
|
121
|
+
MANUAL: 'manual',
|
|
122
|
+
PAYPAL: 'paypal',
|
|
123
|
+
MONZO: 'monzo',
|
|
124
|
+
N26: 'n26',
|
|
125
|
+
ALIPAY: 'alipay',
|
|
126
|
+
CHIME: 'chime',
|
|
127
|
+
ROYALBANKCANADA: 'royalbankcanada',
|
|
128
|
+
IDFC: 'idfc',
|
|
129
|
+
};
|
|
130
|
+
/** Distinct keys for payment sub-providers (currently only used by Zelle) */
|
|
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 = {
|
|
142
|
+
CHASE: 'chase',
|
|
143
|
+
BOFA: 'bankofamerica',
|
|
144
|
+
CITI: 'citi',
|
|
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
|
+
}
|
|
194
|
+
/** Provider key to validation key */
|
|
195
|
+
export const providerKeyToValidationKey = {
|
|
196
|
+
venmo: 'venmoUsername',
|
|
197
|
+
zelle: 'zelleEmail',
|
|
198
|
+
cashapp: 'cashtag',
|
|
199
|
+
revolut: 'revolutUsername',
|
|
200
|
+
wise: 'wisetag',
|
|
201
|
+
mercadopago: 'cvu',
|
|
202
|
+
paypal: 'paypalEmail',
|
|
203
|
+
monzo: 'monzoMeUsername',
|
|
204
|
+
n26: 'n26Email',
|
|
205
|
+
alipay: 'alipayId',
|
|
206
|
+
chime: 'chimesign',
|
|
207
|
+
royalbankcanada: 'interacEmail',
|
|
208
|
+
idfc: 'idfcAccountNumber',
|
|
209
|
+
};
|
|
210
|
+
/** Data encoding for zelle urls */
|
|
211
|
+
export const dataEncoding = (data) => {
|
|
212
|
+
return btoa(JSON.stringify({
|
|
213
|
+
name: '',
|
|
214
|
+
action: 'payment',
|
|
215
|
+
token: data,
|
|
216
|
+
}));
|
|
217
|
+
};
|
|
218
|
+
/** Default Zelle send link */
|
|
219
|
+
export const defaultZelleSendLink = (options) => (!options.username ? null
|
|
220
|
+
: `https://enroll.zellepay.com/qr-codes?data=${dataEncoding(options.username)}`);
|
|
221
|
+
/** Global configuration for all supported sub-providers. Other modules can import this directly. */
|
|
222
|
+
export const subProviderConfigs = {
|
|
223
|
+
zelle: {
|
|
224
|
+
'zelle-chase': {
|
|
225
|
+
paymentMethod: 0,
|
|
226
|
+
key: subProviders.CHASE,
|
|
227
|
+
name: 'Chase',
|
|
228
|
+
icon: 'simple-icons:chase',
|
|
229
|
+
extensionPlatform: extensionPlatforms.CHASE,
|
|
230
|
+
v2Verifiers: (chain) => contracts.v2[chain].zelleChaseReclaimVerifier,
|
|
231
|
+
sendLink: (opts) => {
|
|
232
|
+
if (opts.qrCode) {
|
|
233
|
+
return defaultZelleSendLink(opts);
|
|
234
|
+
}
|
|
235
|
+
// return 'https://secure.chase.com/web/auth/dashboard#/dashboard/singleDoor/payments/activity;params=qp,sentactivity'
|
|
236
|
+
return 'https://secure.chase.com/web/auth/dashboard#/dashboard/singleDoor/singleDoorController/index';
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
'zelle-bofa': {
|
|
240
|
+
paymentMethod: 1,
|
|
241
|
+
key: subProviders.BANK_OF_AMERICA,
|
|
242
|
+
name: 'Bank of America',
|
|
243
|
+
icon: 'simple-icons:bankofamerica',
|
|
244
|
+
extensionPlatform: extensionPlatforms.BOFA,
|
|
245
|
+
v2Verifiers: (chain) => contracts.v2[chain].zelleBoAReclaimVerifier,
|
|
246
|
+
sendLink: (opts) => {
|
|
247
|
+
if (opts.qrCode) {
|
|
248
|
+
return `https://www.bankofamerica.com/movemoney`;
|
|
249
|
+
}
|
|
250
|
+
return 'https://www.bankofamerica.com/';
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
'zelle-citi': {
|
|
254
|
+
paymentMethod: 2,
|
|
255
|
+
key: subProviders.CITI,
|
|
256
|
+
name: 'Citi',
|
|
257
|
+
icon: 'arcticons:citi-mobile',
|
|
258
|
+
extensionPlatform: extensionPlatforms.CITI,
|
|
259
|
+
v2Verifiers: (chain) => contracts.v2[chain].zelleCitiReclaimVerifier,
|
|
260
|
+
sendLink: (opts) => {
|
|
261
|
+
if (opts.qrCode) {
|
|
262
|
+
return defaultZelleSendLink(opts);
|
|
263
|
+
}
|
|
264
|
+
return 'https://online.citi.com/US/nga/zelle/transfer';
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
/** Payment method icon mappings */
|
|
270
|
+
export const providerConfigs = (chainId) => {
|
|
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
|
+
};
|
|
290
|
+
return {
|
|
291
|
+
venmo: {
|
|
292
|
+
key: providers.VENMO,
|
|
293
|
+
contractId: providerKeyToContractId(providers.VENMO),
|
|
294
|
+
icon: 'ion:logo-venmo',
|
|
295
|
+
name: 'Venmo',
|
|
296
|
+
usernameType: 'Venmo Username',
|
|
297
|
+
validationKey: providerKeyToValidationKey.venmo,
|
|
298
|
+
color: 'rgb(0, 116, 222)',
|
|
299
|
+
chartColorLight: '#0074de',
|
|
300
|
+
chartColorDark: '#4da5ff',
|
|
301
|
+
v2Verifiers: getV2Verifiers('venmoReclaimVerifier'),
|
|
302
|
+
limits: {
|
|
303
|
+
min: 1.0,
|
|
304
|
+
},
|
|
305
|
+
subProviders: new Set(),
|
|
306
|
+
sendLink: (options) => {
|
|
307
|
+
if (options.qrCode) {
|
|
308
|
+
return `venmo://paycharge?txn=pay&recipients=${options.username}¬e=cash&amount=${options.amount}`;
|
|
309
|
+
}
|
|
310
|
+
return `https://account.venmo.com/pay?recipients=${options.username}¬e=cash&amount=${options.amount}`;
|
|
311
|
+
},
|
|
312
|
+
list: [
|
|
313
|
+
SUPPORTED_CURRENCIES.USD.contractId,
|
|
314
|
+
],
|
|
315
|
+
// High risk - 1x multiplier, has cooldown
|
|
316
|
+
riskLevel: 'high',
|
|
317
|
+
capMultiplier: 1,
|
|
318
|
+
hasCooldown: true,
|
|
319
|
+
minimumTier: null,
|
|
320
|
+
},
|
|
321
|
+
zelle: {
|
|
322
|
+
key: providers.ZELLE,
|
|
323
|
+
contractId: providerKeyToContractId(providers.ZELLE),
|
|
324
|
+
icon: 'simple-icons:zelle',
|
|
325
|
+
name: 'Zelle',
|
|
326
|
+
color: '#6d1fd4',
|
|
327
|
+
usernameType: 'Zelle Email',
|
|
328
|
+
validationKey: providerKeyToValidationKey.zelle,
|
|
329
|
+
v2Verifiers: getV2Verifiers('zelleBaseVerifier'),
|
|
330
|
+
limits: {
|
|
331
|
+
min: 1.0,
|
|
332
|
+
},
|
|
333
|
+
subProviders: new Set([
|
|
334
|
+
...Object.values(subProviderConfigs.zelle),
|
|
335
|
+
]),
|
|
336
|
+
// Delegate to sub-provider specific link when provided, otherwise fall back to generic QR URL
|
|
337
|
+
sendLink: (options) => {
|
|
338
|
+
if (options.subProvider) {
|
|
339
|
+
return subProviderConfigs.zelle[options.subProvider].sendLink(options);
|
|
340
|
+
}
|
|
341
|
+
return defaultZelleSendLink(options);
|
|
342
|
+
},
|
|
343
|
+
list: [
|
|
344
|
+
SUPPORTED_CURRENCIES.USD.contractId,
|
|
345
|
+
],
|
|
346
|
+
// Medium risk - 1.5x multiplier, has cooldown
|
|
347
|
+
riskLevel: 'medium',
|
|
348
|
+
capMultiplier: 1.5,
|
|
349
|
+
hasCooldown: true,
|
|
350
|
+
minimumTier: null,
|
|
351
|
+
},
|
|
352
|
+
cashapp: {
|
|
353
|
+
key: providers.CASHAPP,
|
|
354
|
+
contractId: providerKeyToContractId(providers.CASHAPP),
|
|
355
|
+
icon: 'simple-icons:cashapp',
|
|
356
|
+
name: 'Cash App',
|
|
357
|
+
color: 'rgba(0,224,19,1.0)',
|
|
358
|
+
chartColorLight: '#00e013',
|
|
359
|
+
chartColorDark: '#4dff6a',
|
|
360
|
+
usernameType: 'CashTag',
|
|
361
|
+
validationKey: providerKeyToValidationKey.cashapp,
|
|
362
|
+
v2Verifiers: getV2Verifiers('cashappReclaimVerifier'),
|
|
363
|
+
limits: {
|
|
364
|
+
min: 1.0,
|
|
365
|
+
},
|
|
366
|
+
subProviders: new Set(),
|
|
367
|
+
list: [
|
|
368
|
+
SUPPORTED_CURRENCIES.USD.contractId,
|
|
369
|
+
],
|
|
370
|
+
sendLink: (options) => {
|
|
371
|
+
const u = options.username.startsWith('$') ? options.username : `$${options.username}`;
|
|
372
|
+
return `https://cash.app/qr/${u}?size=288&margin=0`;
|
|
373
|
+
},
|
|
374
|
+
// High risk - 1x multiplier, has cooldown
|
|
375
|
+
riskLevel: 'high',
|
|
376
|
+
capMultiplier: 1,
|
|
377
|
+
hasCooldown: true,
|
|
378
|
+
minimumTier: null,
|
|
379
|
+
},
|
|
380
|
+
revolut: {
|
|
381
|
+
key: providers.REVOLUT,
|
|
382
|
+
contractId: providerKeyToContractId(providers.REVOLUT),
|
|
383
|
+
icon: 'simple-icons:revolut',
|
|
384
|
+
name: 'Revolut',
|
|
385
|
+
color: '#191c1f',
|
|
386
|
+
// Chart-friendly color to ensure distinction in stacked bar palette
|
|
387
|
+
chartColorLight: '#8b5cf6',
|
|
388
|
+
chartColorDark: '#c4b5fd',
|
|
389
|
+
backgroundColor: '#ffffff',
|
|
390
|
+
usernameType: 'RevTag',
|
|
391
|
+
validationKey: providerKeyToValidationKey.revolut,
|
|
392
|
+
v2Verifiers: getV2Verifiers('revolutReclaimVerifier'),
|
|
393
|
+
limits: {
|
|
394
|
+
min: 1.0,
|
|
395
|
+
},
|
|
396
|
+
subProviders: new Set(),
|
|
397
|
+
sendLink: (options) => `https://revolut.me/${options.username}`,
|
|
398
|
+
list: [
|
|
399
|
+
SUPPORTED_CURRENCIES.USD.contractId,
|
|
400
|
+
SUPPORTED_CURRENCIES.EUR.contractId,
|
|
401
|
+
SUPPORTED_CURRENCIES.GBP.contractId,
|
|
402
|
+
SUPPORTED_CURRENCIES.SGD.contractId,
|
|
403
|
+
SUPPORTED_CURRENCIES.NZD.contractId,
|
|
404
|
+
SUPPORTED_CURRENCIES.AUD.contractId,
|
|
405
|
+
SUPPORTED_CURRENCIES.CAD.contractId,
|
|
406
|
+
SUPPORTED_CURRENCIES.HKD.contractId,
|
|
407
|
+
SUPPORTED_CURRENCIES.MXN.contractId,
|
|
408
|
+
SUPPORTED_CURRENCIES.SAR.contractId,
|
|
409
|
+
SUPPORTED_CURRENCIES.AED.contractId,
|
|
410
|
+
SUPPORTED_CURRENCIES.THB.contractId,
|
|
411
|
+
SUPPORTED_CURRENCIES.TRY.contractId,
|
|
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,
|
|
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,
|
|
431
|
+
},
|
|
432
|
+
wise: {
|
|
433
|
+
key: providers.WISE,
|
|
434
|
+
contractId: providerKeyToContractId(providers.WISE),
|
|
435
|
+
icon: 'simple-icons:wise',
|
|
436
|
+
name: 'Wise',
|
|
437
|
+
color: '#9fe870',
|
|
438
|
+
usernameType: 'WiseTag',
|
|
439
|
+
validationKey: providerKeyToValidationKey.wise,
|
|
440
|
+
v2Verifiers: getV2Verifiers('wiseReclaimVerifier'),
|
|
441
|
+
limits: {
|
|
442
|
+
min: 1.0,
|
|
443
|
+
},
|
|
444
|
+
subProviders: new Set(),
|
|
445
|
+
sendLink: (options) => `https://wise.com/pay/me/${options.username}`,
|
|
446
|
+
list: [
|
|
447
|
+
SUPPORTED_CURRENCIES.USD.contractId,
|
|
448
|
+
SUPPORTED_CURRENCIES.CNY.contractId,
|
|
449
|
+
SUPPORTED_CURRENCIES.EUR.contractId,
|
|
450
|
+
SUPPORTED_CURRENCIES.GBP.contractId,
|
|
451
|
+
SUPPORTED_CURRENCIES.AUD.contractId,
|
|
452
|
+
SUPPORTED_CURRENCIES.NZD.contractId,
|
|
453
|
+
SUPPORTED_CURRENCIES.CAD.contractId,
|
|
454
|
+
SUPPORTED_CURRENCIES.AED.contractId,
|
|
455
|
+
SUPPORTED_CURRENCIES.CHF.contractId,
|
|
456
|
+
SUPPORTED_CURRENCIES.ZAR.contractId,
|
|
457
|
+
SUPPORTED_CURRENCIES.SGD.contractId,
|
|
458
|
+
SUPPORTED_CURRENCIES.ILS.contractId,
|
|
459
|
+
SUPPORTED_CURRENCIES.HKD.contractId,
|
|
460
|
+
SUPPORTED_CURRENCIES.JPY.contractId,
|
|
461
|
+
SUPPORTED_CURRENCIES.PLN.contractId,
|
|
462
|
+
SUPPORTED_CURRENCIES.TRY.contractId,
|
|
463
|
+
SUPPORTED_CURRENCIES.IDR.contractId,
|
|
464
|
+
SUPPORTED_CURRENCIES.KES.contractId,
|
|
465
|
+
SUPPORTED_CURRENCIES.MYR.contractId,
|
|
466
|
+
SUPPORTED_CURRENCIES.MXN.contractId,
|
|
467
|
+
SUPPORTED_CURRENCIES.THB.contractId,
|
|
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,
|
|
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',
|
|
486
|
+
},
|
|
487
|
+
mercadopago: {
|
|
488
|
+
key: providers.MERCADOPAGO,
|
|
489
|
+
contractId: providerKeyToContractId(providers.MERCADOPAGO),
|
|
490
|
+
icon: 'simple-icons:mercadopago',
|
|
491
|
+
name: 'Mercado Pago',
|
|
492
|
+
usernameType: 'Mercado Pago / Bank CVU',
|
|
493
|
+
color: '#ffe600',
|
|
494
|
+
validationKey: providerKeyToValidationKey.mercadopago,
|
|
495
|
+
v2Verifiers: getV2Verifiers('mercadopagoReclaimVerifier'),
|
|
496
|
+
limits: {
|
|
497
|
+
min: 1.0,
|
|
498
|
+
},
|
|
499
|
+
subProviders: new Set(),
|
|
500
|
+
sendLink: () => `https://www.mercadopago.com.ar/money-out/transfer/`,
|
|
501
|
+
list: [
|
|
502
|
+
SUPPORTED_CURRENCIES.ARS.contractId,
|
|
503
|
+
],
|
|
504
|
+
// Low risk - instant settlement, no chargebacks (per peer.xyz docs)
|
|
505
|
+
riskLevel: 'low',
|
|
506
|
+
capMultiplier: 5,
|
|
507
|
+
hasCooldown: false,
|
|
508
|
+
minimumTier: null,
|
|
509
|
+
},
|
|
510
|
+
paypal: {
|
|
511
|
+
key: providers.PAYPAL,
|
|
512
|
+
contractId: providerKeyToContractId(providers.PAYPAL),
|
|
513
|
+
icon: 'simple-icons:paypal',
|
|
514
|
+
name: 'PayPal',
|
|
515
|
+
usernameType: 'PayPal Email',
|
|
516
|
+
validationKey: providerKeyToValidationKey.paypal,
|
|
517
|
+
v2Verifiers: getV2Verifiers('paypalReclaimVerifier'),
|
|
518
|
+
limits: {
|
|
519
|
+
min: 1.0,
|
|
520
|
+
},
|
|
521
|
+
subProviders: new Set(),
|
|
522
|
+
color: '#0070BA',
|
|
523
|
+
chartColor: '#f59e0b',
|
|
524
|
+
sendLink: (options) => {
|
|
525
|
+
if (options.qrCode) {
|
|
526
|
+
return `paypal://`;
|
|
527
|
+
}
|
|
528
|
+
return `https://www.paypal.com/myaccount/transfer/homepage`;
|
|
529
|
+
},
|
|
530
|
+
list: [
|
|
531
|
+
SUPPORTED_CURRENCIES.USD.contractId,
|
|
532
|
+
SUPPORTED_CURRENCIES.EUR.contractId,
|
|
533
|
+
SUPPORTED_CURRENCIES.GBP.contractId,
|
|
534
|
+
SUPPORTED_CURRENCIES.AUD.contractId,
|
|
535
|
+
SUPPORTED_CURRENCIES.NZD.contractId,
|
|
536
|
+
SUPPORTED_CURRENCIES.CAD.contractId,
|
|
537
|
+
SUPPORTED_CURRENCIES.SGD.contractId,
|
|
538
|
+
],
|
|
539
|
+
riskLevel: 'highest',
|
|
540
|
+
capMultiplier: 0.75,
|
|
541
|
+
hasCooldown: true,
|
|
542
|
+
minimumTier: tiers.PLUS,
|
|
543
|
+
disabled: true,
|
|
544
|
+
},
|
|
545
|
+
monzo: {
|
|
546
|
+
key: providers.MONZO,
|
|
547
|
+
contractId: providerKeyToContractId(providers.MONZO),
|
|
548
|
+
icon: 'simple-icons:monzo',
|
|
549
|
+
name: 'Monzo',
|
|
550
|
+
usernameType: 'Monzo Me Username',
|
|
551
|
+
validationKey: providerKeyToValidationKey.monzo,
|
|
552
|
+
v2Verifiers: getV2Verifiers('monzoReclaimVerifier'),
|
|
553
|
+
limits: {
|
|
554
|
+
min: 1.0,
|
|
555
|
+
},
|
|
556
|
+
subProviders: new Set(),
|
|
557
|
+
sendLink: (options) => `https://monzo.me/${options.username}`,
|
|
558
|
+
list: [
|
|
559
|
+
SUPPORTED_CURRENCIES.GBP.contractId,
|
|
560
|
+
],
|
|
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,
|
|
699
|
+
},
|
|
700
|
+
manual: {
|
|
701
|
+
key: providers.MANUAL,
|
|
702
|
+
contractId: providerKeyToContractId(providers.MANUAL),
|
|
703
|
+
icon: 'mdi:help-circle',
|
|
704
|
+
name: 'Manual',
|
|
705
|
+
color: 'gray',
|
|
706
|
+
usernameType: '',
|
|
707
|
+
validationKey: null,
|
|
708
|
+
v2Verifiers: [zeroAddress],
|
|
709
|
+
limits: {
|
|
710
|
+
min: 0.0,
|
|
711
|
+
},
|
|
712
|
+
subProviders: new Set(),
|
|
713
|
+
list: [],
|
|
714
|
+
// Manual verification - no reputation restrictions
|
|
715
|
+
riskLevel: 'low',
|
|
716
|
+
capMultiplier: 5,
|
|
717
|
+
hasCooldown: false,
|
|
718
|
+
minimumTier: null,
|
|
719
|
+
},
|
|
720
|
+
};
|
|
721
|
+
};
|
|
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])));
|
|
818
|
+
/** Provider key to verifiers */
|
|
819
|
+
export const providerKeyToVerifiers = (chainId, providerKey) => {
|
|
820
|
+
return providerKeyToVerifiersMap(chainId).get(providerKey) ?? null;
|
|
821
|
+
};
|
|
822
|
+
/** Verifier gets key */
|
|
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
|
|
837
|
+
try {
|
|
838
|
+
return paymentVerifierToKey(chainId).get(getAddress(verifierAddress)) ?? providers.MANUAL;
|
|
839
|
+
}
|
|
840
|
+
catch (error) {
|
|
841
|
+
return providers.MANUAL;
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
/**
|
|
845
|
+
* Utility function to get payment method icon
|
|
846
|
+
* @param key - The provider key (main provider or sub-provider like 'zelle-chase')
|
|
847
|
+
* @returns The icon string used for iconify
|
|
848
|
+
*/
|
|
849
|
+
export const getPaymentIcon = (chainId, key) => {
|
|
850
|
+
const config = providerConfigs(chainId ?? pulsechain.id);
|
|
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;
|
|
861
|
+
};
|
|
862
|
+
/**
|
|
863
|
+
* Utility function to get payment method configuration by verifier address
|
|
864
|
+
* @param verifierAddress - The verifier address
|
|
865
|
+
* @returns The payment method configuration
|
|
866
|
+
*/
|
|
867
|
+
export const getPaymentMethodConfig = (chainId, verifierAddress) => {
|
|
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);
|
|
878
|
+
};
|
|
879
|
+
/**
|
|
880
|
+
* Utility function to get payment method minimum limit by verifier address
|
|
881
|
+
* @param key - The provider key
|
|
882
|
+
* @returns The minimum limit
|
|
883
|
+
*/
|
|
884
|
+
export const getPaymentMethodMinimum = (chainId, key) => {
|
|
885
|
+
const config = providerConfigs(chainId ?? base.id)[key];
|
|
886
|
+
return config?.limits?.min ?? 0;
|
|
887
|
+
};
|
|
888
|
+
/**
|
|
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')
|
|
891
|
+
*/
|
|
892
|
+
export const getPaymentMethodName = (chainId, verifierAddress) => {
|
|
893
|
+
const providerKey = verifierAddress;
|
|
894
|
+
const providerConfig = providerConfigs(chainId ?? base.id)[providerKey];
|
|
895
|
+
if (providerConfig) {
|
|
896
|
+
return providerConfig.name;
|
|
897
|
+
}
|
|
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);
|
|
915
|
+
return config?.name || 'Unknown';
|
|
916
|
+
};
|
|
917
|
+
/**
|
|
918
|
+
* Calculate effective minimum amount (higher of user minimum or payment provider minimum)
|
|
919
|
+
* @param userMinAmountWei - The user minimum amount
|
|
920
|
+
* @param tokenInfo - The token info
|
|
921
|
+
* @param providerRates - The provider rates
|
|
922
|
+
* @returns The effective minimum amount
|
|
923
|
+
*/
|
|
924
|
+
export function calculateEffectiveMinimum(chainId, userMinAmountWei, tokenInfo, providerRates) {
|
|
925
|
+
const userMinAmountWeiBigInt = BigInt(userMinAmountWei);
|
|
926
|
+
let providerMinAmountWei = 0n;
|
|
927
|
+
if (providerRates) {
|
|
928
|
+
// Get unique payment providers from the rates
|
|
929
|
+
const paymentProviders = new Set();
|
|
930
|
+
for (const [providerKey] of providerRates.entries()) {
|
|
931
|
+
paymentProviders.add(providerKey);
|
|
932
|
+
}
|
|
933
|
+
// Calculate the highest provider minimum limit
|
|
934
|
+
for (const providerKey of paymentProviders) {
|
|
935
|
+
const providerConfig = providerConfigs(chainId)[providerKey];
|
|
936
|
+
if (providerConfig?.limits?.min) {
|
|
937
|
+
const providerMinWei = parseUnits(providerConfig.limits.min.toString(), tokenInfo.decimals);
|
|
938
|
+
if (providerMinWei > providerMinAmountWei) {
|
|
939
|
+
providerMinAmountWei = providerMinWei;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
const effectiveMinAmountWei = userMinAmountWeiBigInt > providerMinAmountWei
|
|
945
|
+
? userMinAmountWeiBigInt
|
|
946
|
+
: providerMinAmountWei;
|
|
947
|
+
const formattedEffectiveMin = formatUnits(effectiveMinAmountWei, { decimals: tokenInfo.decimals });
|
|
948
|
+
return {
|
|
949
|
+
userMinAmountWei: userMinAmountWeiBigInt,
|
|
950
|
+
providerMinAmountWei,
|
|
951
|
+
effectiveMinAmountWei,
|
|
952
|
+
formattedEffectiveMin
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Helper function to get payment provider minimum limit (returns decimal number for config)
|
|
957
|
+
* @param key - The provider key
|
|
958
|
+
* @returns The minimum limit
|
|
959
|
+
*/
|
|
960
|
+
export function getPaymentProviderMinimum(chainId, key) {
|
|
961
|
+
return getPaymentMethodMinimum(chainId, key) ?? 0;
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
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)
|
|
995
|
+
* @param chainId - The chain ID
|
|
996
|
+
* @param verifierAddress - The verifier address
|
|
997
|
+
* @returns True if the payment method is known, false otherwise
|
|
998
|
+
*/
|
|
999
|
+
export const isPaymentMethodKnown = (chainId, verifierAddress) => {
|
|
1000
|
+
return !!getPaymentMethodConfig(chainId, verifierAddress);
|
|
1001
|
+
};
|
|
1002
|
+
/**
|
|
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)
|
|
1023
|
+
* @returns All payment methods
|
|
1024
|
+
*/
|
|
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;
|
|
1042
|
+
};
|
|
1043
|
+
/**
|
|
1044
|
+
* Get all verifiable payment methods including sub-providers
|
|
1045
|
+
* @param includeSubProviders - Whether to include sub-providers as separate entries (default: false)
|
|
1046
|
+
* @returns All verifiable payment methods
|
|
1047
|
+
*/
|
|
1048
|
+
export const verifiablePaymentMethods = (chainId, includeSubProviders = false) => {
|
|
1049
|
+
return getAllPaymentMethods(chainId, includeSubProviders).filter(key => key !== providers.MANUAL);
|
|
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
|
+
}
|