@ab-org/predicate-market-sdk 1.0.0 → 1.0.1
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/index.d.ts +672 -22
- package/dist/index.js +4700 -23
- package/package.json +6 -5
- package/dist/auth/autoReconnect.d.ts +0 -11
- package/dist/auth/autoReconnect.js +0 -36
- package/dist/auth/bundledConfig.d.ts +0 -2
- package/dist/auth/bundledConfig.js +0 -19
- package/dist/auth/config.d.ts +0 -29
- package/dist/auth/config.js +0 -53
- package/dist/auth/google.d.ts +0 -43
- package/dist/auth/google.js +0 -147
- package/dist/auth/oidcRelay.d.ts +0 -11
- package/dist/auth/oidcRelay.js +0 -107
- package/dist/auth/twitter.d.ts +0 -7
- package/dist/auth/twitter.js +0 -94
- package/dist/auth/walletAccount.d.ts +0 -20
- package/dist/auth/walletAccount.js +0 -267
- package/dist/constants/chains.d.ts +0 -2
- package/dist/constants/chains.js +0 -3
- package/dist/modules/api.d.ts +0 -149
- package/dist/modules/api.js +0 -95
- package/dist/modules/balanceQuery.d.ts +0 -27
- package/dist/modules/balanceQuery.js +0 -60
- package/dist/modules/deposit.d.ts +0 -31
- package/dist/modules/deposit.js +0 -58
- package/dist/modules/marketData.d.ts +0 -8
- package/dist/modules/marketData.js +0 -107
- package/dist/modules/withdraw.d.ts +0 -31
- package/dist/modules/withdraw.js +0 -61
- package/dist/modules/withdrawDirect.d.ts +0 -14
- package/dist/modules/withdrawDirect.js +0 -33
- package/dist/modules/withdrawExecutor.d.ts +0 -56
- package/dist/modules/withdrawExecutor.js +0 -210
- package/dist/policyAdapter.d.ts +0 -11
- package/dist/policyAdapter.js +0 -38
- package/dist/types.d.ts +0 -62
- package/dist/types.js +0 -1
- package/dist/ui/DepositModal.d.ts +0 -36
- package/dist/ui/DepositModal.js +0 -354
- package/dist/ui/SignInModal.d.ts +0 -22
- package/dist/ui/SignInModal.js +0 -77
- package/dist/ui/SignInModal.sections.d.ts +0 -33
- package/dist/ui/SignInModal.sections.js +0 -45
- package/dist/ui/SignInModal.shared.d.ts +0 -15
- package/dist/ui/SignInModal.shared.js +0 -126
- package/dist/ui/WalletSelectionModal.d.ts +0 -14
- package/dist/ui/WalletSelectionModal.js +0 -54
- package/dist/ui/WithdrawModal.d.ts +0 -57
- package/dist/ui/WithdrawModal.js +0 -574
- package/dist/ui/components/CloseButton.d.ts +0 -4
- package/dist/ui/components/CloseButton.js +0 -15
- package/dist/ui/components/Countdown.d.ts +0 -16
- package/dist/ui/components/Countdown.js +0 -42
- package/dist/ui/components/DepositDetailsPanel.d.ts +0 -8
- package/dist/ui/components/DepositDetailsPanel.js +0 -143
- package/dist/ui/components/DropdownField.d.ts +0 -19
- package/dist/ui/components/DropdownField.js +0 -81
- package/dist/ui/components/Field.d.ts +0 -10
- package/dist/ui/components/Field.js +0 -21
- package/dist/ui/components/LoginRequiredOverlay.d.ts +0 -6
- package/dist/ui/components/LoginRequiredOverlay.js +0 -31
- package/dist/ui/components/ModalCard.d.ts +0 -9
- package/dist/ui/components/ModalCard.js +0 -14
- package/dist/ui/components/ModalFrame.d.ts +0 -9
- package/dist/ui/components/ModalFrame.js +0 -18
- package/dist/ui/components/PrimaryButton.d.ts +0 -2
- package/dist/ui/components/PrimaryButton.js +0 -14
- package/dist/ui/components/QRCodePanel.d.ts +0 -4
- package/dist/ui/components/QRCodePanel.js +0 -43
- package/dist/ui/components/Select.d.ts +0 -12
- package/dist/ui/components/Select.js +0 -29
- package/dist/ui/components/StepIndicator.d.ts +0 -7
- package/dist/ui/components/StepIndicator.js +0 -35
- package/dist/ui/components/Success.d.ts +0 -1
- package/dist/ui/components/Success.js +0 -4
- package/dist/ui/components/Toast.d.ts +0 -8
- package/dist/ui/components/Toast.js +0 -51
- package/dist/ui/hooks/useSession.d.ts +0 -2
- package/dist/ui/hooks/useSession.js +0 -10
- package/dist/ui/signInTypes.d.ts +0 -28
- package/dist/ui/signInTypes.js +0 -1
- package/dist/ui/theme.d.ts +0 -31
- package/dist/ui/theme.js +0 -31
- package/dist/ui/useSignInModalController.d.ts +0 -25
- package/dist/ui/useSignInModalController.js +0 -119
- package/dist/utils/env.d.ts +0 -1
- package/dist/utils/env.js +0 -63
- package/dist/utils/explorer.d.ts +0 -3
- package/dist/utils/explorer.js +0 -47
- package/dist/walletUtils.d.ts +0 -3
- package/dist/walletUtils.js +0 -3
package/dist/index.js
CHANGED
|
@@ -1,23 +1,4700 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
import { sessionStore, createDefaultInjectedWalletRegistry, CubistSocialProvider, WalletConnector, createSessionCapabilityPolicy, CubeSignerAuth, createChainContext } from '@ab-org/sdk-core';
|
|
2
|
+
import { toHex, fromHex, parseGwei, formatUnits } from 'viem';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
|
|
5
|
+
import { EvmSigner } from '@cubist-labs/cubesigner-sdk';
|
|
6
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
|
+
import qrcode from 'qrcode-generator';
|
|
8
|
+
|
|
9
|
+
// src/utils/env.ts
|
|
10
|
+
function pick(...candidates) {
|
|
11
|
+
for (const candidate of candidates) {
|
|
12
|
+
if (candidate != null && candidate !== "") return candidate;
|
|
13
|
+
}
|
|
14
|
+
return void 0;
|
|
15
|
+
}
|
|
16
|
+
function nextPublicProcessEnvKey(logicalKey) {
|
|
17
|
+
return `NEXT_PUBLIC_${logicalKey}`;
|
|
18
|
+
}
|
|
19
|
+
function readProcessEnvStatic(key) {
|
|
20
|
+
if (typeof process === "undefined" || !process.env) return void 0;
|
|
21
|
+
switch (key) {
|
|
22
|
+
case "STAGE":
|
|
23
|
+
return pick(process.env.NEXT_PUBLIC_STAGE, process.env.STAGE);
|
|
24
|
+
case "GOOGLE_CLIENT_ID":
|
|
25
|
+
return pick(process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID, process.env.GOOGLE_CLIENT_ID);
|
|
26
|
+
case "X_CLIENT_ID":
|
|
27
|
+
return pick(process.env.NEXT_PUBLIC_X_CLIENT_ID, process.env.X_CLIENT_ID);
|
|
28
|
+
case "MERCHANT_BASE_URL":
|
|
29
|
+
return pick(process.env.NEXT_PUBLIC_MERCHANT_BASE_URL, process.env.MERCHANT_BASE_URL);
|
|
30
|
+
case "CUBE_SIGNER_ENV":
|
|
31
|
+
return pick(process.env.NEXT_PUBLIC_CUBE_SIGNER_ENV, process.env.CUBE_SIGNER_ENV);
|
|
32
|
+
case "CUBE_SIGNER_ORG_ID":
|
|
33
|
+
return pick(process.env.NEXT_PUBLIC_CUBE_SIGNER_ORG_ID, process.env.CUBE_SIGNER_ORG_ID);
|
|
34
|
+
case "CUBE_REG":
|
|
35
|
+
return pick(process.env.NEXT_PUBLIC_CUBE_REG, process.env.CUBE_REG);
|
|
36
|
+
case "RELAY_ORIGIN":
|
|
37
|
+
return pick(process.env.NEXT_PUBLIC_RELAY_ORIGIN, process.env.RELAY_ORIGIN);
|
|
38
|
+
case "FUNDING_TOKEN_SYMBOL":
|
|
39
|
+
return pick(process.env.NEXT_PUBLIC_FUNDING_TOKEN_SYMBOL, process.env.FUNDING_TOKEN_SYMBOL) || "USDT";
|
|
40
|
+
default:
|
|
41
|
+
return void 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function getEnv(key) {
|
|
45
|
+
const staticVal = readProcessEnvStatic(key);
|
|
46
|
+
if (staticVal != null && staticVal !== "") return staticVal;
|
|
47
|
+
const globalEnv = globalThis.process?.env;
|
|
48
|
+
if (globalEnv) {
|
|
49
|
+
const pub = nextPublicProcessEnvKey(key);
|
|
50
|
+
const val = globalEnv[key] ?? globalEnv[pub];
|
|
51
|
+
if (val != null && val !== "") return val;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const metaEnv = import.meta.env;
|
|
55
|
+
if (metaEnv) {
|
|
56
|
+
const pub = nextPublicProcessEnvKey(key);
|
|
57
|
+
const val = metaEnv[key] ?? metaEnv[pub];
|
|
58
|
+
if (val != null && val !== "") return val;
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
console.error(`${key} is not set`);
|
|
63
|
+
return "";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/auth/bundledConfig.ts
|
|
67
|
+
function readOptionalEnv(key) {
|
|
68
|
+
const value = getEnv(key);
|
|
69
|
+
return value === "" ? void 0 : value;
|
|
70
|
+
}
|
|
71
|
+
var relayOrigin = readOptionalEnv("RELAY_ORIGIN");
|
|
72
|
+
var cubeEnv = readOptionalEnv("CUBE_SIGNER_ENV");
|
|
73
|
+
var cubeOrgId = readOptionalEnv("CUBE_SIGNER_ORG_ID");
|
|
74
|
+
var BUNDLED_AUTH_CONFIG = {
|
|
75
|
+
googleClientId: readOptionalEnv("GOOGLE_CLIENT_ID"),
|
|
76
|
+
twitterClientId: readOptionalEnv("X_CLIENT_ID"),
|
|
77
|
+
twitterRedirectUri: relayOrigin ? `${relayOrigin}/auth/twitter-callback` : void 0,
|
|
78
|
+
cubeSigner: cubeEnv && cubeOrgId ? {
|
|
79
|
+
env: cubeEnv,
|
|
80
|
+
orgId: cubeOrgId
|
|
81
|
+
} : void 0
|
|
82
|
+
};
|
|
83
|
+
var pending = null;
|
|
84
|
+
function tryAutoReconnect() {
|
|
85
|
+
const session = sessionStore.getState().session;
|
|
86
|
+
if (!session) return Promise.resolve(null);
|
|
87
|
+
if (pending) return pending;
|
|
88
|
+
pending = doAutoReconnect().finally(() => {
|
|
89
|
+
pending = null;
|
|
90
|
+
});
|
|
91
|
+
return pending;
|
|
92
|
+
}
|
|
93
|
+
async function doAutoReconnect() {
|
|
94
|
+
const config = getSDKConfig();
|
|
95
|
+
const registry = createDefaultInjectedWalletRegistry();
|
|
96
|
+
const adapters = [...registry.map((r) => r.provider)];
|
|
97
|
+
if (config.cubeSigner) {
|
|
98
|
+
adapters.push(
|
|
99
|
+
new CubistSocialProvider({
|
|
100
|
+
...config.cubeSigner,
|
|
101
|
+
defaultSessionPolicy: config.signIn?.sessionPolicy ?? config.cubeSigner.defaultSessionPolicy
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
const connector = new WalletConnector(adapters);
|
|
106
|
+
return connector.tryAutoReconnect();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/auth/config.ts
|
|
110
|
+
var sdkConfig = {};
|
|
111
|
+
function readOptionalEnv2(key) {
|
|
112
|
+
const value = getEnv(key);
|
|
113
|
+
return value === "" ? void 0 : value;
|
|
114
|
+
}
|
|
115
|
+
function getFixedAuthConfig() {
|
|
116
|
+
const envGoogle = readOptionalEnv2("GOOGLE_CLIENT_ID");
|
|
117
|
+
const envTwitter = readOptionalEnv2("X_CLIENT_ID");
|
|
118
|
+
const relayOrigin2 = readOptionalEnv2("RELAY_ORIGIN");
|
|
119
|
+
const envRedirect = relayOrigin2 ? `${relayOrigin2}/auth/twitter-callback` : void 0;
|
|
120
|
+
const cubeEnv2 = readOptionalEnv2("CUBE_SIGNER_ENV");
|
|
121
|
+
const cubeOrgId2 = readOptionalEnv2("CUBE_SIGNER_ORG_ID");
|
|
122
|
+
const cubeSignerFromEnv = cubeEnv2 && cubeOrgId2 ? { env: cubeEnv2, orgId: cubeOrgId2 } : void 0;
|
|
123
|
+
return {
|
|
124
|
+
googleClientId: envGoogle || BUNDLED_AUTH_CONFIG.googleClientId,
|
|
125
|
+
twitterClientId: envTwitter || BUNDLED_AUTH_CONFIG.twitterClientId,
|
|
126
|
+
twitterRedirectUri: envRedirect || BUNDLED_AUTH_CONFIG.twitterRedirectUri,
|
|
127
|
+
cubeSigner: cubeSignerFromEnv ?? BUNDLED_AUTH_CONFIG.cubeSigner
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function initSDK(config = {}) {
|
|
131
|
+
const { registerUser, ...rest } = config;
|
|
132
|
+
const fixed = getFixedAuthConfig();
|
|
133
|
+
const merged = {
|
|
134
|
+
...sdkConfig,
|
|
135
|
+
...fixed,
|
|
136
|
+
...rest,
|
|
137
|
+
cubeSigner: rest.cubeSigner ?? fixed.cubeSigner
|
|
138
|
+
};
|
|
139
|
+
if (registerUser != null && merged.cubeSigner) {
|
|
140
|
+
merged.cubeSigner = {
|
|
141
|
+
...merged.cubeSigner,
|
|
142
|
+
oidcLoginHooks: {
|
|
143
|
+
...merged.cubeSigner.oidcLoginHooks,
|
|
144
|
+
registerUser
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
sdkConfig = merged;
|
|
149
|
+
tryAutoReconnect().catch(() => {
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function getSDKConfig() {
|
|
153
|
+
return sdkConfig;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// src/auth/google.ts
|
|
157
|
+
var GIS_URL = "https://accounts.google.com/gsi/client";
|
|
158
|
+
var loadPromise = null;
|
|
159
|
+
var currentCredentialHandler = null;
|
|
160
|
+
var initializedKey = null;
|
|
161
|
+
function loadGIS() {
|
|
162
|
+
if (loadPromise) return loadPromise;
|
|
163
|
+
if (window.google?.accounts?.id) {
|
|
164
|
+
loadPromise = Promise.resolve();
|
|
165
|
+
return loadPromise;
|
|
166
|
+
}
|
|
167
|
+
loadPromise = new Promise((resolve, reject) => {
|
|
168
|
+
const script = document.createElement("script");
|
|
169
|
+
script.src = GIS_URL;
|
|
170
|
+
script.async = true;
|
|
171
|
+
script.defer = true;
|
|
172
|
+
script.onload = () => resolve();
|
|
173
|
+
script.onerror = () => reject(new Error("Failed to load Google Identity Services"));
|
|
174
|
+
document.head.appendChild(script);
|
|
175
|
+
});
|
|
176
|
+
return loadPromise;
|
|
177
|
+
}
|
|
178
|
+
function decodeJwtPayload(token) {
|
|
179
|
+
const parts = token.split(".");
|
|
180
|
+
if (parts.length !== 3) throw new Error("Invalid JWT");
|
|
181
|
+
const payload = parts[1];
|
|
182
|
+
if (!payload) throw new Error("Invalid JWT payload");
|
|
183
|
+
let padded = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
184
|
+
while (padded.length % 4 !== 0) padded += "=";
|
|
185
|
+
return JSON.parse(atob(padded));
|
|
186
|
+
}
|
|
187
|
+
function isFedCMSupported() {
|
|
188
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") return false;
|
|
189
|
+
if (!window.isSecureContext) return false;
|
|
190
|
+
return typeof navigator.credentials?.get === "function";
|
|
191
|
+
}
|
|
192
|
+
async function signInWithGoogle(clientId) {
|
|
193
|
+
await loadGIS();
|
|
194
|
+
const gid = window.google?.accounts?.id;
|
|
195
|
+
if (!gid) throw new Error("Google Identity Services not available");
|
|
196
|
+
const SIGN_IN_TIMEOUT_MS = 9e4;
|
|
197
|
+
return new Promise((resolve, reject) => {
|
|
198
|
+
let settled = false;
|
|
199
|
+
let fallbackContainer = null;
|
|
200
|
+
const cleanupFallback = () => {
|
|
201
|
+
if (!fallbackContainer) return;
|
|
202
|
+
fallbackContainer.remove();
|
|
203
|
+
fallbackContainer = null;
|
|
204
|
+
};
|
|
205
|
+
const finish = (fn) => {
|
|
206
|
+
if (settled) return;
|
|
207
|
+
settled = true;
|
|
208
|
+
clearTimeout(timeoutId);
|
|
209
|
+
cleanupFallback();
|
|
210
|
+
fn();
|
|
211
|
+
};
|
|
212
|
+
const timeoutId = setTimeout(() => {
|
|
213
|
+
finish(() => reject(new Error("Google sign-in timed out")));
|
|
214
|
+
}, SIGN_IN_TIMEOUT_MS);
|
|
215
|
+
const handleCredential = (response) => {
|
|
216
|
+
finish(() => {
|
|
217
|
+
try {
|
|
218
|
+
const payload = decodeJwtPayload(response.credential);
|
|
219
|
+
resolve({
|
|
220
|
+
idToken: response.credential,
|
|
221
|
+
email: payload.email,
|
|
222
|
+
name: payload.name,
|
|
223
|
+
picture: payload.picture
|
|
224
|
+
});
|
|
225
|
+
} catch {
|
|
226
|
+
resolve({ idToken: response.credential });
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
};
|
|
230
|
+
const useFedcmForPrompt = isFedCMSupported();
|
|
231
|
+
const initKey = `${clientId}\0${useFedcmForPrompt ? "1" : "0"}`;
|
|
232
|
+
currentCredentialHandler = handleCredential;
|
|
233
|
+
if (initializedKey !== initKey) {
|
|
234
|
+
initializedKey = initKey;
|
|
235
|
+
gid.initialize({
|
|
236
|
+
client_id: clientId,
|
|
237
|
+
callback: (response) => currentCredentialHandler?.(response),
|
|
238
|
+
auto_select: false,
|
|
239
|
+
cancel_on_tap_outside: true,
|
|
240
|
+
use_fedcm_for_prompt: useFedcmForPrompt
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
const triggerFallback = () => {
|
|
244
|
+
if (settled) return;
|
|
245
|
+
fallbackContainer = document.createElement("div");
|
|
246
|
+
Object.assign(fallbackContainer.style, {
|
|
247
|
+
position: "fixed",
|
|
248
|
+
top: "-9999px",
|
|
249
|
+
left: "-9999px",
|
|
250
|
+
opacity: "0",
|
|
251
|
+
pointerEvents: "none"
|
|
252
|
+
});
|
|
253
|
+
document.body.appendChild(fallbackContainer);
|
|
254
|
+
gid.renderButton(fallbackContainer, { type: "standard", size: "large" });
|
|
255
|
+
const tryClickButton = (attemptsLeft) => {
|
|
256
|
+
requestAnimationFrame(() => {
|
|
257
|
+
const btn = fallbackContainer?.querySelector('[role="button"]') ?? fallbackContainer?.querySelector("div[style]");
|
|
258
|
+
if (btn) {
|
|
259
|
+
Object.assign(fallbackContainer.style, { pointerEvents: "auto" });
|
|
260
|
+
btn.click();
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (attemptsLeft > 0) {
|
|
264
|
+
tryClickButton(attemptsLeft - 1);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
finish(() => reject(new Error("Google sign-in unavailable")));
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
tryClickButton(8);
|
|
271
|
+
};
|
|
272
|
+
gid.prompt((moment) => {
|
|
273
|
+
if (settled) return;
|
|
274
|
+
if (moment.isDismissedMoment()) {
|
|
275
|
+
const reason = moment.getDismissedReason();
|
|
276
|
+
if (reason === "credential_returned") return;
|
|
277
|
+
finish(() => reject(new Error(`Google sign-in dismissed: ${reason}`)));
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (moment.isSkippedMoment()) {
|
|
281
|
+
triggerFallback();
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (moment.isNotDisplayed()) {
|
|
285
|
+
triggerFallback();
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/auth/twitter.ts
|
|
292
|
+
function generateRandom(length) {
|
|
293
|
+
const array = new Uint8Array(length);
|
|
294
|
+
crypto.getRandomValues(array);
|
|
295
|
+
return Array.from(array, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
296
|
+
}
|
|
297
|
+
function base64url(buffer) {
|
|
298
|
+
const bytes = new Uint8Array(buffer);
|
|
299
|
+
let binary = "";
|
|
300
|
+
for (const b of bytes) binary += String.fromCharCode(b);
|
|
301
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
302
|
+
}
|
|
303
|
+
async function createCodeChallenge(verifier) {
|
|
304
|
+
const encoder = new TextEncoder();
|
|
305
|
+
const data = encoder.encode(verifier);
|
|
306
|
+
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
307
|
+
return base64url(digest);
|
|
308
|
+
}
|
|
309
|
+
var POPUP_WIDTH = 600;
|
|
310
|
+
var POPUP_HEIGHT = 700;
|
|
311
|
+
var MESSAGE_TYPE = "twitter-oauth-callback";
|
|
312
|
+
var TWITTER_AUTH_URL = "https://twitter.com/i/oauth2/authorize";
|
|
313
|
+
function notifyTwitterCallback() {
|
|
314
|
+
const params = new URLSearchParams(window.location.search);
|
|
315
|
+
const code = params.get("code");
|
|
316
|
+
const state = params.get("state");
|
|
317
|
+
const error = params.get("error");
|
|
318
|
+
if (window.opener) {
|
|
319
|
+
window.opener.postMessage(
|
|
320
|
+
{ type: MESSAGE_TYPE, code, state, error },
|
|
321
|
+
window.location.origin
|
|
322
|
+
);
|
|
323
|
+
window.close();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
async function signInWithTwitter(clientId, redirectUri) {
|
|
327
|
+
const codeVerifier = generateRandom(64);
|
|
328
|
+
const codeChallenge = await createCodeChallenge(codeVerifier);
|
|
329
|
+
const state = generateRandom(16);
|
|
330
|
+
const authUrl = new URL(TWITTER_AUTH_URL);
|
|
331
|
+
authUrl.searchParams.set("response_type", "code");
|
|
332
|
+
authUrl.searchParams.set("client_id", clientId);
|
|
333
|
+
authUrl.searchParams.set("redirect_uri", redirectUri);
|
|
334
|
+
authUrl.searchParams.set("scope", "tweet.read users.read offline.access");
|
|
335
|
+
authUrl.searchParams.set("state", state);
|
|
336
|
+
authUrl.searchParams.set("code_challenge", codeChallenge);
|
|
337
|
+
authUrl.searchParams.set("code_challenge_method", "S256");
|
|
338
|
+
const left = Math.round(screen.width / 2 - POPUP_WIDTH / 2);
|
|
339
|
+
const top = Math.round(screen.height / 2 - POPUP_HEIGHT / 2);
|
|
340
|
+
const popup = window.open(
|
|
341
|
+
authUrl.toString(),
|
|
342
|
+
"twitter-auth",
|
|
343
|
+
`width=${POPUP_WIDTH},height=${POPUP_HEIGHT},left=${left},top=${top},toolbar=no,menubar=no`
|
|
344
|
+
);
|
|
345
|
+
if (!popup) {
|
|
346
|
+
throw new Error("Failed to open Twitter login popup. Check your popup blocker.");
|
|
347
|
+
}
|
|
348
|
+
return new Promise((resolve, reject) => {
|
|
349
|
+
let settled = false;
|
|
350
|
+
const cleanup = () => {
|
|
351
|
+
window.removeEventListener("message", onMessage);
|
|
352
|
+
clearInterval(pollTimer);
|
|
353
|
+
};
|
|
354
|
+
const onMessage = (event) => {
|
|
355
|
+
if (event.origin !== window.location.origin) return;
|
|
356
|
+
const data = event.data;
|
|
357
|
+
if (!data || data.type !== MESSAGE_TYPE) return;
|
|
358
|
+
if (settled) return;
|
|
359
|
+
settled = true;
|
|
360
|
+
cleanup();
|
|
361
|
+
if (data.error) {
|
|
362
|
+
reject(new Error(`Twitter auth error: ${data.error}`));
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
if (!data.code) {
|
|
366
|
+
reject(new Error("No authorization code received from Twitter"));
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (data.state !== state) {
|
|
370
|
+
reject(new Error("State mismatch - possible CSRF attack"));
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
resolve({
|
|
374
|
+
code: data.code,
|
|
375
|
+
codeVerifier,
|
|
376
|
+
state
|
|
377
|
+
});
|
|
378
|
+
};
|
|
379
|
+
const pollTimer = setInterval(() => {
|
|
380
|
+
if (popup.closed && !settled) {
|
|
381
|
+
settled = true;
|
|
382
|
+
cleanup();
|
|
383
|
+
reject(new Error("Twitter login popup was closed"));
|
|
384
|
+
}
|
|
385
|
+
}, 500);
|
|
386
|
+
window.addEventListener("message", onMessage);
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
function requireSession() {
|
|
390
|
+
const session = sessionStore.getState().session;
|
|
391
|
+
if (!session) throw new Error("Login required");
|
|
392
|
+
return session;
|
|
393
|
+
}
|
|
394
|
+
var createDepositController = (custody, marketData) => {
|
|
395
|
+
let status = { phase: "idle" };
|
|
396
|
+
const notify = (next, cb) => {
|
|
397
|
+
status = next;
|
|
398
|
+
cb?.(status);
|
|
399
|
+
};
|
|
400
|
+
const open = async (config) => {
|
|
401
|
+
const session = requireSession();
|
|
402
|
+
const chain = config?.preferredChain ?? session.chainContext?.settlementChain ?? session.chain ?? "AB_CORE";
|
|
403
|
+
const token = config?.preferredToken || getEnv("FUNDING_TOKEN_SYMBOL") || "USDT";
|
|
404
|
+
try {
|
|
405
|
+
const { address } = await marketData.getDepositAddress(token, chain);
|
|
406
|
+
const depositId = `${chain}:${token}:${Date.now()}`;
|
|
407
|
+
notify({ phase: "address-issued", depositId, address }, config?.onStatusChange);
|
|
408
|
+
notify({ phase: "confirming", depositId }, config?.onStatusChange);
|
|
409
|
+
const { status: finalStatus, txHash } = await custody.getDepositStatus(depositId);
|
|
410
|
+
notify(
|
|
411
|
+
finalStatus === "SETTLED" ? { phase: "settled", depositId, txHash } : { phase: "failed", reason: finalStatus },
|
|
412
|
+
config?.onStatusChange
|
|
413
|
+
);
|
|
414
|
+
} catch (error) {
|
|
415
|
+
notify({ phase: "failed", reason: error.message }, config?.onStatusChange);
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
return {
|
|
419
|
+
get status() {
|
|
420
|
+
return status;
|
|
421
|
+
},
|
|
422
|
+
open,
|
|
423
|
+
fetchTokens() {
|
|
424
|
+
requireSession();
|
|
425
|
+
return marketData.getSupportedTokens("deposit");
|
|
426
|
+
},
|
|
427
|
+
fetchChains(token) {
|
|
428
|
+
requireSession();
|
|
429
|
+
return marketData.getSupportedChains(token, "deposit");
|
|
430
|
+
},
|
|
431
|
+
fetchQuote(token, chain, amount) {
|
|
432
|
+
requireSession();
|
|
433
|
+
return marketData.getQuote({ token, chain, amount, direction: "deposit" });
|
|
434
|
+
},
|
|
435
|
+
fetchDepositAddress(token, chain) {
|
|
436
|
+
requireSession();
|
|
437
|
+
return marketData.getDepositAddress(token, chain);
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
};
|
|
441
|
+
function requireSession2() {
|
|
442
|
+
const session = sessionStore.getState().session;
|
|
443
|
+
if (!session) throw new Error("Login required");
|
|
444
|
+
return session;
|
|
445
|
+
}
|
|
446
|
+
var createWithdrawController = (custody, marketData) => {
|
|
447
|
+
let status = { phase: "idle" };
|
|
448
|
+
const update = (next, cb) => {
|
|
449
|
+
status = next;
|
|
450
|
+
cb?.(status);
|
|
451
|
+
};
|
|
452
|
+
const open = async (config) => {
|
|
453
|
+
const session = requireSession2();
|
|
454
|
+
const token = config?.defaultToken || getEnv("FUNDING_TOKEN_SYMBOL") || "USDT";
|
|
455
|
+
const chain = config?.defaultChain ?? session.chainContext?.settlementChain ?? session.chain ?? "AB_CORE";
|
|
456
|
+
const targetAddress = config?.targetAddress;
|
|
457
|
+
if (!targetAddress) throw new Error("targetAddress required for withdraw");
|
|
458
|
+
try {
|
|
459
|
+
const { requestId } = await custody.requestWithdraw({
|
|
460
|
+
amount: config?.defaultAmount ?? "0",
|
|
461
|
+
token,
|
|
462
|
+
chain,
|
|
463
|
+
targetAddress
|
|
464
|
+
});
|
|
465
|
+
update({ phase: "requested", requestId }, config?.onStatusChange);
|
|
466
|
+
update({ phase: "processing", requestId }, config?.onStatusChange);
|
|
467
|
+
const { status: finalStatus, txHash } = await custody.getWithdrawStatus(requestId);
|
|
468
|
+
update(
|
|
469
|
+
finalStatus === "SETTLED" ? { phase: "settled", requestId, txHash } : { phase: "failed", reason: finalStatus },
|
|
470
|
+
config?.onStatusChange
|
|
471
|
+
);
|
|
472
|
+
} catch (error) {
|
|
473
|
+
update({ phase: "failed", reason: error.message }, config?.onStatusChange);
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
return {
|
|
477
|
+
get status() {
|
|
478
|
+
return status;
|
|
479
|
+
},
|
|
480
|
+
open,
|
|
481
|
+
fetchTokens() {
|
|
482
|
+
requireSession2();
|
|
483
|
+
return marketData.getSupportedTokens("withdraw");
|
|
484
|
+
},
|
|
485
|
+
fetchChains(token) {
|
|
486
|
+
requireSession2();
|
|
487
|
+
return marketData.getSupportedChains(token, "withdraw");
|
|
488
|
+
},
|
|
489
|
+
fetchQuote(token, chain, amount) {
|
|
490
|
+
requireSession2();
|
|
491
|
+
return marketData.getQuote({ token, chain, amount, direction: "withdraw" });
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
};
|
|
495
|
+
function createClient() {
|
|
496
|
+
const BASE_URL = getEnv("MERCHANT_BASE_URL");
|
|
497
|
+
if (!BASE_URL) {
|
|
498
|
+
throw new Error("MERCHANT_BASE_URL is not set");
|
|
499
|
+
}
|
|
500
|
+
return axios.create({
|
|
501
|
+
baseURL: BASE_URL,
|
|
502
|
+
timeout: 3e4,
|
|
503
|
+
headers: { "Content-Type": "application/json" }
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
function unwrap(res) {
|
|
507
|
+
if (res.code !== 0 || res.data === null) {
|
|
508
|
+
throw new Error(res.msg || "API error");
|
|
509
|
+
}
|
|
510
|
+
return res.data;
|
|
511
|
+
}
|
|
512
|
+
var apiClient = createClient();
|
|
513
|
+
function configureMerchantApi() {
|
|
514
|
+
apiClient = createClient();
|
|
515
|
+
}
|
|
516
|
+
function getMerchantApiClient() {
|
|
517
|
+
return apiClient;
|
|
518
|
+
}
|
|
519
|
+
async function getChains() {
|
|
520
|
+
try {
|
|
521
|
+
const { data } = await apiClient.get("/chains");
|
|
522
|
+
return unwrap(data);
|
|
523
|
+
} catch {
|
|
524
|
+
throw new Error("Failed to get chains");
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
async function registerPlatform(body) {
|
|
528
|
+
try {
|
|
529
|
+
const { data } = await apiClient.post(
|
|
530
|
+
"/api/v1/platform",
|
|
531
|
+
body
|
|
532
|
+
);
|
|
533
|
+
return unwrap(data);
|
|
534
|
+
} catch {
|
|
535
|
+
throw new Error("Failed to register platform");
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
async function quote(body) {
|
|
539
|
+
const { data } = await apiClient.post("/api/v1/quote", body);
|
|
540
|
+
return unwrap(data);
|
|
541
|
+
}
|
|
542
|
+
async function getDepositOrder(orderId) {
|
|
543
|
+
try {
|
|
544
|
+
const { data } = await apiClient.get(
|
|
545
|
+
`/api/v1/orders/deposit/${encodeURIComponent(orderId)}`
|
|
546
|
+
);
|
|
547
|
+
return unwrap(data);
|
|
548
|
+
} catch {
|
|
549
|
+
throw new Error("Failed to get deposit order");
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
async function getWithdrawOrder(orderId) {
|
|
553
|
+
try {
|
|
554
|
+
const { data } = await apiClient.get(
|
|
555
|
+
`/api/v1/orders/withdraw/${encodeURIComponent(orderId)}`
|
|
556
|
+
);
|
|
557
|
+
return unwrap(data);
|
|
558
|
+
} catch {
|
|
559
|
+
throw new Error("Failed to get withdraw order");
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
async function createOrder(body) {
|
|
563
|
+
try {
|
|
564
|
+
const { data } = await apiClient.post("/order", body);
|
|
565
|
+
return unwrap(data);
|
|
566
|
+
} catch {
|
|
567
|
+
throw new Error("Failed to create order");
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// src/modules/marketData.ts
|
|
572
|
+
var cachedChains = null;
|
|
573
|
+
async function fetchChainsFromApi() {
|
|
574
|
+
if (cachedChains) return cachedChains;
|
|
575
|
+
try {
|
|
576
|
+
const { chains } = await getChains();
|
|
577
|
+
if (chains.length > 0) {
|
|
578
|
+
cachedChains = chains;
|
|
579
|
+
return chains;
|
|
580
|
+
}
|
|
581
|
+
return [];
|
|
582
|
+
} catch {
|
|
583
|
+
return [];
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
function chainToChainInfo(chain) {
|
|
587
|
+
return {
|
|
588
|
+
id: chain.chain_id,
|
|
589
|
+
name: chain.network
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
function findTokenInChains(chains, chainId, tokenSymbol) {
|
|
593
|
+
const chain = chains.find((c) => c.chain_id === chainId);
|
|
594
|
+
return chain?.tokens.find((t) => t.symbol === tokenSymbol);
|
|
595
|
+
}
|
|
596
|
+
function formatMinimumDepositDisplay(token, tokenSymbol) {
|
|
597
|
+
const raw = token.minimum_deposit?.trim();
|
|
598
|
+
if (raw == null || raw === "") return void 0;
|
|
599
|
+
try {
|
|
600
|
+
return `${formatUnits(BigInt(raw), token.decimals)} ${tokenSymbol}`;
|
|
601
|
+
} catch {
|
|
602
|
+
return `${raw} ${tokenSymbol}`;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
function deriveTokensFromChains(chains) {
|
|
606
|
+
const bySymbol = /* @__PURE__ */ new Map();
|
|
607
|
+
for (const chain of chains) {
|
|
608
|
+
for (const t of chain.tokens) {
|
|
609
|
+
if (!bySymbol.has(t.symbol)) {
|
|
610
|
+
bySymbol.set(t.symbol, {
|
|
611
|
+
symbol: t.symbol,
|
|
612
|
+
name: t.symbol,
|
|
613
|
+
decimals: t.decimals
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
return Array.from(bySymbol.values());
|
|
619
|
+
}
|
|
620
|
+
function computeDefaultQuote(request) {
|
|
621
|
+
const isStable = ["USDT", "USDC", "USD1"].includes(request.token);
|
|
622
|
+
const slippage = isStable ? "0.3" : "1.0";
|
|
623
|
+
const feeRate = request.direction === "withdraw" ? 1e-3 : 0;
|
|
624
|
+
const amount = Number(request.amount) || 0;
|
|
625
|
+
const fee = (amount * feeRate).toFixed(2);
|
|
626
|
+
const estimatedAmount = (amount - Number(fee)).toFixed(6);
|
|
627
|
+
return {
|
|
628
|
+
quoteId: `quote-${Date.now()}`,
|
|
629
|
+
estimatedAmount: amount > 0 ? estimatedAmount : "0",
|
|
630
|
+
slippage,
|
|
631
|
+
fee,
|
|
632
|
+
feeToken: request.token,
|
|
633
|
+
exchangeRate: "1.0",
|
|
634
|
+
expiresAt: Date.now() + 3e4
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
function createMarketDataProvider() {
|
|
638
|
+
return {
|
|
639
|
+
async getSupportedTokens(_direction) {
|
|
640
|
+
const chains = await fetchChainsFromApi();
|
|
641
|
+
const tokens = deriveTokensFromChains(chains);
|
|
642
|
+
return tokens.length > 0 ? tokens : [];
|
|
643
|
+
},
|
|
644
|
+
async getSupportedChains(token, _direction) {
|
|
645
|
+
const chains = await fetchChainsFromApi();
|
|
646
|
+
const forToken = chains.filter((c) => c.tokens.some((t) => t.symbol === token));
|
|
647
|
+
const list = forToken.length > 0 ? forToken : chains;
|
|
648
|
+
return list.map(chainToChainInfo);
|
|
649
|
+
},
|
|
650
|
+
async getQuote(request) {
|
|
651
|
+
return computeDefaultQuote(request);
|
|
652
|
+
},
|
|
653
|
+
async getDepositAddress(token, chain) {
|
|
654
|
+
const session = sessionStore.getState().session;
|
|
655
|
+
const chains = await fetchChainsFromApi();
|
|
656
|
+
const meta = findTokenInChains(chains, chain, token);
|
|
657
|
+
const minimumDeposit = meta != null ? formatMinimumDepositDisplay(meta, token) : void 0;
|
|
658
|
+
return {
|
|
659
|
+
address: session?.address ?? "",
|
|
660
|
+
minimumDeposit
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// ../wallet-utils/dist/index.js
|
|
667
|
+
var __defProp = Object.defineProperty;
|
|
668
|
+
var __export = (target, all) => {
|
|
669
|
+
for (var name in all)
|
|
670
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
671
|
+
};
|
|
672
|
+
var cache_exports = {};
|
|
673
|
+
__export(cache_exports, {
|
|
674
|
+
clear: () => clear,
|
|
675
|
+
get: () => get,
|
|
676
|
+
remove: () => remove,
|
|
677
|
+
set: () => set,
|
|
678
|
+
setKeyNS: () => setKeyNS
|
|
679
|
+
});
|
|
680
|
+
var keyNS = "tomo-";
|
|
681
|
+
function get(key) {
|
|
682
|
+
if (typeof window === "undefined") {
|
|
683
|
+
return null;
|
|
684
|
+
}
|
|
685
|
+
const tempKey = keyNS + key;
|
|
686
|
+
if (!isKeyExist(tempKey)) {
|
|
687
|
+
return null;
|
|
688
|
+
}
|
|
689
|
+
let val = null;
|
|
690
|
+
try {
|
|
691
|
+
const data = window.localStorage.getItem(tempKey) || window.sessionStorage.getItem(tempKey);
|
|
692
|
+
val = JSON.parse(data);
|
|
693
|
+
} catch (err) {
|
|
694
|
+
console.error(err);
|
|
695
|
+
}
|
|
696
|
+
if (val !== null && Object.prototype.hasOwnProperty.call(val, "type") && Object.prototype.hasOwnProperty.call(val, "data")) {
|
|
697
|
+
return val["data"];
|
|
698
|
+
}
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
701
|
+
function set(key, val, isTemp) {
|
|
702
|
+
if (typeof window === "undefined") {
|
|
703
|
+
return false;
|
|
704
|
+
}
|
|
705
|
+
let store;
|
|
706
|
+
if (isTemp) {
|
|
707
|
+
store = window.sessionStorage;
|
|
708
|
+
} else {
|
|
709
|
+
store = window.localStorage;
|
|
710
|
+
}
|
|
711
|
+
const data = JSON.stringify({
|
|
712
|
+
data: val,
|
|
713
|
+
time: (/* @__PURE__ */ new Date()).getTime(),
|
|
714
|
+
//for manage by time limit
|
|
715
|
+
type: typeof val
|
|
716
|
+
});
|
|
717
|
+
try {
|
|
718
|
+
store.setItem(keyNS + key, data);
|
|
719
|
+
return true;
|
|
720
|
+
} catch (err) {
|
|
721
|
+
if (err?.name?.toUpperCase().indexOf("QUOTA") >= 0) {
|
|
722
|
+
window.localStorage.clear();
|
|
723
|
+
store.setItem(keyNS + key, data);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
function remove(key) {
|
|
729
|
+
if (typeof window === "undefined") {
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
const tempKey = keyNS + key;
|
|
733
|
+
window.localStorage.removeItem(tempKey);
|
|
734
|
+
window.sessionStorage.removeItem(tempKey);
|
|
735
|
+
}
|
|
736
|
+
function clear() {
|
|
737
|
+
if (typeof window === "undefined") {
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
window?.localStorage?.clear();
|
|
741
|
+
window?.sessionStorage?.clear();
|
|
742
|
+
}
|
|
743
|
+
function isKeyExist(key) {
|
|
744
|
+
if (typeof window === "undefined") {
|
|
745
|
+
return false;
|
|
746
|
+
}
|
|
747
|
+
return Object.prototype.hasOwnProperty.call(window.localStorage, key) || Object.prototype.hasOwnProperty.call(window.sessionStorage, key);
|
|
748
|
+
}
|
|
749
|
+
function setKeyNS(NS) {
|
|
750
|
+
const isString = typeof NS === "string";
|
|
751
|
+
if (isString && NS !== "") {
|
|
752
|
+
keyNS = NS;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
function pick2(...candidates) {
|
|
756
|
+
for (const c of candidates) {
|
|
757
|
+
if (c != null && c !== "") return c;
|
|
758
|
+
}
|
|
759
|
+
return void 0;
|
|
760
|
+
}
|
|
761
|
+
function nextPublicProcessEnvKey2(logicalKey) {
|
|
762
|
+
return `NEXT_PUBLIC_${logicalKey}`;
|
|
763
|
+
}
|
|
764
|
+
function readProcessEnvStatic2(key) {
|
|
765
|
+
if (typeof process === "undefined" || !process.env) return void 0;
|
|
766
|
+
switch (key) {
|
|
767
|
+
case "STAGE":
|
|
768
|
+
return pick2(
|
|
769
|
+
process.env.NEXT_PUBLIC_STAGE,
|
|
770
|
+
process.env.STAGE
|
|
771
|
+
);
|
|
772
|
+
case "FUNDING_CHAIN_ID":
|
|
773
|
+
return pick2(
|
|
774
|
+
process.env.NEXT_PUBLIC_FUNDING_CHAIN_ID,
|
|
775
|
+
process.env.FUNDING_CHAIN_ID
|
|
776
|
+
);
|
|
777
|
+
/** Next.js 仅内联「静态」`process.env.NEXT_PUBLIC_*`;动态键名在客户端会为 undefined,必须逐键写出。 */
|
|
778
|
+
case "GOOGLE_CLIENT_ID":
|
|
779
|
+
return pick2(
|
|
780
|
+
process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
|
|
781
|
+
process.env.GOOGLE_CLIENT_ID
|
|
782
|
+
);
|
|
783
|
+
case "X_CLIENT_ID":
|
|
784
|
+
return pick2(
|
|
785
|
+
process.env.NEXT_PUBLIC_X_CLIENT_ID,
|
|
786
|
+
process.env.X_CLIENT_ID
|
|
787
|
+
);
|
|
788
|
+
case "MERCHANT_BASE_URL":
|
|
789
|
+
return pick2(
|
|
790
|
+
process.env.NEXT_PUBLIC_MERCHANT_BASE_URL,
|
|
791
|
+
process.env.MERCHANT_BASE_URL
|
|
792
|
+
);
|
|
793
|
+
case "RELAY_ORIGIN":
|
|
794
|
+
return pick2(
|
|
795
|
+
process.env.NEXT_PUBLIC_RELAY_ORIGIN,
|
|
796
|
+
process.env.RELAY_ORIGIN
|
|
797
|
+
);
|
|
798
|
+
case "CUBE_SIGNER_ENV":
|
|
799
|
+
return pick2(
|
|
800
|
+
process.env.NEXT_PUBLIC_CUBE_SIGNER_ENV,
|
|
801
|
+
process.env.CUBE_SIGNER_ENV
|
|
802
|
+
);
|
|
803
|
+
case "CUBE_SIGNER_ORG_ID":
|
|
804
|
+
return pick2(
|
|
805
|
+
process.env.NEXT_PUBLIC_CUBE_SIGNER_ORG_ID,
|
|
806
|
+
process.env.CUBE_SIGNER_ORG_ID
|
|
807
|
+
);
|
|
808
|
+
case "CUBE_REG":
|
|
809
|
+
return pick2(
|
|
810
|
+
process.env.NEXT_PUBLIC_CUBE_REG,
|
|
811
|
+
process.env.CUBE_REG
|
|
812
|
+
);
|
|
813
|
+
case "FUNDING_TOKEN_SYMBOL":
|
|
814
|
+
return pick2(
|
|
815
|
+
process.env.NEXT_PUBLIC_FUNDING_TOKEN_SYMBOL,
|
|
816
|
+
process.env.FUNDING_TOKEN_SYMBOL
|
|
817
|
+
);
|
|
818
|
+
case "FUNDING_TOKEN_ADDRESS":
|
|
819
|
+
return pick2(
|
|
820
|
+
process.env.NEXT_PUBLIC_FUNDING_TOKEN_ADDRESS,
|
|
821
|
+
process.env.FUNDING_TOKEN_ADDRESS
|
|
822
|
+
);
|
|
823
|
+
default:
|
|
824
|
+
return pick2(
|
|
825
|
+
process.env[`NEXT_PUBLIC_${key}`],
|
|
826
|
+
process.env[key]
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
function getEnv2(key) {
|
|
831
|
+
const staticVal = readProcessEnvStatic2(key);
|
|
832
|
+
if (staticVal != null && staticVal !== "") return staticVal;
|
|
833
|
+
const g = globalThis;
|
|
834
|
+
const env = g.process?.env;
|
|
835
|
+
if (env) {
|
|
836
|
+
const pub = nextPublicProcessEnvKey2(key);
|
|
837
|
+
const v = env[key] ?? env[pub];
|
|
838
|
+
if (v != null && v !== "") return v;
|
|
839
|
+
}
|
|
840
|
+
try {
|
|
841
|
+
const m = import.meta.env;
|
|
842
|
+
if (m) {
|
|
843
|
+
const pub = nextPublicProcessEnvKey2(key);
|
|
844
|
+
const v = m[key] ?? m[pub];
|
|
845
|
+
if (v != null && v !== "") return v;
|
|
846
|
+
}
|
|
847
|
+
} catch {
|
|
848
|
+
}
|
|
849
|
+
console.error(`${key} is not set.`);
|
|
850
|
+
return "";
|
|
851
|
+
}
|
|
852
|
+
var TENDERLY_BSC_3131 = {
|
|
853
|
+
chainId: "3131",
|
|
854
|
+
name: "BSC_TENDERLY",
|
|
855
|
+
chainName: "BSC_TENDERLY",
|
|
856
|
+
nativeCurrencyName: "BSC",
|
|
857
|
+
nativeCurrencySymbol: "BSC",
|
|
858
|
+
nativeCurrencyDecimals: 18,
|
|
859
|
+
rpcUrls: [
|
|
860
|
+
"https://virtual.binance.eu.rpc.tenderly.co/e643ea28-32eb-4fb9-8116-90be24f7defa"
|
|
861
|
+
],
|
|
862
|
+
blockExplorerUrl: "https://dashboard.tenderly.co/explorer/vnet/6593bc72-f548-497d-bff9-5be061436a48",
|
|
863
|
+
platformType: "EVM",
|
|
864
|
+
icon: "https://static.tomo.inc/token/bsc_new.svg",
|
|
865
|
+
// Tenderly 默认资金侧合约地址(测试环境镜像):
|
|
866
|
+
defaultFundingTokenAddress: "0x55d398326f99059fF775485246999027B3197955"
|
|
867
|
+
};
|
|
868
|
+
var BSC_MAINNET_56 = {
|
|
869
|
+
chainId: "56",
|
|
870
|
+
name: "BSC",
|
|
871
|
+
chainName: "BNB Smart Chain",
|
|
872
|
+
nativeCurrencyName: "BNB",
|
|
873
|
+
nativeCurrencySymbol: "BNB",
|
|
874
|
+
nativeCurrencyDecimals: 18,
|
|
875
|
+
rpcUrls: ["https://bsc-dataseed.binance.org", "https://bsc-dataseed1.defibit.io"],
|
|
876
|
+
blockExplorerUrl: "https://bscscan.com",
|
|
877
|
+
platformType: "EVM",
|
|
878
|
+
icon: "https://static.tomo.inc/token/bsc_new.svg",
|
|
879
|
+
// 主网默认资金侧合约地址(USDT);如需覆盖请使用 FUNDING_TOKEN_ADDRESS 环境变量
|
|
880
|
+
defaultFundingTokenAddress: "0x55d398326f99059fF775485246999027B3197955"
|
|
881
|
+
};
|
|
882
|
+
var CHAIN_REGISTRY = {
|
|
883
|
+
[TENDERLY_BSC_3131.chainId]: TENDERLY_BSC_3131,
|
|
884
|
+
[BSC_MAINNET_56.chainId]: BSC_MAINNET_56
|
|
885
|
+
};
|
|
886
|
+
var DEFAULT_FUNDING_CHAIN_ID = getEnv2("FUNDING_CHAIN_ID") || "3131";
|
|
887
|
+
function normalizeFundingChainId(chainId) {
|
|
888
|
+
if (chainId === void 0 || chainId === null) return DEFAULT_FUNDING_CHAIN_ID;
|
|
889
|
+
const s = String(chainId).trim();
|
|
890
|
+
return s === "" ? DEFAULT_FUNDING_CHAIN_ID : s;
|
|
891
|
+
}
|
|
892
|
+
function getChainInfo(chainId) {
|
|
893
|
+
const id = normalizeFundingChainId(chainId);
|
|
894
|
+
const info = CHAIN_REGISTRY[id];
|
|
895
|
+
if (!info) {
|
|
896
|
+
throw new Error(
|
|
897
|
+
`Unsupported funding chainId "${id}". Supported: ${Object.keys(CHAIN_REGISTRY).sort().join(", ")}`
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
return info;
|
|
901
|
+
}
|
|
902
|
+
function pickEnvFundingTokenAddress() {
|
|
903
|
+
const tryPairs = [
|
|
904
|
+
["NEXT_PUBLIC_FUNDING_TOKEN_ADDRESS", "FUNDING_TOKEN_ADDRESS"]
|
|
905
|
+
];
|
|
906
|
+
if (typeof process !== "undefined" && process.env) {
|
|
907
|
+
for (const [pub, priv] of tryPairs) {
|
|
908
|
+
const a = process.env[pub];
|
|
909
|
+
const b = process.env[priv];
|
|
910
|
+
if (a != null && a !== "") return a;
|
|
911
|
+
if (b != null && b !== "") return b;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
try {
|
|
915
|
+
const m = import.meta.env;
|
|
916
|
+
if (m) {
|
|
917
|
+
for (const [pub, priv] of tryPairs) {
|
|
918
|
+
const a = m[pub];
|
|
919
|
+
const b = m[priv];
|
|
920
|
+
if (a != null && a !== "") return a;
|
|
921
|
+
if (b != null && b !== "") return b;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
} catch {
|
|
925
|
+
}
|
|
926
|
+
return void 0;
|
|
927
|
+
}
|
|
928
|
+
function getFundingTokenAddress(chainId) {
|
|
929
|
+
const v = pickEnvFundingTokenAddress();
|
|
930
|
+
if (v && /^0x[0-9a-fA-F]{40}$/.test(v)) return v;
|
|
931
|
+
return getChainInfo(chainId).defaultFundingTokenAddress;
|
|
932
|
+
}
|
|
933
|
+
var DEFAULT_FUNDING_TOKEN_ADDRESS = getFundingTokenAddress(DEFAULT_FUNDING_CHAIN_ID);
|
|
934
|
+
var ClientIds = {
|
|
935
|
+
google: getEnv2("GOOGLE_CLIENT_ID"),
|
|
936
|
+
x: getEnv2("X_CLIENT_ID")
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
// src/modules/balanceQuery.ts
|
|
940
|
+
var ERC20_BALANCE_OF_SELECTOR = "0x70a08231";
|
|
941
|
+
function padAddress(address) {
|
|
942
|
+
return address.toLowerCase().replace("0x", "").padStart(64, "0");
|
|
943
|
+
}
|
|
944
|
+
function formatUnits2(value, decimals) {
|
|
945
|
+
const divisor = 10n ** BigInt(decimals);
|
|
946
|
+
const intPart = value / divisor;
|
|
947
|
+
const fracPart = value % divisor;
|
|
948
|
+
if (fracPart === 0n) return intPart.toString();
|
|
949
|
+
const fracStr = fracPart.toString().padStart(decimals, "0").replace(/0+$/, "");
|
|
950
|
+
return `${intPart}.${fracStr}`;
|
|
951
|
+
}
|
|
952
|
+
function formatBalanceDisplay(value, decimals) {
|
|
953
|
+
const full = formatUnits2(value, decimals);
|
|
954
|
+
const n = Number(full);
|
|
955
|
+
return Number.isNaN(n) ? full : n.toFixed(2);
|
|
956
|
+
}
|
|
957
|
+
async function fetchErc20Balance(rpcUrl, tokenAddress, walletAddress) {
|
|
958
|
+
const data = `${ERC20_BALANCE_OF_SELECTOR}${padAddress(walletAddress)}`;
|
|
959
|
+
const response = await fetch(rpcUrl, {
|
|
960
|
+
method: "POST",
|
|
961
|
+
headers: { "Content-Type": "application/json" },
|
|
962
|
+
body: JSON.stringify({
|
|
963
|
+
jsonrpc: "2.0",
|
|
964
|
+
id: 1,
|
|
965
|
+
method: "eth_call",
|
|
966
|
+
params: [{ to: tokenAddress, data }, "latest"]
|
|
967
|
+
})
|
|
968
|
+
});
|
|
969
|
+
const json = await response.json();
|
|
970
|
+
if (json.error) throw new Error(json.error.message ?? "RPC error");
|
|
971
|
+
return BigInt(json.result ?? "0x0");
|
|
972
|
+
}
|
|
973
|
+
async function fetchFundingTokenBalance(walletAddress, options) {
|
|
974
|
+
const chain = getChainInfo(options?.chainId);
|
|
975
|
+
const rpcUrl = options?.rpcUrl ?? chain.rpcUrls[0];
|
|
976
|
+
const tokenAddress = options?.tokenAddress ?? getFundingTokenAddress(options?.chainId);
|
|
977
|
+
const decimals = options?.decimals ?? chain.nativeCurrencyDecimals;
|
|
978
|
+
const FUNDING_TOKEN_SYMBOL3 = getEnv("FUNDING_TOKEN_SYMBOL");
|
|
979
|
+
const displaySymbol = options?.displaySymbol ?? (FUNDING_TOKEN_SYMBOL3 || "Funding");
|
|
980
|
+
const raw = await fetchErc20Balance(rpcUrl, tokenAddress, walletAddress);
|
|
981
|
+
return {
|
|
982
|
+
raw,
|
|
983
|
+
formatted: formatBalanceDisplay(raw, decimals),
|
|
984
|
+
symbol: displaySymbol
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
var MAX_WITHDRAW_GAS_LIMIT = 500000n;
|
|
988
|
+
var ERC20_TRANSFER_SELECTOR = "0xa9059cbb";
|
|
989
|
+
function padHex256(value) {
|
|
990
|
+
return value.toString(16).padStart(64, "0");
|
|
991
|
+
}
|
|
992
|
+
function padAddress2(address) {
|
|
993
|
+
return address.toLowerCase().replace("0x", "").padStart(64, "0");
|
|
994
|
+
}
|
|
995
|
+
function parseUnits(value, decimals) {
|
|
996
|
+
if (!value || value === "0") return 0n;
|
|
997
|
+
const [intPart = "0", fracPart = ""] = value.split(".");
|
|
998
|
+
const padded = fracPart.padEnd(decimals, "0").slice(0, decimals);
|
|
999
|
+
return BigInt(intPart) * 10n ** BigInt(decimals) + BigInt(padded);
|
|
1000
|
+
}
|
|
1001
|
+
function encodeTransferData(to, amountWei) {
|
|
1002
|
+
return `${ERC20_TRANSFER_SELECTOR}${padAddress2(to)}${padHex256(amountWei)}`;
|
|
1003
|
+
}
|
|
1004
|
+
function isUnsupportedMethodError(error) {
|
|
1005
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1006
|
+
return /unsupported rpc method|unsupported method|method not found|does not support/i.test(
|
|
1007
|
+
message
|
|
1008
|
+
);
|
|
1009
|
+
}
|
|
1010
|
+
function toHexQuantity(value) {
|
|
1011
|
+
if (typeof value === "string") {
|
|
1012
|
+
if (/^0x[0-9a-fA-F]+$/.test(value)) {
|
|
1013
|
+
return value;
|
|
1014
|
+
}
|
|
1015
|
+
if (/^\d+$/.test(value)) {
|
|
1016
|
+
return toHex(BigInt(value));
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
if (typeof value === "number") {
|
|
1020
|
+
return toHex(BigInt(value));
|
|
1021
|
+
}
|
|
1022
|
+
if (typeof value === "bigint") {
|
|
1023
|
+
return toHex(value);
|
|
1024
|
+
}
|
|
1025
|
+
throw new Error(`Invalid EVM quantity: ${String(value)}`);
|
|
1026
|
+
}
|
|
1027
|
+
async function callRpc(rpcUrl, method, params) {
|
|
1028
|
+
const response = await fetch(rpcUrl, {
|
|
1029
|
+
method: "POST",
|
|
1030
|
+
headers: { "Content-Type": "application/json" },
|
|
1031
|
+
body: JSON.stringify({
|
|
1032
|
+
jsonrpc: "2.0",
|
|
1033
|
+
id: Date.now(),
|
|
1034
|
+
method,
|
|
1035
|
+
params
|
|
1036
|
+
})
|
|
1037
|
+
});
|
|
1038
|
+
const json = await response.json();
|
|
1039
|
+
if (!response.ok || json.error) {
|
|
1040
|
+
throw new Error(json.error?.message ?? `${method} failed`);
|
|
1041
|
+
}
|
|
1042
|
+
return json.result;
|
|
1043
|
+
}
|
|
1044
|
+
async function requestHexQuantity(provider, rpcUrl, method, params) {
|
|
1045
|
+
try {
|
|
1046
|
+
const result = await provider.request({ method, params });
|
|
1047
|
+
return toHexQuantity(result);
|
|
1048
|
+
} catch (error) {
|
|
1049
|
+
if (!isUnsupportedMethodError(error)) {
|
|
1050
|
+
throw error;
|
|
1051
|
+
}
|
|
1052
|
+
return toHexQuantity(await callRpc(rpcUrl, method, params));
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
async function ensureFundingEvmChain(provider, chainId) {
|
|
1056
|
+
const hex = `0x${chainId.toString(16)}`;
|
|
1057
|
+
try {
|
|
1058
|
+
await provider.request({ method: "wallet_switchEthereumChain", params: [{ chainId: hex }] });
|
|
1059
|
+
} catch {
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
function getDstTokenAddress(chains, chainId, tokenSymbol) {
|
|
1063
|
+
const chain = chains.find((c) => c.chain_id === chainId);
|
|
1064
|
+
return chain?.tokens.find((t) => t.symbol === tokenSymbol)?.address;
|
|
1065
|
+
}
|
|
1066
|
+
function createFundingWithdrawExecutor(options) {
|
|
1067
|
+
const fundingChain = getChainInfo(options?.chainId);
|
|
1068
|
+
const chainIdNum = Number(fundingChain.chainId);
|
|
1069
|
+
const rpcUrl = options?.rpcUrl ?? fundingChain.rpcUrls[0];
|
|
1070
|
+
const tokenAddress = options?.tokenAddress ?? getFundingTokenAddress(options?.chainId);
|
|
1071
|
+
const decimals = options?.decimals ?? fundingChain.nativeCurrencyDecimals;
|
|
1072
|
+
const maxAmountWei = options?.maxAmountWei;
|
|
1073
|
+
const fundingLegTokenSymbol = options?.fundingLegTokenSymbol || getEnv("FUNDING_TOKEN_SYMBOL") || "USDT";
|
|
1074
|
+
return async (request) => {
|
|
1075
|
+
const amountWei = parseUnits(request.amount, decimals);
|
|
1076
|
+
const amountWeiStr = amountWei.toString();
|
|
1077
|
+
if (maxAmountWei != null && amountWei > BigInt(maxAmountWei)) {
|
|
1078
|
+
throw new Error("Withdraw amount exceeds the single-transaction limit");
|
|
1079
|
+
}
|
|
1080
|
+
let session = sessionStore.getState().session;
|
|
1081
|
+
if (!session) throw new Error("Login required");
|
|
1082
|
+
let { provider } = session;
|
|
1083
|
+
try {
|
|
1084
|
+
await provider.request({ method: "eth_chainId", params: [] });
|
|
1085
|
+
} catch (err) {
|
|
1086
|
+
const msg = err.message ?? "";
|
|
1087
|
+
if (msg.includes("restored from cache") || msg.includes("Reconnect your wallet")) {
|
|
1088
|
+
const reconnected = await tryAutoReconnect();
|
|
1089
|
+
if (reconnected) {
|
|
1090
|
+
session = reconnected;
|
|
1091
|
+
provider = reconnected.provider;
|
|
1092
|
+
} else {
|
|
1093
|
+
sessionStore.clearSession();
|
|
1094
|
+
throw new Error("Session expired. Please sign in again.");
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
const chainsRes = await getChains();
|
|
1099
|
+
const chains = chainsRes?.chains ?? [];
|
|
1100
|
+
const dstTokenAddress = getDstTokenAddress(chains, request.chain, request.token);
|
|
1101
|
+
if (!dstTokenAddress) {
|
|
1102
|
+
throw new Error(`Unsupported token ${request.token} on chain ${request.chain}`);
|
|
1103
|
+
}
|
|
1104
|
+
const sourceTokenSymbol = fundingLegTokenSymbol;
|
|
1105
|
+
const orderRes = await createOrder({
|
|
1106
|
+
intent_id: `withdraw-${Date.now()}`,
|
|
1107
|
+
order_type: "NATIVE_SWAP",
|
|
1108
|
+
order_payload: {
|
|
1109
|
+
chain_id: fundingChain.chainId,
|
|
1110
|
+
token_address: tokenAddress,
|
|
1111
|
+
token_amount: amountWeiStr,
|
|
1112
|
+
dst_chain_id: request.chain,
|
|
1113
|
+
dst_token_address: dstTokenAddress,
|
|
1114
|
+
recipient: request.toAddress
|
|
1115
|
+
},
|
|
1116
|
+
payment_pairs: [
|
|
1117
|
+
{
|
|
1118
|
+
token_symbol: sourceTokenSymbol,
|
|
1119
|
+
token_amount: amountWeiStr,
|
|
1120
|
+
token_address: tokenAddress,
|
|
1121
|
+
user_address: session.address,
|
|
1122
|
+
chain_id: fundingChain.chainId
|
|
1123
|
+
}
|
|
1124
|
+
]
|
|
1125
|
+
});
|
|
1126
|
+
const oneTimeAddress = orderRes.payment_sessions?.[0]?.one_time_wallet_address;
|
|
1127
|
+
if (!oneTimeAddress) {
|
|
1128
|
+
throw new Error("Order created but no one-time wallet address returned");
|
|
1129
|
+
}
|
|
1130
|
+
await ensureFundingEvmChain(provider, chainIdNum);
|
|
1131
|
+
const data = encodeTransferData(oneTimeAddress, amountWei);
|
|
1132
|
+
const nonce = await requestHexQuantity(
|
|
1133
|
+
provider,
|
|
1134
|
+
rpcUrl,
|
|
1135
|
+
"eth_getTransactionCount",
|
|
1136
|
+
[session.address, "latest"]
|
|
1137
|
+
);
|
|
1138
|
+
const tx = {
|
|
1139
|
+
from: session.address,
|
|
1140
|
+
to: tokenAddress,
|
|
1141
|
+
value: "0x0",
|
|
1142
|
+
nonce,
|
|
1143
|
+
data,
|
|
1144
|
+
chainId: toHex(chainIdNum)
|
|
1145
|
+
};
|
|
1146
|
+
const estimatedGasHex = await requestHexQuantity(
|
|
1147
|
+
provider,
|
|
1148
|
+
rpcUrl,
|
|
1149
|
+
"eth_estimateGas",
|
|
1150
|
+
[tx]
|
|
1151
|
+
);
|
|
1152
|
+
const estimatedGas = fromHex(estimatedGasHex, "bigint");
|
|
1153
|
+
const gas = toHex(
|
|
1154
|
+
estimatedGas > MAX_WITHDRAW_GAS_LIMIT ? MAX_WITHDRAW_GAS_LIMIT : estimatedGas
|
|
1155
|
+
);
|
|
1156
|
+
const transaction = {
|
|
1157
|
+
...tx,
|
|
1158
|
+
gas,
|
|
1159
|
+
maxFeePerGas: toHex(parseGwei("5")),
|
|
1160
|
+
maxPriorityFeePerGas: toHex(parseGwei("1"))
|
|
1161
|
+
};
|
|
1162
|
+
let txHash;
|
|
1163
|
+
try {
|
|
1164
|
+
txHash = await provider.request({
|
|
1165
|
+
method: "eth_sendTransaction",
|
|
1166
|
+
params: [transaction]
|
|
1167
|
+
});
|
|
1168
|
+
} catch (error) {
|
|
1169
|
+
if (!isUnsupportedMethodError(error)) {
|
|
1170
|
+
throw error;
|
|
1171
|
+
}
|
|
1172
|
+
const signedTx = await provider.request({
|
|
1173
|
+
method: "eth_signTransaction",
|
|
1174
|
+
params: [transaction]
|
|
1175
|
+
});
|
|
1176
|
+
txHash = await callRpc(rpcUrl, "eth_sendRawTransaction", [signedTx]);
|
|
1177
|
+
}
|
|
1178
|
+
return { txHash, orderId: orderRes.order_id, fundingChainId: fundingChain.chainId };
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
// src/modules/withdrawDirect.ts
|
|
1183
|
+
function isUsdtWithdrawDirect(chainId, tokenAddress, chains) {
|
|
1184
|
+
if (chainId !== String(DEFAULT_FUNDING_CHAIN_ID)) return false;
|
|
1185
|
+
const addr = tokenAddress.trim();
|
|
1186
|
+
if (!addr) return false;
|
|
1187
|
+
const chain = chains.find((c) => c.chain_id === chainId);
|
|
1188
|
+
const token = chain?.tokens.find((t) => t.address.toLowerCase() === addr.toLowerCase());
|
|
1189
|
+
return token?.is_usd_stable === true;
|
|
1190
|
+
}
|
|
1191
|
+
function findTokenDataFromChains(chains, chainId, opts) {
|
|
1192
|
+
const chain = chains.find((c) => c.chain_id === chainId);
|
|
1193
|
+
if (!chain?.tokens.length) return void 0;
|
|
1194
|
+
const sym = opts.symbol.trim();
|
|
1195
|
+
const addr = opts.tokenAddress?.trim().toLowerCase();
|
|
1196
|
+
return chain.tokens.find((t) => {
|
|
1197
|
+
if (addr && t.address.toLowerCase() === addr) return true;
|
|
1198
|
+
if (sym.length > 0 && t.symbol === sym) return true;
|
|
1199
|
+
return false;
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
var createPolicy = (overrides, options) => createSessionCapabilityPolicy({
|
|
1203
|
+
appId: options?.appId,
|
|
1204
|
+
origin: options?.origin,
|
|
1205
|
+
expiresAt: options?.expiresAt,
|
|
1206
|
+
...overrides
|
|
1207
|
+
});
|
|
1208
|
+
var withActionMetadata = (action, policy) => ({
|
|
1209
|
+
...policy,
|
|
1210
|
+
metadata: {
|
|
1211
|
+
...policy.metadata ?? {},
|
|
1212
|
+
action
|
|
1213
|
+
}
|
|
1214
|
+
});
|
|
1215
|
+
var createPredicateMarketPolicyAdapter = (options) => ({
|
|
1216
|
+
deposit(token, chain, maxAmount) {
|
|
1217
|
+
return withActionMetadata(
|
|
1218
|
+
"deposit",
|
|
1219
|
+
createPolicy(
|
|
1220
|
+
{
|
|
1221
|
+
methods: ["eth_sendTransaction"],
|
|
1222
|
+
chains: [chain],
|
|
1223
|
+
tokens: [token],
|
|
1224
|
+
maxAmount
|
|
1225
|
+
},
|
|
1226
|
+
options
|
|
1227
|
+
)
|
|
1228
|
+
);
|
|
1229
|
+
},
|
|
1230
|
+
withdraw(token, chain, maxAmount) {
|
|
1231
|
+
return withActionMetadata(
|
|
1232
|
+
"withdraw",
|
|
1233
|
+
createPolicy(
|
|
1234
|
+
{
|
|
1235
|
+
methods: ["eth_sendTransaction"],
|
|
1236
|
+
chains: [chain],
|
|
1237
|
+
tokens: [token],
|
|
1238
|
+
maxAmount
|
|
1239
|
+
},
|
|
1240
|
+
options
|
|
1241
|
+
)
|
|
1242
|
+
);
|
|
1243
|
+
},
|
|
1244
|
+
trade(chain, capabilities = ["eth_sendTransaction"]) {
|
|
1245
|
+
return withActionMetadata(
|
|
1246
|
+
"trade",
|
|
1247
|
+
createPolicy(
|
|
1248
|
+
{
|
|
1249
|
+
methods: capabilities,
|
|
1250
|
+
chains: [chain]
|
|
1251
|
+
},
|
|
1252
|
+
options
|
|
1253
|
+
)
|
|
1254
|
+
);
|
|
1255
|
+
}
|
|
1256
|
+
});
|
|
1257
|
+
var cubistCapabilities = [
|
|
1258
|
+
"eth_accounts",
|
|
1259
|
+
"eth_requestAccounts",
|
|
1260
|
+
"eth_chainId",
|
|
1261
|
+
"eth_signTransaction",
|
|
1262
|
+
"personal_sign",
|
|
1263
|
+
"eth_signTypedData_v4",
|
|
1264
|
+
"wallet_disconnect"
|
|
1265
|
+
];
|
|
1266
|
+
var evmChainIdMap = {
|
|
1267
|
+
ETH: 1,
|
|
1268
|
+
BSC: 56
|
|
1269
|
+
};
|
|
1270
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1271
|
+
var toBigIntQuantity = (value) => {
|
|
1272
|
+
if (typeof value === "bigint") return value;
|
|
1273
|
+
if (typeof value === "number") {
|
|
1274
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
1275
|
+
throw new Error(`Invalid EVM quantity number: ${value}`);
|
|
1276
|
+
}
|
|
1277
|
+
return BigInt(value);
|
|
1278
|
+
}
|
|
1279
|
+
const trimmed = value.trim();
|
|
1280
|
+
if (!trimmed) {
|
|
1281
|
+
throw new Error("EVM quantity cannot be empty");
|
|
1282
|
+
}
|
|
1283
|
+
if (/^0x[0-9a-fA-F]+$/.test(trimmed) || /^\d+$/.test(trimmed)) {
|
|
1284
|
+
return BigInt(trimmed);
|
|
1285
|
+
}
|
|
1286
|
+
throw new Error(`Invalid EVM quantity string: ${value}`);
|
|
1287
|
+
};
|
|
1288
|
+
var toHexQuantity2 = (value) => {
|
|
1289
|
+
if (value === void 0) return void 0;
|
|
1290
|
+
return `0x${toBigIntQuantity(value).toString(16)}`;
|
|
1291
|
+
};
|
|
1292
|
+
var normalizeAccessList = (accessList) => {
|
|
1293
|
+
if (!accessList) return void 0;
|
|
1294
|
+
return accessList.map((item) => ({
|
|
1295
|
+
address: item.address,
|
|
1296
|
+
storageKeys: item.storageKeys
|
|
1297
|
+
}));
|
|
1298
|
+
};
|
|
1299
|
+
var textEncoder = new TextEncoder();
|
|
1300
|
+
var resolveTransactionType = (transaction) => {
|
|
1301
|
+
if (transaction.type !== void 0) {
|
|
1302
|
+
const normalized = toHexQuantity2(transaction.type);
|
|
1303
|
+
if (normalized === "0x0" || normalized === "0x1" || normalized === "0x2") {
|
|
1304
|
+
return normalized;
|
|
1305
|
+
}
|
|
1306
|
+
throw new Error(`Unsupported EVM transaction type for Cubist: ${normalized}`);
|
|
1307
|
+
}
|
|
1308
|
+
if (transaction.maxFeePerGas !== void 0 || transaction.maxPriorityFeePerGas !== void 0) {
|
|
1309
|
+
return "0x2";
|
|
1310
|
+
}
|
|
1311
|
+
if (transaction.accessList?.length) {
|
|
1312
|
+
return "0x1";
|
|
1313
|
+
}
|
|
1314
|
+
return "0x0";
|
|
1315
|
+
};
|
|
1316
|
+
var toCubistSignRequest = (address, chain, transaction) => {
|
|
1317
|
+
const resolvedChainId = (transaction.chainId !== void 0 ? Number(toBigIntQuantity(transaction.chainId)) : void 0) ?? evmChainIdMap[chain];
|
|
1318
|
+
if (!resolvedChainId) {
|
|
1319
|
+
throw new Error("Cubist signing requires an EVM chainId");
|
|
1320
|
+
}
|
|
1321
|
+
const type = resolveTransactionType(transaction);
|
|
1322
|
+
const commonFields = {
|
|
1323
|
+
from: transaction.from ?? address,
|
|
1324
|
+
to: transaction.to,
|
|
1325
|
+
data: transaction.data,
|
|
1326
|
+
gas: toHexQuantity2(transaction.gas),
|
|
1327
|
+
nonce: toHexQuantity2(transaction.nonce),
|
|
1328
|
+
value: toHexQuantity2(transaction.value)
|
|
1329
|
+
};
|
|
1330
|
+
const accessList = normalizeAccessList(transaction.accessList);
|
|
1331
|
+
const tx = type === "0x2" ? {
|
|
1332
|
+
...commonFields,
|
|
1333
|
+
type,
|
|
1334
|
+
...accessList ? { accessList } : {},
|
|
1335
|
+
maxFeePerGas: toHexQuantity2(transaction.maxFeePerGas),
|
|
1336
|
+
maxPriorityFeePerGas: toHexQuantity2(transaction.maxPriorityFeePerGas)
|
|
1337
|
+
} : type === "0x1" ? {
|
|
1338
|
+
...commonFields,
|
|
1339
|
+
type,
|
|
1340
|
+
...accessList ? { accessList } : {},
|
|
1341
|
+
gasPrice: toHexQuantity2(transaction.gasPrice)
|
|
1342
|
+
} : {
|
|
1343
|
+
...commonFields,
|
|
1344
|
+
type,
|
|
1345
|
+
gasPrice: toHexQuantity2(transaction.gasPrice)
|
|
1346
|
+
};
|
|
1347
|
+
return {
|
|
1348
|
+
chain_id: resolvedChainId,
|
|
1349
|
+
tx
|
|
1350
|
+
};
|
|
1351
|
+
};
|
|
1352
|
+
var getTransactionParam = (params) => {
|
|
1353
|
+
const candidate = params?.[0];
|
|
1354
|
+
if (!isRecord(candidate)) {
|
|
1355
|
+
throw new Error("eth_signTransaction requires a transaction object");
|
|
1356
|
+
}
|
|
1357
|
+
return candidate;
|
|
1358
|
+
};
|
|
1359
|
+
var toHexBytes = (value) => {
|
|
1360
|
+
if (/^0x[0-9a-fA-F]*$/.test(value)) return value;
|
|
1361
|
+
return `0x${Array.from(textEncoder.encode(value)).map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
1362
|
+
};
|
|
1363
|
+
var getMessageParam = (address, params) => {
|
|
1364
|
+
const [first, second] = params ?? [];
|
|
1365
|
+
if (typeof second === "string" && second.toLowerCase() === address.toLowerCase()) {
|
|
1366
|
+
return String(first ?? "");
|
|
1367
|
+
}
|
|
1368
|
+
if (typeof first === "string" && first.toLowerCase() === address.toLowerCase()) {
|
|
1369
|
+
return String(second ?? "");
|
|
1370
|
+
}
|
|
1371
|
+
return String(first ?? "");
|
|
1372
|
+
};
|
|
1373
|
+
var getTypedDataParam = (address, params) => {
|
|
1374
|
+
const [first, second] = params ?? [];
|
|
1375
|
+
if (typeof first === "string" && first.toLowerCase() === address.toLowerCase()) {
|
|
1376
|
+
return typeof second === "string" ? JSON.parse(second) : second ?? {};
|
|
1377
|
+
}
|
|
1378
|
+
return typeof second === "string" ? JSON.parse(second) : second ?? first ?? {};
|
|
1379
|
+
};
|
|
1380
|
+
function createEmbeddedProvider({
|
|
1381
|
+
session,
|
|
1382
|
+
address,
|
|
1383
|
+
chain
|
|
1384
|
+
}) {
|
|
1385
|
+
const signer = new EvmSigner(address, session.client);
|
|
1386
|
+
return {
|
|
1387
|
+
async request(payload) {
|
|
1388
|
+
switch (payload.method) {
|
|
1389
|
+
case "eth_accounts":
|
|
1390
|
+
case "eth_requestAccounts":
|
|
1391
|
+
return [address];
|
|
1392
|
+
case "eth_chainId": {
|
|
1393
|
+
const chainId = evmChainIdMap[chain];
|
|
1394
|
+
return `0x${chainId.toString(16)}`;
|
|
1395
|
+
}
|
|
1396
|
+
case "eth_signTransaction": {
|
|
1397
|
+
const transaction = getTransactionParam(payload.params);
|
|
1398
|
+
const signRequest = toCubistSignRequest(address, chain, transaction);
|
|
1399
|
+
return await signer.signTransaction(signRequest);
|
|
1400
|
+
}
|
|
1401
|
+
case "personal_sign": {
|
|
1402
|
+
const message = getMessageParam(address, payload.params);
|
|
1403
|
+
return await signer.signEip191({ data: toHexBytes(message) });
|
|
1404
|
+
}
|
|
1405
|
+
case "eth_signTypedData_v4": {
|
|
1406
|
+
const typedData = getTypedDataParam(address, payload.params);
|
|
1407
|
+
const domain = typedData.domain;
|
|
1408
|
+
const chainId = domain?.chainId !== void 0 ? Number(toBigIntQuantity(domain.chainId)) : evmChainIdMap[chain];
|
|
1409
|
+
if (!chainId) {
|
|
1410
|
+
throw new Error("CubistProvider: typed data signing requires an EVM chainId");
|
|
1411
|
+
}
|
|
1412
|
+
return await signer.signEip712({
|
|
1413
|
+
chain_id: chainId,
|
|
1414
|
+
typed_data: typedData
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1417
|
+
default:
|
|
1418
|
+
throw new Error(`CubistProvider: unsupported RPC method "${payload.method}"`);
|
|
1419
|
+
}
|
|
1420
|
+
},
|
|
1421
|
+
async disconnect() {
|
|
1422
|
+
await session.client.revokeSession();
|
|
1423
|
+
}
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
var EmbeddedWalletAccountProvider = class {
|
|
1427
|
+
constructor(provider) {
|
|
1428
|
+
this.provider = provider;
|
|
1429
|
+
}
|
|
1430
|
+
async request(payload) {
|
|
1431
|
+
return this.provider.request(payload);
|
|
1432
|
+
}
|
|
1433
|
+
async disconnect() {
|
|
1434
|
+
await this.provider.disconnect();
|
|
1435
|
+
}
|
|
1436
|
+
async eth_accounts() {
|
|
1437
|
+
return this.request({ method: "eth_accounts" });
|
|
1438
|
+
}
|
|
1439
|
+
async eth_chainId() {
|
|
1440
|
+
return this.request({ method: "eth_chainId" });
|
|
1441
|
+
}
|
|
1442
|
+
};
|
|
1443
|
+
var _WalletAccount = class _WalletAccount {
|
|
1444
|
+
static clearInstance() {
|
|
1445
|
+
_WalletAccount.instance = null;
|
|
1446
|
+
_WalletAccount.instanceToken = null;
|
|
1447
|
+
_WalletAccount.walletSession = null;
|
|
1448
|
+
_WalletAccount.cubeSignerSession = null;
|
|
1449
|
+
}
|
|
1450
|
+
static getWalletSession() {
|
|
1451
|
+
return _WalletAccount.walletSession;
|
|
1452
|
+
}
|
|
1453
|
+
static getCubeSignerSession() {
|
|
1454
|
+
return _WalletAccount.cubeSignerSession;
|
|
1455
|
+
}
|
|
1456
|
+
static async getInstance(oidcToken, authSource, cubeSignerConfig) {
|
|
1457
|
+
if (_WalletAccount.instance && _WalletAccount.instanceToken === oidcToken) {
|
|
1458
|
+
return _WalletAccount.instance;
|
|
1459
|
+
}
|
|
1460
|
+
_WalletAccount.clearInstance();
|
|
1461
|
+
const auth = new CubeSignerAuth(cubeSignerConfig);
|
|
1462
|
+
const cubeSignerSession = await auth.loginWithGoogle(oidcToken);
|
|
1463
|
+
const keys = await cubeSignerSession.client.sessionKeys();
|
|
1464
|
+
const evmKey = keys.find((key) => key.cached.key_type === "SecpEthAddr");
|
|
1465
|
+
if (!evmKey) {
|
|
1466
|
+
throw new Error("No EVM key found in CubeSigner session");
|
|
1467
|
+
}
|
|
1468
|
+
const address = evmKey.materialId;
|
|
1469
|
+
const chain = "BSC";
|
|
1470
|
+
const provider = createEmbeddedProvider({
|
|
1471
|
+
session: cubeSignerSession,
|
|
1472
|
+
address,
|
|
1473
|
+
chain
|
|
1474
|
+
});
|
|
1475
|
+
const wrappedProvider = new EmbeddedWalletAccountProvider(provider);
|
|
1476
|
+
const capabilityPolicy = auth.defaultSessionPolicy ? createSessionCapabilityPolicy(auth.defaultSessionPolicy) : void 0;
|
|
1477
|
+
_WalletAccount.instance = wrappedProvider;
|
|
1478
|
+
_WalletAccount.instanceToken = oidcToken;
|
|
1479
|
+
_WalletAccount.cubeSignerSession = cubeSignerSession;
|
|
1480
|
+
_WalletAccount.walletSession = {
|
|
1481
|
+
address,
|
|
1482
|
+
chain,
|
|
1483
|
+
provider: wrappedProvider,
|
|
1484
|
+
walletType: "social",
|
|
1485
|
+
authSource,
|
|
1486
|
+
sessionId: `${authSource}:${address.toLowerCase()}`,
|
|
1487
|
+
expiresAt: capabilityPolicy?.expiresAt,
|
|
1488
|
+
capabilities: [...cubistCapabilities],
|
|
1489
|
+
sessionData: cubeSignerSession.sessionData,
|
|
1490
|
+
chainContext: createChainContext(chain),
|
|
1491
|
+
capabilityPolicy
|
|
1492
|
+
};
|
|
1493
|
+
return wrappedProvider;
|
|
1494
|
+
}
|
|
1495
|
+
};
|
|
1496
|
+
_WalletAccount.instance = null;
|
|
1497
|
+
_WalletAccount.instanceToken = null;
|
|
1498
|
+
_WalletAccount.walletSession = null;
|
|
1499
|
+
_WalletAccount.cubeSignerSession = null;
|
|
1500
|
+
var WalletAccount = _WalletAccount;
|
|
1501
|
+
function clearSocialAccountInstance() {
|
|
1502
|
+
WalletAccount.clearInstance();
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
// src/ui/theme.ts
|
|
1506
|
+
var colors = {
|
|
1507
|
+
background: "#050608",
|
|
1508
|
+
card: "#121214",
|
|
1509
|
+
cardRaised: "#151821",
|
|
1510
|
+
border: "rgba(126,135,162,0.2)",
|
|
1511
|
+
borderStrong: "rgba(255,255,255,0.16)",
|
|
1512
|
+
borderFocused: "#FFFFFF",
|
|
1513
|
+
textPrimary: "#FFFFFF",
|
|
1514
|
+
textSecondary: "#737477",
|
|
1515
|
+
accent: "#29FF9B",
|
|
1516
|
+
accentStrong: "#4AD481",
|
|
1517
|
+
warning: "#FFB547",
|
|
1518
|
+
danger: "#FF6B6B",
|
|
1519
|
+
stepActive: "#FFFFFF",
|
|
1520
|
+
stepInactive: "#36383D",
|
|
1521
|
+
buttonDisabledBg: "rgba(255,255,255,0.14)",
|
|
1522
|
+
buttonDisabledBorder: "#444444"
|
|
1523
|
+
};
|
|
1524
|
+
var radii = {
|
|
1525
|
+
xl: "28px",
|
|
1526
|
+
lg: "20px",
|
|
1527
|
+
pill: "99px",
|
|
1528
|
+
full: "9999px",
|
|
1529
|
+
card: "12px",
|
|
1530
|
+
input: "8px"
|
|
1531
|
+
};
|
|
1532
|
+
var fonts = {
|
|
1533
|
+
family: '"Switzer", "Inter", "SF Pro Display", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'
|
|
1534
|
+
};
|
|
1535
|
+
var GoogleIcon = () => /* @__PURE__ */ jsxs("svg", { width: "21", height: "21", viewBox: "0 0 21 21", fill: "none", children: [
|
|
1536
|
+
/* @__PURE__ */ jsx("path", { d: "M20.3 10.73c0-.79-.07-1.54-.19-2.27H10.5v4.51h5.5a4.69 4.69 0 0 1-2.04 3.09v2.57h3.3c1.93-1.78 3.04-4.4 3.04-7.9Z", fill: "#4285F4" }),
|
|
1537
|
+
/* @__PURE__ */ jsx("path", { d: "M10.5 21c2.76 0 5.07-.91 6.76-2.47l-3.3-2.57c-.92.61-2.09.97-3.46.97-2.66 0-4.91-1.8-5.71-4.22H1.39v2.65A10.5 10.5 0 0 0 10.5 21Z", fill: "#34A853" }),
|
|
1538
|
+
/* @__PURE__ */ jsx("path", { d: "M4.79 12.71A6.3 6.3 0 0 1 4.46 10.5c0-.77.13-1.51.33-2.21V5.64H1.39A10.5 10.5 0 0 0 0 10.5c0 1.7.41 3.3 1.39 4.86l3.4-2.65Z", fill: "#FBBC05" }),
|
|
1539
|
+
/* @__PURE__ */ jsx("path", { d: "M10.5 4.07c1.5 0 2.84.51 3.9 1.52l2.92-2.92C15.56 1.02 13.26 0 10.5 0A10.5 10.5 0 0 0 1.39 5.64l3.4 2.65C5.59 5.87 7.84 4.07 10.5 4.07Z", fill: "#EA4335" })
|
|
1540
|
+
] });
|
|
1541
|
+
var XIcon = () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231 5.45-6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117L17.083 19.77Z", fill: "white" }) });
|
|
1542
|
+
var ExpandIcon = ({ expanded }) => /* @__PURE__ */ jsxs(
|
|
1543
|
+
"svg",
|
|
1544
|
+
{
|
|
1545
|
+
width: "24",
|
|
1546
|
+
height: "24",
|
|
1547
|
+
viewBox: "0 0 24 24",
|
|
1548
|
+
fill: "none",
|
|
1549
|
+
style: { transform: expanded ? "rotate(180deg)" : void 0, transition: "transform 0.2s" },
|
|
1550
|
+
children: [
|
|
1551
|
+
/* @__PURE__ */ jsx("path", { d: "M5 9L9 13L13 9", stroke: colors.textSecondary, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
1552
|
+
/* @__PURE__ */ jsx("path", { d: "M11 9L15 13L19 9", stroke: colors.textSecondary, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
1553
|
+
]
|
|
1554
|
+
}
|
|
1555
|
+
);
|
|
1556
|
+
var SpinnerIcon = () => /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", style: { animation: "spin 1s linear infinite" }, children: [
|
|
1557
|
+
/* @__PURE__ */ jsx("circle", { cx: "10", cy: "10", r: "8", stroke: "rgba(255,255,255,0.2)", strokeWidth: "2.5" }),
|
|
1558
|
+
/* @__PURE__ */ jsx("path", { d: "M10 2a8 8 0 0 1 8 8", stroke: colors.textPrimary, strokeWidth: "2.5", strokeLinecap: "round" }),
|
|
1559
|
+
/* @__PURE__ */ jsx("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
1560
|
+
] });
|
|
1561
|
+
var defaultSocialProviders = [
|
|
1562
|
+
{ id: "google", label: "Continue with Google", icon: /* @__PURE__ */ jsx(GoogleIcon, {}) },
|
|
1563
|
+
{ id: "x", label: "Continue with X", icon: /* @__PURE__ */ jsx(XIcon, {}) }
|
|
1564
|
+
];
|
|
1565
|
+
function resolveWalletItems(wallets, defaultWalletRegistry) {
|
|
1566
|
+
const walletMap = new Map(
|
|
1567
|
+
defaultWalletRegistry.map((item) => [
|
|
1568
|
+
item.id,
|
|
1569
|
+
{
|
|
1570
|
+
name: item.title,
|
|
1571
|
+
installed: item.installed,
|
|
1572
|
+
installUrl: item.installUrl
|
|
1573
|
+
}
|
|
1574
|
+
])
|
|
1575
|
+
);
|
|
1576
|
+
if (wallets === void 0) {
|
|
1577
|
+
return defaultWalletRegistry.map((item) => ({
|
|
1578
|
+
id: item.id,
|
|
1579
|
+
name: item.title,
|
|
1580
|
+
icon: void 0,
|
|
1581
|
+
installed: item.installed,
|
|
1582
|
+
installUrl: item.installUrl
|
|
1583
|
+
}));
|
|
1584
|
+
}
|
|
1585
|
+
if (wallets.length === 0) {
|
|
1586
|
+
return [];
|
|
1587
|
+
}
|
|
1588
|
+
return wallets.map((wallet) => {
|
|
1589
|
+
const fallback = walletMap.get(wallet.id);
|
|
1590
|
+
return {
|
|
1591
|
+
...wallet,
|
|
1592
|
+
name: wallet.name ?? fallback?.name ?? wallet.id,
|
|
1593
|
+
installed: wallet.installed ?? fallback?.installed,
|
|
1594
|
+
installUrl: wallet.installUrl ?? fallback?.installUrl
|
|
1595
|
+
};
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
function resolveSocialProviders(socialProviders) {
|
|
1599
|
+
if (socialProviders === void 0) {
|
|
1600
|
+
return defaultSocialProviders;
|
|
1601
|
+
}
|
|
1602
|
+
if (socialProviders.length === 0) {
|
|
1603
|
+
return [];
|
|
1604
|
+
}
|
|
1605
|
+
const defaultProviderMap = new Map(
|
|
1606
|
+
defaultSocialProviders.map((provider) => [provider.id, provider])
|
|
1607
|
+
);
|
|
1608
|
+
return socialProviders.map((provider) => {
|
|
1609
|
+
const fallback = defaultProviderMap.get(provider.id);
|
|
1610
|
+
return {
|
|
1611
|
+
...provider,
|
|
1612
|
+
label: provider.label ?? fallback?.label ?? provider.id,
|
|
1613
|
+
icon: provider.icon ?? fallback?.icon
|
|
1614
|
+
};
|
|
1615
|
+
});
|
|
1616
|
+
}
|
|
1617
|
+
var IconFrame = ({
|
|
1618
|
+
background,
|
|
1619
|
+
children
|
|
1620
|
+
}) => /* @__PURE__ */ jsx(
|
|
1621
|
+
"div",
|
|
1622
|
+
{
|
|
1623
|
+
style: {
|
|
1624
|
+
width: 48,
|
|
1625
|
+
height: 48,
|
|
1626
|
+
borderRadius: 12,
|
|
1627
|
+
background,
|
|
1628
|
+
display: "flex",
|
|
1629
|
+
alignItems: "center",
|
|
1630
|
+
justifyContent: "center",
|
|
1631
|
+
overflow: "hidden"
|
|
1632
|
+
},
|
|
1633
|
+
children
|
|
1634
|
+
}
|
|
1635
|
+
);
|
|
1636
|
+
var MetaMaskWalletIcon = () => /* @__PURE__ */ jsx(IconFrame, { background: "#1A0F07", children: /* @__PURE__ */ jsxs("svg", { width: "32", height: "32", viewBox: "0 0 32 32", fill: "none", children: [
|
|
1637
|
+
/* @__PURE__ */ jsx("path", { d: "M8 6L15 11L12 14L8 6Z", fill: "#E17726" }),
|
|
1638
|
+
/* @__PURE__ */ jsx("path", { d: "M24 6L17 11L20 14L24 6Z", fill: "#E27625" }),
|
|
1639
|
+
/* @__PURE__ */ jsx("path", { d: "M11 19L15 22V17L11 19Z", fill: "#F6851B" }),
|
|
1640
|
+
/* @__PURE__ */ jsx("path", { d: "M21 19L17 22V17L21 19Z", fill: "#F6851B" }),
|
|
1641
|
+
/* @__PURE__ */ jsx("path", { d: "M12 14L15 11V17L11 19L12 14Z", fill: "#763D16" }),
|
|
1642
|
+
/* @__PURE__ */ jsx("path", { d: "M20 14L17 11V17L21 19L20 14Z", fill: "#763D16" })
|
|
1643
|
+
] }) });
|
|
1644
|
+
var OKXWalletIcon = () => /* @__PURE__ */ jsx(IconFrame, { background: "#FFFFFF", children: /* @__PURE__ */ jsxs("svg", { width: "30", height: "30", viewBox: "0 0 30 30", fill: "none", children: [
|
|
1645
|
+
/* @__PURE__ */ jsx("rect", { x: "2", y: "2", width: "8", height: "8", rx: "2", fill: "#050608" }),
|
|
1646
|
+
/* @__PURE__ */ jsx("rect", { x: "11", y: "2", width: "8", height: "8", rx: "2", fill: "#050608" }),
|
|
1647
|
+
/* @__PURE__ */ jsx("rect", { x: "20", y: "2", width: "8", height: "8", rx: "2", fill: "#050608" }),
|
|
1648
|
+
/* @__PURE__ */ jsx("rect", { x: "2", y: "11", width: "8", height: "8", rx: "2", fill: "#050608" }),
|
|
1649
|
+
/* @__PURE__ */ jsx("rect", { x: "20", y: "11", width: "8", height: "8", rx: "2", fill: "#050608" }),
|
|
1650
|
+
/* @__PURE__ */ jsx("rect", { x: "2", y: "20", width: "8", height: "8", rx: "2", fill: "#050608" }),
|
|
1651
|
+
/* @__PURE__ */ jsx("rect", { x: "11", y: "20", width: "8", height: "8", rx: "2", fill: "#050608" }),
|
|
1652
|
+
/* @__PURE__ */ jsx("rect", { x: "20", y: "20", width: "8", height: "8", rx: "2", fill: "#050608" })
|
|
1653
|
+
] }) });
|
|
1654
|
+
var CoinbaseWalletIcon = () => /* @__PURE__ */ jsx(IconFrame, { background: "#0052FF", children: /* @__PURE__ */ jsxs("svg", { width: "30", height: "30", viewBox: "0 0 30 30", fill: "none", children: [
|
|
1655
|
+
/* @__PURE__ */ jsx("circle", { cx: "15", cy: "15", r: "10", stroke: "white", strokeWidth: "4" }),
|
|
1656
|
+
/* @__PURE__ */ jsx("rect", { x: "9", y: "13", width: "12", height: "4", rx: "2", fill: "white" })
|
|
1657
|
+
] }) });
|
|
1658
|
+
var TrustWalletIcon = () => /* @__PURE__ */ jsx(IconFrame, { background: "#3375FF", children: /* @__PURE__ */ jsxs("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", children: [
|
|
1659
|
+
/* @__PURE__ */ jsx("path", { d: "M14 4L21 6.6V12.8C21 17.1 18.1 20.9 14 22.4C9.9 20.9 7 17.1 7 12.8V6.6L14 4Z", fill: "white" }),
|
|
1660
|
+
/* @__PURE__ */ jsx("path", { d: "M14 8L17 9.1V12.3C17 14.7 15.7 16.8 14 17.6C12.3 16.8 11 14.7 11 12.3V9.1L14 8Z", fill: "#3375FF" })
|
|
1661
|
+
] }) });
|
|
1662
|
+
var PhantomWalletIcon = () => /* @__PURE__ */ jsx(IconFrame, { background: "linear-gradient(135deg, #6C47FF 0%, #9B6BFF 100%)", children: /* @__PURE__ */ jsxs("svg", { width: "30", height: "30", viewBox: "0 0 30 30", fill: "none", children: [
|
|
1663
|
+
/* @__PURE__ */ jsx("path", { d: "M8 18.5C8 14.4 11.2 11 15.3 11H20.4C21.8 11 23 12.2 23 13.6C23 15 21.8 16.2 20.4 16.2H14.7", stroke: "white", strokeWidth: "3", strokeLinecap: "round" }),
|
|
1664
|
+
/* @__PURE__ */ jsx("path", { d: "M10.5 14H19.5", stroke: "white", strokeWidth: "3", strokeLinecap: "round" }),
|
|
1665
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "20", r: "1.4", fill: "white" }),
|
|
1666
|
+
/* @__PURE__ */ jsx("circle", { cx: "18", cy: "20", r: "1.4", fill: "white" })
|
|
1667
|
+
] }) });
|
|
1668
|
+
var RabbyWalletIcon = () => /* @__PURE__ */ jsx(IconFrame, { background: "#EBF2FF", children: /* @__PURE__ */ jsxs("svg", { width: "30", height: "30", viewBox: "0 0 30 30", fill: "none", children: [
|
|
1669
|
+
/* @__PURE__ */ jsx("path", { d: "M11 7L13.5 13", stroke: "#7084FF", strokeWidth: "3", strokeLinecap: "round" }),
|
|
1670
|
+
/* @__PURE__ */ jsx("path", { d: "M19 7L16.5 13", stroke: "#7084FF", strokeWidth: "3", strokeLinecap: "round" }),
|
|
1671
|
+
/* @__PURE__ */ jsx("rect", { x: "8", y: "12", width: "14", height: "11", rx: "6", fill: "#7084FF" }),
|
|
1672
|
+
/* @__PURE__ */ jsx("circle", { cx: "13", cy: "17", r: "1.4", fill: "white" }),
|
|
1673
|
+
/* @__PURE__ */ jsx("circle", { cx: "17", cy: "17", r: "1.4", fill: "white" }),
|
|
1674
|
+
/* @__PURE__ */ jsx("path", { d: "M13 20C13.6 20.4 14.3 20.6 15 20.6C15.7 20.6 16.4 20.4 17 20", stroke: "white", strokeWidth: "1.8", strokeLinecap: "round" })
|
|
1675
|
+
] }) });
|
|
1676
|
+
var RainbowWalletIcon = () => /* @__PURE__ */ jsx(IconFrame, { background: "linear-gradient(180deg, #174299 0%, #001E59 100%)", children: /* @__PURE__ */ jsxs("svg", { width: "32", height: "32", viewBox: "0 0 120 120", fill: "none", style: { overflow: "hidden", borderRadius: 12 }, children: [
|
|
1677
|
+
/* @__PURE__ */ jsxs("defs", { children: [
|
|
1678
|
+
/* @__PURE__ */ jsxs("radialGradient", { id: "rainbow_r1", cx: "0", cy: "0", r: "1", gradientUnits: "userSpaceOnUse", gradientTransform: "translate(26 94) rotate(-90) scale(74)", children: [
|
|
1679
|
+
/* @__PURE__ */ jsx("stop", { offset: "0.770277", stopColor: "#FF4000" }),
|
|
1680
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#8754C9" })
|
|
1681
|
+
] }),
|
|
1682
|
+
/* @__PURE__ */ jsxs("linearGradient", { id: "rainbow_l2", x1: "83", y1: "97", x2: "100", y2: "97", gradientUnits: "userSpaceOnUse", children: [
|
|
1683
|
+
/* @__PURE__ */ jsx("stop", { stopColor: "#FF4000" }),
|
|
1684
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#8754C9" })
|
|
1685
|
+
] }),
|
|
1686
|
+
/* @__PURE__ */ jsxs("linearGradient", { id: "rainbow_l3", x1: "23", y1: "20", x2: "23", y2: "37", gradientUnits: "userSpaceOnUse", children: [
|
|
1687
|
+
/* @__PURE__ */ jsx("stop", { stopColor: "#8754C9" }),
|
|
1688
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#FF4000" })
|
|
1689
|
+
] }),
|
|
1690
|
+
/* @__PURE__ */ jsxs("radialGradient", { id: "rainbow_r4", cx: "0", cy: "0", r: "1", gradientUnits: "userSpaceOnUse", gradientTransform: "translate(26 94) rotate(-90) scale(58)", children: [
|
|
1691
|
+
/* @__PURE__ */ jsx("stop", { offset: "0.723929", stopColor: "#FFF700" }),
|
|
1692
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#FF9901" })
|
|
1693
|
+
] }),
|
|
1694
|
+
/* @__PURE__ */ jsxs("linearGradient", { id: "rainbow_l5", x1: "68", y1: "97", x2: "84", y2: "97", gradientUnits: "userSpaceOnUse", children: [
|
|
1695
|
+
/* @__PURE__ */ jsx("stop", { stopColor: "#FFF700" }),
|
|
1696
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#FF9901" })
|
|
1697
|
+
] }),
|
|
1698
|
+
/* @__PURE__ */ jsxs("linearGradient", { id: "rainbow_l6", x1: "23", y1: "52", x2: "23", y2: "36", gradientUnits: "userSpaceOnUse", children: [
|
|
1699
|
+
/* @__PURE__ */ jsx("stop", { stopColor: "#FFF700" }),
|
|
1700
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#FF9901" })
|
|
1701
|
+
] }),
|
|
1702
|
+
/* @__PURE__ */ jsxs("radialGradient", { id: "rainbow_r7", cx: "0", cy: "0", r: "1", gradientUnits: "userSpaceOnUse", gradientTransform: "translate(26 94) rotate(-90) scale(42)", children: [
|
|
1703
|
+
/* @__PURE__ */ jsx("stop", { offset: "0.59513", stopColor: "#00AAFF" }),
|
|
1704
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#01DA40" })
|
|
1705
|
+
] }),
|
|
1706
|
+
/* @__PURE__ */ jsxs("radialGradient", { id: "rainbow_r8", cx: "0", cy: "0", r: "1", gradientUnits: "userSpaceOnUse", gradientTransform: "translate(51 97) scale(17 45.3333)", children: [
|
|
1707
|
+
/* @__PURE__ */ jsx("stop", { stopColor: "#00AAFF" }),
|
|
1708
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#01DA40" })
|
|
1709
|
+
] }),
|
|
1710
|
+
/* @__PURE__ */ jsxs("radialGradient", { id: "rainbow_r9", cx: "0", cy: "0", r: "1", gradientUnits: "userSpaceOnUse", gradientTransform: "translate(23 69) rotate(-90) scale(17 322.37)", children: [
|
|
1711
|
+
/* @__PURE__ */ jsx("stop", { stopColor: "#00AAFF" }),
|
|
1712
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#01DA40" })
|
|
1713
|
+
] })
|
|
1714
|
+
] }),
|
|
1715
|
+
/* @__PURE__ */ jsx("path", { d: "M20 38H26C56.9279 38 82 63.0721 82 94V100H94C97.3137 100 100 97.3137 100 94C100 53.1309 66.8691 20 26 20C22.6863 20 20 22.6863 20 26V38Z", fill: "url(#rainbow_r1)" }),
|
|
1716
|
+
/* @__PURE__ */ jsx("path", { d: "M84 94H100C100 97.3137 97.3137 100 94 100H84V94Z", fill: "url(#rainbow_l2)" }),
|
|
1717
|
+
/* @__PURE__ */ jsx("path", { d: "M26 20L26 36H20L20 26C20 22.6863 22.6863 20 26 20Z", fill: "url(#rainbow_l3)" }),
|
|
1718
|
+
/* @__PURE__ */ jsx("path", { d: "M20 36H26C58.0325 36 84 61.9675 84 94V100H66V94C66 71.9086 48.0914 54 26 54H20V36Z", fill: "url(#rainbow_r4)" }),
|
|
1719
|
+
/* @__PURE__ */ jsx("path", { d: "M68 94H84V100H68V94Z", fill: "url(#rainbow_l5)" }),
|
|
1720
|
+
/* @__PURE__ */ jsx("path", { d: "M20 52L20 36L26 36L26 52H20Z", fill: "url(#rainbow_l6)" }),
|
|
1721
|
+
/* @__PURE__ */ jsx("path", { d: "M20 62C20 65.3137 22.6863 68 26 68C40.3594 68 52 79.6406 52 94C52 97.3137 54.6863 100 58 100H68V94C68 70.804 49.196 52 26 52H20V62Z", fill: "url(#rainbow_r7)" }),
|
|
1722
|
+
/* @__PURE__ */ jsx("path", { d: "M52 94H68V100H58C54.6863 100 52 97.3137 52 94Z", fill: "url(#rainbow_r8)" }),
|
|
1723
|
+
/* @__PURE__ */ jsx("path", { d: "M26 68C22.6863 68 20 65.3137 20 62L20 52L26 52L26 68Z", fill: "url(#rainbow_r9)" })
|
|
1724
|
+
] }) });
|
|
1725
|
+
var ZerionWalletIcon = () => /* @__PURE__ */ jsx(IconFrame, { background: "#2962EF", children: /* @__PURE__ */ jsx("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", children: /* @__PURE__ */ jsx("path", { fill: "#fff", d: "M6.073 7c-.48 0-.665.593-.262.841l10.073 6.074a.577.577 0 0 0 .758-.139l4.43-5.814c.3-.404-.004-.962-.525-.962H6.073ZM21.904 21c.48 0 .67-.596.267-.844l-10.075-6.073a.569.569 0 0 0-.751.146l-4.437 5.813c-.301.404.012.958.534.958h14.462Z" }) }) });
|
|
1726
|
+
var BraveWalletIcon = () => /* @__PURE__ */ jsx(IconFrame, { background: "#FFF", children: /* @__PURE__ */ jsxs("svg", { width: "32", height: "32", viewBox: "-100 -100 2970 2970", fill: "none", style: { overflow: "hidden", borderRadius: 12 }, children: [
|
|
1727
|
+
/* @__PURE__ */ jsxs("defs", { children: [
|
|
1728
|
+
/* @__PURE__ */ jsxs("linearGradient", { id: "brave_a", y1: "51%", y2: "51%", children: [
|
|
1729
|
+
/* @__PURE__ */ jsx("stop", { offset: "0.4", stopColor: "#f50" }),
|
|
1730
|
+
/* @__PURE__ */ jsx("stop", { offset: "0.6", stopColor: "#ff2000" })
|
|
1731
|
+
] }),
|
|
1732
|
+
/* @__PURE__ */ jsxs("linearGradient", { id: "brave_b", x1: "2%", y1: "51%", x2: "51%", y2: "51%", children: [
|
|
1733
|
+
/* @__PURE__ */ jsx("stop", { offset: "0", stopColor: "#ff452a" }),
|
|
1734
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#ff2000" })
|
|
1735
|
+
] })
|
|
1736
|
+
] }),
|
|
1737
|
+
/* @__PURE__ */ jsx("path", { fill: "url(#brave_a)", d: "m2395 723 60-147-170-176c-92-92-288-38-288-38l-222-252H992L769 363s-196-53-288 37L311 575l60 147-75 218 250 953c52 204 87 283 234 387l457 310c44 27 98 74 147 74s103-47 147-74l457-310c147-104 182-183 234-387l250-953z" }),
|
|
1738
|
+
/* @__PURE__ */ jsx("path", { fill: "#fff", d: "M1935 524s287 347 287 420c0 75-36 94-72 133l-215 230c-20 20-63 54-38 113 25 60 60 134 20 210-40 77-110 128-155 120a820 820 0 0 1-190-90c-38-25-160-126-160-165s126-110 150-124c23-16 130-78 132-102s2-30-30-90-88-140-80-192c10-52 100-80 167-105l207-78c16-8 12-15-36-20-48-4-183-22-244-5s-163 43-173 57c-8 14-16 14-7 62l58 315c4 40 12 67-30 77-44 10-117 27-142 27s-99-17-142-27-35-37-30-77c4-40 48-268 57-315 10-48 1-48-7-62-10-14-113-40-174-57-60-17-196 1-244 6-48 4-52 10-36 20l207 77c66 25 158 53 167 105 10 53-47 132-80 192s-32 66-30 90 110 86 132 102c24 15 150 85 150 124s-119 140-159 165a820 820 0 0 1-190 90c-45 8-115-43-156-120-40-76-4-150 20-210 25-60-17-92-38-113l-215-230c-35-37-71-57-71-131s287-420 287-420l273 44c32 0 103-27 168-50 65-20 110-22 110-22s44 0 110 22 136 50 168 50c33 0 275-47 275-47zm-215 1328c18 10 7 32-10 44l-254 198c-20 20-52 50-73 50s-52-30-73-50a13200 13200 0 0 0-255-198c-16-12-27-33-10-44l150-80a870 870 0 0 1 188-73c15 0 110 34 187 73l150 80z" }),
|
|
1739
|
+
/* @__PURE__ */ jsx("path", { fill: "url(#brave_b)", d: "m1999 363-224-253H992L769 363s-196-53-288 37c0 0 260-23 350 123l276 47c32 0 103-27 168-50 65-20 110-22 110-22s44 0 110 22 136 50 168 50c33 0 275-47 275-47 90-146 350-123 350-123-92-92-288-38-288-38" })
|
|
1740
|
+
] }) });
|
|
1741
|
+
var BitgetWalletIcon = () => /* @__PURE__ */ jsx(IconFrame, { background: "#001F29", children: /* @__PURE__ */ jsx("svg", { width: "28", height: "28", viewBox: "0 0 512 512", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M219.948 95.7022C201.623 95.6929 183.33 95.6835 164.941 95.7116C153.822 95.7116 149.651 109.671 157.921 117.939L283.098 243.117C287.004 246.69 289.441 250.574 289.53 255.693C289.441 260.812 287.004 264.696 283.098 268.269L157.921 393.446C149.651 401.715 153.822 415.674 164.941 415.674C183.33 415.702 201.623 415.693 219.948 415.683C229.122 415.679 238.305 415.674 247.511 415.674C259.555 415.674 266.72 409.24 273.154 402.805L386.047 289.912C395.057 280.902 403.119 268.939 403.009 255.693C403.119 242.447 395.057 230.484 386.047 221.474L273.154 108.58C266.72 102.146 259.555 95.7116 247.511 95.7116C238.305 95.7116 229.122 95.7069 219.948 95.7022Z", fill: "#00F0FF" }) }) });
|
|
1742
|
+
var walletIconTheme = {
|
|
1743
|
+
metamask: "#F6851B",
|
|
1744
|
+
okx: "#050608",
|
|
1745
|
+
coinbase: "#0052FF",
|
|
1746
|
+
trust: "#3375FF",
|
|
1747
|
+
phantom: "#6C47FF",
|
|
1748
|
+
rabby: "#7084FF",
|
|
1749
|
+
rainbow: "#123F99",
|
|
1750
|
+
zerion: "#2962EF",
|
|
1751
|
+
brave: "#FF452A",
|
|
1752
|
+
bitget: "#00F0FF"
|
|
1753
|
+
};
|
|
1754
|
+
var WalletPlaceholder = ({ walletId, name }) => /* @__PURE__ */ jsx(IconFrame, { background: walletIconTheme[walletId] ?? colors.cardRaised, children: /* @__PURE__ */ jsx(
|
|
1755
|
+
"span",
|
|
1756
|
+
{
|
|
1757
|
+
style: {
|
|
1758
|
+
fontSize: 14,
|
|
1759
|
+
fontWeight: 700,
|
|
1760
|
+
color: walletIconTheme[walletId] ? "#FFFFFF" : colors.textSecondary,
|
|
1761
|
+
fontFamily: fonts.family
|
|
1762
|
+
},
|
|
1763
|
+
children: name.slice(0, 2).toUpperCase()
|
|
1764
|
+
}
|
|
1765
|
+
) });
|
|
1766
|
+
var DefaultWalletIcon = ({
|
|
1767
|
+
walletId,
|
|
1768
|
+
name
|
|
1769
|
+
}) => {
|
|
1770
|
+
switch (walletId) {
|
|
1771
|
+
case "metamask":
|
|
1772
|
+
return /* @__PURE__ */ jsx(MetaMaskWalletIcon, {});
|
|
1773
|
+
case "okx":
|
|
1774
|
+
return /* @__PURE__ */ jsx(OKXWalletIcon, {});
|
|
1775
|
+
case "coinbase":
|
|
1776
|
+
return /* @__PURE__ */ jsx(CoinbaseWalletIcon, {});
|
|
1777
|
+
case "trust":
|
|
1778
|
+
return /* @__PURE__ */ jsx(TrustWalletIcon, {});
|
|
1779
|
+
case "phantom":
|
|
1780
|
+
return /* @__PURE__ */ jsx(PhantomWalletIcon, {});
|
|
1781
|
+
case "rabby":
|
|
1782
|
+
return /* @__PURE__ */ jsx(RabbyWalletIcon, {});
|
|
1783
|
+
case "rainbow":
|
|
1784
|
+
return /* @__PURE__ */ jsx(RainbowWalletIcon, {});
|
|
1785
|
+
case "zerion":
|
|
1786
|
+
return /* @__PURE__ */ jsx(ZerionWalletIcon, {});
|
|
1787
|
+
case "brave":
|
|
1788
|
+
return /* @__PURE__ */ jsx(BraveWalletIcon, {});
|
|
1789
|
+
case "bitget":
|
|
1790
|
+
return /* @__PURE__ */ jsx(BitgetWalletIcon, {});
|
|
1791
|
+
default:
|
|
1792
|
+
return /* @__PURE__ */ jsx(WalletPlaceholder, { walletId, name });
|
|
1793
|
+
}
|
|
1794
|
+
};
|
|
1795
|
+
var CloseButton = ({ onClick }) => /* @__PURE__ */ jsx(
|
|
1796
|
+
"button",
|
|
1797
|
+
{
|
|
1798
|
+
type: "button",
|
|
1799
|
+
onClick,
|
|
1800
|
+
"aria-label": "Close",
|
|
1801
|
+
style: {
|
|
1802
|
+
width: 30,
|
|
1803
|
+
height: 30,
|
|
1804
|
+
borderRadius: "50%",
|
|
1805
|
+
background: colors.card,
|
|
1806
|
+
border: "none",
|
|
1807
|
+
cursor: "pointer",
|
|
1808
|
+
display: "flex",
|
|
1809
|
+
alignItems: "center",
|
|
1810
|
+
justifyContent: "center",
|
|
1811
|
+
padding: 0,
|
|
1812
|
+
flexShrink: 0
|
|
1813
|
+
},
|
|
1814
|
+
children: /* @__PURE__ */ jsx("svg", { width: "17", height: "17", viewBox: "0 0 17 17", fill: "none", children: /* @__PURE__ */ jsx(
|
|
1815
|
+
"path",
|
|
1816
|
+
{
|
|
1817
|
+
d: "M4.25 4.25L12.75 12.75M12.75 4.25L4.25 12.75",
|
|
1818
|
+
stroke: colors.textPrimary,
|
|
1819
|
+
strokeWidth: "1.5",
|
|
1820
|
+
strokeLinecap: "round"
|
|
1821
|
+
}
|
|
1822
|
+
) })
|
|
1823
|
+
}
|
|
1824
|
+
);
|
|
1825
|
+
var ModalFrame = ({
|
|
1826
|
+
onClose,
|
|
1827
|
+
width = 500,
|
|
1828
|
+
cardStyle,
|
|
1829
|
+
contentStyle,
|
|
1830
|
+
children
|
|
1831
|
+
}) => /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 14, alignItems: "flex-start" }, children: [
|
|
1832
|
+
/* @__PURE__ */ jsx(
|
|
1833
|
+
"div",
|
|
1834
|
+
{
|
|
1835
|
+
style: {
|
|
1836
|
+
width,
|
|
1837
|
+
background: colors.card,
|
|
1838
|
+
borderRadius: radii.card,
|
|
1839
|
+
overflow: "hidden",
|
|
1840
|
+
...cardStyle
|
|
1841
|
+
},
|
|
1842
|
+
children: /* @__PURE__ */ jsx(
|
|
1843
|
+
"div",
|
|
1844
|
+
{
|
|
1845
|
+
style: {
|
|
1846
|
+
display: "flex",
|
|
1847
|
+
flexDirection: "column",
|
|
1848
|
+
minHeight: 0,
|
|
1849
|
+
fontFamily: fonts.family,
|
|
1850
|
+
color: colors.textPrimary,
|
|
1851
|
+
boxSizing: "border-box",
|
|
1852
|
+
...contentStyle
|
|
1853
|
+
},
|
|
1854
|
+
children
|
|
1855
|
+
}
|
|
1856
|
+
)
|
|
1857
|
+
}
|
|
1858
|
+
),
|
|
1859
|
+
/* @__PURE__ */ jsx(CloseButton, { onClick: onClose })
|
|
1860
|
+
] }) });
|
|
1861
|
+
var SignInModalFrame = ({
|
|
1862
|
+
id,
|
|
1863
|
+
title,
|
|
1864
|
+
onClose,
|
|
1865
|
+
footer,
|
|
1866
|
+
children
|
|
1867
|
+
}) => /* @__PURE__ */ jsx(
|
|
1868
|
+
ModalFrame,
|
|
1869
|
+
{
|
|
1870
|
+
onClose,
|
|
1871
|
+
cardStyle: { padding: "32px 24px" },
|
|
1872
|
+
contentStyle: { alignItems: "center" },
|
|
1873
|
+
children: /* @__PURE__ */ jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: 24, alignItems: "center" }, id, children: [
|
|
1874
|
+
/* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: 24, fontWeight: 600, lineHeight: 1.4, textAlign: "center" }, children: title }),
|
|
1875
|
+
/* @__PURE__ */ jsx("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: 12, alignItems: "center" }, children }),
|
|
1876
|
+
footer
|
|
1877
|
+
] })
|
|
1878
|
+
}
|
|
1879
|
+
);
|
|
1880
|
+
var SignInModalSocialSection = ({
|
|
1881
|
+
id,
|
|
1882
|
+
socialProviders,
|
|
1883
|
+
isBusy,
|
|
1884
|
+
loadingProvider,
|
|
1885
|
+
onSocialClick
|
|
1886
|
+
}) => /* @__PURE__ */ jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: 24 }, id, children: [
|
|
1887
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: socialProviders.map((provider) => {
|
|
1888
|
+
const isLoading = loadingProvider === provider.id;
|
|
1889
|
+
return /* @__PURE__ */ jsxs(
|
|
1890
|
+
"button",
|
|
1891
|
+
{
|
|
1892
|
+
type: "button",
|
|
1893
|
+
disabled: isBusy,
|
|
1894
|
+
onClick: () => onSocialClick(provider.id),
|
|
1895
|
+
style: {
|
|
1896
|
+
width: "100%",
|
|
1897
|
+
height: 48,
|
|
1898
|
+
borderRadius: radii.pill,
|
|
1899
|
+
border: `1px solid ${colors.border}`,
|
|
1900
|
+
background: "transparent",
|
|
1901
|
+
display: "flex",
|
|
1902
|
+
alignItems: "center",
|
|
1903
|
+
justifyContent: "center",
|
|
1904
|
+
gap: 12,
|
|
1905
|
+
cursor: isBusy ? "wait" : "pointer",
|
|
1906
|
+
padding: 12,
|
|
1907
|
+
boxSizing: "border-box",
|
|
1908
|
+
opacity: isLoading ? 0.6 : isBusy ? 0.8 : 1,
|
|
1909
|
+
transition: "opacity .15s"
|
|
1910
|
+
},
|
|
1911
|
+
children: [
|
|
1912
|
+
isLoading ? /* @__PURE__ */ jsx(SpinnerIcon, {}) : provider.icon,
|
|
1913
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 16, fontWeight: 500, lineHeight: 1.4, color: colors.textPrimary, fontFamily: fonts.family }, children: isLoading ? "Signing in..." : provider.label })
|
|
1914
|
+
]
|
|
1915
|
+
},
|
|
1916
|
+
provider.id
|
|
1917
|
+
);
|
|
1918
|
+
}) }),
|
|
1919
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 20, width: "100%" }, children: [
|
|
1920
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1, height: 1, background: colors.border } }),
|
|
1921
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary, opacity: 0.4, whiteSpace: "nowrap" }, children: "Or connect a wallet" }),
|
|
1922
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1, height: 1, background: colors.border } })
|
|
1923
|
+
] })
|
|
1924
|
+
] });
|
|
1925
|
+
var SignInModalWalletGrid = ({
|
|
1926
|
+
wallets,
|
|
1927
|
+
isBusy,
|
|
1928
|
+
loadingWalletId,
|
|
1929
|
+
expanded,
|
|
1930
|
+
showExpandToggle,
|
|
1931
|
+
onWalletClick,
|
|
1932
|
+
onToggleExpanded
|
|
1933
|
+
}) => /* @__PURE__ */ jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: 8, alignItems: "center", paddingTop: 12 }, children: [
|
|
1934
|
+
/* @__PURE__ */ jsx("div", { style: { width: "100%", display: "flex", flexWrap: "wrap", gap: "14px 0" }, children: wallets.map((wallet) => /* @__PURE__ */ jsxs(
|
|
1935
|
+
"button",
|
|
1936
|
+
{
|
|
1937
|
+
type: "button",
|
|
1938
|
+
disabled: isBusy,
|
|
1939
|
+
onClick: () => onWalletClick(wallet.id),
|
|
1940
|
+
style: {
|
|
1941
|
+
width: "25%",
|
|
1942
|
+
display: "flex",
|
|
1943
|
+
flexDirection: "column",
|
|
1944
|
+
alignItems: "center",
|
|
1945
|
+
gap: 4,
|
|
1946
|
+
background: "transparent",
|
|
1947
|
+
border: "none",
|
|
1948
|
+
cursor: isBusy ? "wait" : "pointer",
|
|
1949
|
+
padding: 0,
|
|
1950
|
+
opacity: loadingWalletId === wallet.id ? 0.7 : isBusy ? 0.85 : 1
|
|
1951
|
+
},
|
|
1952
|
+
children: [
|
|
1953
|
+
/* @__PURE__ */ jsx("div", { style: { width: 56, height: 56, display: "flex", alignItems: "center", justifyContent: "center" }, children: loadingWalletId === wallet.id ? /* @__PURE__ */ jsx(SpinnerIcon, {}) : wallet.icon ?? /* @__PURE__ */ jsx(DefaultWalletIcon, { walletId: wallet.id, name: wallet.name }) }),
|
|
1954
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }, children: [
|
|
1955
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 12, fontWeight: 500, lineHeight: 1.4, color: colors.textPrimary, fontFamily: fonts.family, textAlign: "center", whiteSpace: "nowrap" }, children: wallet.name }),
|
|
1956
|
+
loadingWalletId === wallet.id ? /* @__PURE__ */ jsx("span", { style: { fontSize: 10, lineHeight: 1.4, color: colors.textSecondary, fontFamily: fonts.family }, children: "Connecting..." }) : wallet.installed ? /* @__PURE__ */ jsx("span", { style: { fontSize: 10, lineHeight: 1.4, color: colors.accent, fontFamily: fonts.family }, children: "Installed" }) : wallet.installUrl ? /* @__PURE__ */ jsx(
|
|
1957
|
+
"a",
|
|
1958
|
+
{
|
|
1959
|
+
href: wallet.installUrl,
|
|
1960
|
+
target: "_blank",
|
|
1961
|
+
rel: "noopener noreferrer",
|
|
1962
|
+
onClick: (event) => event.stopPropagation(),
|
|
1963
|
+
style: { fontSize: 10, lineHeight: 1.4, color: colors.textSecondary, fontFamily: fonts.family, textDecoration: "underline" },
|
|
1964
|
+
children: "Install"
|
|
1965
|
+
}
|
|
1966
|
+
) : null
|
|
1967
|
+
] })
|
|
1968
|
+
]
|
|
1969
|
+
},
|
|
1970
|
+
wallet.id
|
|
1971
|
+
)) }),
|
|
1972
|
+
showExpandToggle && /* @__PURE__ */ jsx(
|
|
1973
|
+
"button",
|
|
1974
|
+
{
|
|
1975
|
+
type: "button",
|
|
1976
|
+
onClick: onToggleExpanded,
|
|
1977
|
+
style: {
|
|
1978
|
+
background: "transparent",
|
|
1979
|
+
border: "none",
|
|
1980
|
+
cursor: "pointer",
|
|
1981
|
+
display: "flex",
|
|
1982
|
+
alignItems: "center",
|
|
1983
|
+
justifyContent: "center",
|
|
1984
|
+
padding: 4
|
|
1985
|
+
},
|
|
1986
|
+
children: /* @__PURE__ */ jsx(ExpandIcon, { expanded })
|
|
1987
|
+
}
|
|
1988
|
+
)
|
|
1989
|
+
] });
|
|
1990
|
+
var SignInModalFooter = ({
|
|
1991
|
+
privacyPolicyUrl,
|
|
1992
|
+
termsOfUseUrl
|
|
1993
|
+
}) => /* @__PURE__ */ jsx("div", { style: { padding: "12px 0", display: "flex", justifyContent: "center", width: "100%" }, children: /* @__PURE__ */ jsxs("p", { style: { margin: 0, fontSize: 14, lineHeight: 1.4, color: colors.textSecondary, fontFamily: fonts.family, textAlign: "center" }, children: [
|
|
1994
|
+
"By continuing, I agree to the",
|
|
1995
|
+
" ",
|
|
1996
|
+
/* @__PURE__ */ jsx("a", { href: privacyPolicyUrl, style: { color: colors.textPrimary, textDecoration: "underline" }, target: "_blank", rel: "noopener noreferrer", children: "Privacy Policy" }),
|
|
1997
|
+
" ",
|
|
1998
|
+
"and",
|
|
1999
|
+
" ",
|
|
2000
|
+
/* @__PURE__ */ jsx("a", { href: termsOfUseUrl, style: { color: colors.textPrimary, textDecoration: "underline" }, target: "_blank", rel: "noopener noreferrer", children: "Terms of Use" })
|
|
2001
|
+
] }) });
|
|
2002
|
+
|
|
2003
|
+
// src/auth/oidcRelay.ts
|
|
2004
|
+
function getRelayOrigin() {
|
|
2005
|
+
if (typeof window === "undefined") {
|
|
2006
|
+
throw new Error("OIDC relay requires a browser environment");
|
|
2007
|
+
}
|
|
2008
|
+
if (window.location.hostname === "localhost") {
|
|
2009
|
+
return window.location.origin;
|
|
2010
|
+
}
|
|
2011
|
+
const relayOrigin2 = getEnv("RELAY_ORIGIN");
|
|
2012
|
+
if (!relayOrigin2) {
|
|
2013
|
+
throw new Error("RELAY_ORIGIN is not configured");
|
|
2014
|
+
}
|
|
2015
|
+
return relayOrigin2;
|
|
2016
|
+
}
|
|
2017
|
+
function openRelayWindow(url, name) {
|
|
2018
|
+
const width = 420;
|
|
2019
|
+
const height = 640;
|
|
2020
|
+
const top = (window.innerHeight - height) / 2 + window.screenY;
|
|
2021
|
+
const left = (window.innerWidth - width) / 2 + window.screenX;
|
|
2022
|
+
return window.open(
|
|
2023
|
+
url,
|
|
2024
|
+
name,
|
|
2025
|
+
`dialog=yes,top=${top}px,left=${left}px,width=${width}px,height=${height}px`
|
|
2026
|
+
);
|
|
2027
|
+
}
|
|
2028
|
+
function waitForOidcToken(popup, relayOrigin2, timeoutMs = 12e4) {
|
|
2029
|
+
return new Promise((resolve, reject) => {
|
|
2030
|
+
if (!popup) {
|
|
2031
|
+
reject(new Error("Failed to open login popup"));
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
let settled = false;
|
|
2035
|
+
const cleanup = () => {
|
|
2036
|
+
clearTimeout(timeout);
|
|
2037
|
+
clearInterval(closedCheck);
|
|
2038
|
+
window.removeEventListener("message", onMessage);
|
|
2039
|
+
};
|
|
2040
|
+
const finish = (fn) => {
|
|
2041
|
+
if (settled) return;
|
|
2042
|
+
settled = true;
|
|
2043
|
+
cleanup();
|
|
2044
|
+
fn();
|
|
2045
|
+
};
|
|
2046
|
+
const timeout = window.setTimeout(() => {
|
|
2047
|
+
try {
|
|
2048
|
+
popup.close();
|
|
2049
|
+
} catch {
|
|
2050
|
+
}
|
|
2051
|
+
finish(() => reject(new Error("Login timeout")));
|
|
2052
|
+
}, timeoutMs);
|
|
2053
|
+
const onMessage = (event) => {
|
|
2054
|
+
if (event.origin !== relayOrigin2) return;
|
|
2055
|
+
if (event.data?.action !== "login") return;
|
|
2056
|
+
const payload = event.data?.data ?? {};
|
|
2057
|
+
if (payload.error) {
|
|
2058
|
+
try {
|
|
2059
|
+
popup.close();
|
|
2060
|
+
} catch {
|
|
2061
|
+
}
|
|
2062
|
+
finish(() => reject(new Error(String(payload.error))));
|
|
2063
|
+
return;
|
|
2064
|
+
}
|
|
2065
|
+
if (payload.oidcToken) {
|
|
2066
|
+
try {
|
|
2067
|
+
popup.close();
|
|
2068
|
+
} catch {
|
|
2069
|
+
}
|
|
2070
|
+
finish(() => resolve(payload.oidcToken));
|
|
2071
|
+
}
|
|
2072
|
+
};
|
|
2073
|
+
const closedCheck = window.setInterval(() => {
|
|
2074
|
+
if (popup.closed) {
|
|
2075
|
+
finish(() => reject(new Error("Login cancelled by user")));
|
|
2076
|
+
}
|
|
2077
|
+
}, 400);
|
|
2078
|
+
window.addEventListener("message", onMessage);
|
|
2079
|
+
});
|
|
2080
|
+
}
|
|
2081
|
+
function createOidcRelayAuth({
|
|
2082
|
+
stage,
|
|
2083
|
+
googleClientId,
|
|
2084
|
+
xClientId
|
|
2085
|
+
}) {
|
|
2086
|
+
const relayOrigin2 = getRelayOrigin();
|
|
2087
|
+
const buildUrl = (provider, clientId) => {
|
|
2088
|
+
const target = window.location.origin;
|
|
2089
|
+
const params = new URLSearchParams({
|
|
2090
|
+
target,
|
|
2091
|
+
stage,
|
|
2092
|
+
eventId: Date.now().toString(),
|
|
2093
|
+
action: "login",
|
|
2094
|
+
clientId
|
|
2095
|
+
});
|
|
2096
|
+
return `${relayOrigin2}/relay/${provider}?${params.toString()}`;
|
|
2097
|
+
};
|
|
2098
|
+
return {
|
|
2099
|
+
async loginByGoogle() {
|
|
2100
|
+
const popup = openRelayWindow(buildUrl("google", googleClientId), "Google login");
|
|
2101
|
+
return waitForOidcToken(popup, relayOrigin2);
|
|
2102
|
+
},
|
|
2103
|
+
async loginByX() {
|
|
2104
|
+
const popup = openRelayWindow(buildUrl("x", xClientId), "X login");
|
|
2105
|
+
return waitForOidcToken(popup, relayOrigin2);
|
|
2106
|
+
}
|
|
2107
|
+
};
|
|
2108
|
+
}
|
|
2109
|
+
function resolveOidcStage() {
|
|
2110
|
+
return getEnv("STAGE").toLowerCase() === "prod" ? "prod" : "dev";
|
|
2111
|
+
}
|
|
2112
|
+
var useSignInModalController = ({
|
|
2113
|
+
wallets,
|
|
2114
|
+
initialVisibleCount,
|
|
2115
|
+
onGoogleLogin,
|
|
2116
|
+
onTwitterLogin,
|
|
2117
|
+
onCubeSignerSession,
|
|
2118
|
+
onWalletConnected,
|
|
2119
|
+
onSocialLogin,
|
|
2120
|
+
onWalletSelect
|
|
2121
|
+
}) => {
|
|
2122
|
+
const [expanded, setExpanded] = useState(false);
|
|
2123
|
+
const [loadingProvider, setLoadingProvider] = useState(null);
|
|
2124
|
+
const [loadingWalletId, setLoadingWalletId] = useState(null);
|
|
2125
|
+
const defaultWalletRegistry = useMemo(() => createDefaultInjectedWalletRegistry(), []);
|
|
2126
|
+
const defaultWalletConnector = useMemo(
|
|
2127
|
+
() => new WalletConnector([
|
|
2128
|
+
...defaultWalletRegistry.map((item) => item.provider)
|
|
2129
|
+
]),
|
|
2130
|
+
[defaultWalletRegistry]
|
|
2131
|
+
);
|
|
2132
|
+
const resolvedWallets = useMemo(
|
|
2133
|
+
() => resolveWalletItems(wallets, defaultWalletRegistry),
|
|
2134
|
+
[defaultWalletRegistry, wallets]
|
|
2135
|
+
);
|
|
2136
|
+
const showExpandToggle = resolvedWallets.length > initialVisibleCount;
|
|
2137
|
+
const visibleWallets = expanded ? resolvedWallets : resolvedWallets.slice(0, initialVisibleCount);
|
|
2138
|
+
const isBusy = !!loadingProvider || !!loadingWalletId;
|
|
2139
|
+
const handleSocialClick = async (providerId) => {
|
|
2140
|
+
setLoadingProvider(providerId);
|
|
2141
|
+
try {
|
|
2142
|
+
const config = getSDKConfig();
|
|
2143
|
+
if (!config.cubeSigner) {
|
|
2144
|
+
throw new Error("cubeSigner config is required for social login");
|
|
2145
|
+
}
|
|
2146
|
+
const auth = createOidcRelayAuth({
|
|
2147
|
+
stage: resolveOidcStage(),
|
|
2148
|
+
googleClientId: config.googleClientId ?? "",
|
|
2149
|
+
xClientId: config.twitterClientId ?? ""
|
|
2150
|
+
});
|
|
2151
|
+
if (providerId === "google") {
|
|
2152
|
+
if (!config.googleClientId) {
|
|
2153
|
+
throw new Error("googleClientId is required for Google sign-in");
|
|
2154
|
+
}
|
|
2155
|
+
const oidcToken = await auth.loginByGoogle();
|
|
2156
|
+
const authSource = "google";
|
|
2157
|
+
WalletAccount.clearInstance();
|
|
2158
|
+
await WalletAccount.getInstance(oidcToken, authSource, config.cubeSigner);
|
|
2159
|
+
const session = WalletAccount.getWalletSession();
|
|
2160
|
+
const cubeSignerSession = WalletAccount.getCubeSignerSession();
|
|
2161
|
+
onGoogleLogin?.({ idToken: oidcToken });
|
|
2162
|
+
if (cubeSignerSession) onCubeSignerSession?.(cubeSignerSession);
|
|
2163
|
+
onSocialLogin?.(providerId);
|
|
2164
|
+
if (!session) {
|
|
2165
|
+
throw new Error("Failed to build wallet session from Google login");
|
|
2166
|
+
}
|
|
2167
|
+
return session;
|
|
2168
|
+
}
|
|
2169
|
+
if (providerId === "x") {
|
|
2170
|
+
if (!config.twitterClientId) {
|
|
2171
|
+
throw new Error("twitterClientId is required for X sign-in");
|
|
2172
|
+
}
|
|
2173
|
+
const oidcToken = await auth.loginByX();
|
|
2174
|
+
const authSource = "twitter";
|
|
2175
|
+
WalletAccount.clearInstance();
|
|
2176
|
+
await WalletAccount.getInstance(oidcToken, authSource, config.cubeSigner);
|
|
2177
|
+
const session = WalletAccount.getWalletSession();
|
|
2178
|
+
const cubeSignerSession = WalletAccount.getCubeSignerSession();
|
|
2179
|
+
onTwitterLogin?.({ code: "", codeVerifier: "", state: "" });
|
|
2180
|
+
if (cubeSignerSession) onCubeSignerSession?.(cubeSignerSession);
|
|
2181
|
+
onSocialLogin?.(providerId);
|
|
2182
|
+
if (!session) {
|
|
2183
|
+
throw new Error("Failed to build wallet session from X login");
|
|
2184
|
+
}
|
|
2185
|
+
return session;
|
|
2186
|
+
}
|
|
2187
|
+
throw new Error(`Unsupported social provider: ${providerId}`);
|
|
2188
|
+
} finally {
|
|
2189
|
+
setLoadingProvider(null);
|
|
2190
|
+
}
|
|
2191
|
+
};
|
|
2192
|
+
const handleWalletClick = async (walletId) => {
|
|
2193
|
+
if (isBusy) return null;
|
|
2194
|
+
const targetWallet = resolvedWallets.find((wallet) => wallet.id === walletId);
|
|
2195
|
+
if (!targetWallet) return null;
|
|
2196
|
+
if (targetWallet.installed === false && targetWallet.installUrl) return null;
|
|
2197
|
+
setLoadingWalletId(walletId);
|
|
2198
|
+
try {
|
|
2199
|
+
if (onWalletSelect) {
|
|
2200
|
+
await onWalletSelect(walletId);
|
|
2201
|
+
return null;
|
|
2202
|
+
}
|
|
2203
|
+
const builtInWallet = defaultWalletRegistry.find((item) => item.id === walletId);
|
|
2204
|
+
if (!builtInWallet || !builtInWallet.installed) return null;
|
|
2205
|
+
const session = await defaultWalletConnector.connect(walletId);
|
|
2206
|
+
onWalletConnected?.(session, walletId);
|
|
2207
|
+
return session;
|
|
2208
|
+
} catch (error) {
|
|
2209
|
+
console.error(`[predicate-market-sdk] Wallet connect failed for ${walletId}:`, error);
|
|
2210
|
+
throw error;
|
|
2211
|
+
} finally {
|
|
2212
|
+
setLoadingWalletId(null);
|
|
2213
|
+
}
|
|
2214
|
+
};
|
|
2215
|
+
return {
|
|
2216
|
+
expanded,
|
|
2217
|
+
loadingProvider,
|
|
2218
|
+
loadingWalletId,
|
|
2219
|
+
visibleWallets,
|
|
2220
|
+
showExpandToggle,
|
|
2221
|
+
isBusy,
|
|
2222
|
+
handleSocialClick,
|
|
2223
|
+
handleWalletClick,
|
|
2224
|
+
toggleExpanded: () => setExpanded((value) => !value)
|
|
2225
|
+
};
|
|
2226
|
+
};
|
|
2227
|
+
var variantStyles = {
|
|
2228
|
+
success: { bg: "rgba(41, 255, 155, 0.82)", border: "rgba(41, 255, 155, 0.53)" },
|
|
2229
|
+
error: { bg: "rgba(255, 107, 107, 0.82)", border: "rgba(255, 107, 107, 0.53)" },
|
|
2230
|
+
info: { bg: "rgba(126, 135, 162, 0.82)", border: "rgba(126, 135, 162, 0.55)" }
|
|
2231
|
+
};
|
|
2232
|
+
var Toast = ({ message, variant = "info", duration, onClose }) => {
|
|
2233
|
+
const style = variantStyles[variant];
|
|
2234
|
+
useEffect(() => {
|
|
2235
|
+
if (duration != null && duration > 0 && onClose) {
|
|
2236
|
+
const timer = setTimeout(onClose, duration);
|
|
2237
|
+
return () => clearTimeout(timer);
|
|
2238
|
+
}
|
|
2239
|
+
}, [duration, onClose]);
|
|
2240
|
+
return /* @__PURE__ */ jsx(
|
|
2241
|
+
"div",
|
|
2242
|
+
{
|
|
2243
|
+
style: {
|
|
2244
|
+
position: "fixed",
|
|
2245
|
+
top: 0,
|
|
2246
|
+
left: 0,
|
|
2247
|
+
right: 0,
|
|
2248
|
+
display: "flex",
|
|
2249
|
+
justifyContent: "center",
|
|
2250
|
+
paddingTop: 16,
|
|
2251
|
+
zIndex: 1e4,
|
|
2252
|
+
pointerEvents: "none"
|
|
2253
|
+
},
|
|
2254
|
+
children: /* @__PURE__ */ jsxs(
|
|
2255
|
+
"div",
|
|
2256
|
+
{
|
|
2257
|
+
role: "alert",
|
|
2258
|
+
style: {
|
|
2259
|
+
pointerEvents: "auto",
|
|
2260
|
+
display: "flex",
|
|
2261
|
+
alignItems: "center",
|
|
2262
|
+
gap: 10,
|
|
2263
|
+
padding: "12px 16px",
|
|
2264
|
+
borderRadius: radii.card,
|
|
2265
|
+
background: style.bg,
|
|
2266
|
+
border: `1px solid ${style.border}`,
|
|
2267
|
+
color: colors.textPrimary,
|
|
2268
|
+
fontSize: 14,
|
|
2269
|
+
lineHeight: 1.4,
|
|
2270
|
+
maxWidth: 360,
|
|
2271
|
+
boxSizing: "border-box"
|
|
2272
|
+
},
|
|
2273
|
+
children: [
|
|
2274
|
+
/* @__PURE__ */ jsx("span", { style: { flex: 1 }, children: message }),
|
|
2275
|
+
onClose ? /* @__PURE__ */ jsx(
|
|
2276
|
+
"button",
|
|
2277
|
+
{
|
|
2278
|
+
type: "button",
|
|
2279
|
+
"aria-label": "Dismiss",
|
|
2280
|
+
onClick: onClose,
|
|
2281
|
+
style: {
|
|
2282
|
+
padding: 4,
|
|
2283
|
+
margin: -4,
|
|
2284
|
+
border: "none",
|
|
2285
|
+
background: "transparent",
|
|
2286
|
+
color: colors.textSecondary,
|
|
2287
|
+
cursor: "pointer",
|
|
2288
|
+
borderRadius: 4,
|
|
2289
|
+
lineHeight: 1
|
|
2290
|
+
},
|
|
2291
|
+
children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: /* @__PURE__ */ jsx(
|
|
2292
|
+
"path",
|
|
2293
|
+
{
|
|
2294
|
+
d: "M3.5 3.5L10.5 10.5M10.5 3.5L3.5 10.5",
|
|
2295
|
+
stroke: "currentColor",
|
|
2296
|
+
strokeWidth: "1.5",
|
|
2297
|
+
strokeLinecap: "round"
|
|
2298
|
+
}
|
|
2299
|
+
) })
|
|
2300
|
+
}
|
|
2301
|
+
) : null
|
|
2302
|
+
]
|
|
2303
|
+
}
|
|
2304
|
+
)
|
|
2305
|
+
}
|
|
2306
|
+
);
|
|
2307
|
+
};
|
|
2308
|
+
function clearSocialAccountInstance2() {
|
|
2309
|
+
try {
|
|
2310
|
+
clearSocialAccountInstance();
|
|
2311
|
+
const storage = typeof localStorage !== "undefined" ? localStorage : null;
|
|
2312
|
+
const adapterId = storage?.getItem("ab:wallet:adapterId");
|
|
2313
|
+
const session = sessionStore.getState().session;
|
|
2314
|
+
const isSocialSession = session?.walletType === "social" || session?.authSource === "google" || session?.authSource === "twitter" || adapterId === "cubist";
|
|
2315
|
+
if (!isSocialSession) return;
|
|
2316
|
+
sessionStore.clearSession();
|
|
2317
|
+
storage?.removeItem("ab:wallet:session");
|
|
2318
|
+
storage?.removeItem("ab:wallet:adapterId");
|
|
2319
|
+
} catch {
|
|
2320
|
+
clearSocialAccountInstance();
|
|
2321
|
+
sessionStore.clearSession();
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
var SignInModal = ({
|
|
2325
|
+
title = "Welcome to PredicateMarket",
|
|
2326
|
+
socialProviders,
|
|
2327
|
+
wallets,
|
|
2328
|
+
initialVisibleCount,
|
|
2329
|
+
privacyPolicyUrl = "#",
|
|
2330
|
+
termsOfUseUrl = "#",
|
|
2331
|
+
onGoogleLogin,
|
|
2332
|
+
onTwitterLogin,
|
|
2333
|
+
onCubeSignerSession,
|
|
2334
|
+
onWalletConnected,
|
|
2335
|
+
onSocialLogin,
|
|
2336
|
+
onWalletSelect,
|
|
2337
|
+
onDismiss,
|
|
2338
|
+
onSuccess
|
|
2339
|
+
}) => {
|
|
2340
|
+
const sdkConfig2 = getSDKConfig();
|
|
2341
|
+
const effectiveSocialProviders = resolveSocialProviders(
|
|
2342
|
+
socialProviders ?? sdkConfig2.signIn?.socialProviders
|
|
2343
|
+
);
|
|
2344
|
+
const effectiveWallets = wallets ?? sdkConfig2.signIn?.wallets;
|
|
2345
|
+
const effectiveInitialVisibleCount = initialVisibleCount ?? sdkConfig2.signIn?.initialVisibleCount ?? 5;
|
|
2346
|
+
const [toastError, setToastError] = useState(null);
|
|
2347
|
+
const {
|
|
2348
|
+
expanded,
|
|
2349
|
+
loadingProvider,
|
|
2350
|
+
loadingWalletId,
|
|
2351
|
+
visibleWallets,
|
|
2352
|
+
showExpandToggle,
|
|
2353
|
+
isBusy,
|
|
2354
|
+
handleSocialClick,
|
|
2355
|
+
handleWalletClick,
|
|
2356
|
+
toggleExpanded
|
|
2357
|
+
} = useSignInModalController({
|
|
2358
|
+
wallets: effectiveWallets,
|
|
2359
|
+
initialVisibleCount: effectiveInitialVisibleCount,
|
|
2360
|
+
onGoogleLogin,
|
|
2361
|
+
onTwitterLogin,
|
|
2362
|
+
onCubeSignerSession,
|
|
2363
|
+
onWalletConnected,
|
|
2364
|
+
onSocialLogin,
|
|
2365
|
+
onWalletSelect
|
|
2366
|
+
});
|
|
2367
|
+
return /* @__PURE__ */ jsxs(
|
|
2368
|
+
SignInModalFrame,
|
|
2369
|
+
{
|
|
2370
|
+
id: "SignInModalFrame",
|
|
2371
|
+
title,
|
|
2372
|
+
onClose: onDismiss,
|
|
2373
|
+
footer: /* @__PURE__ */ jsx(
|
|
2374
|
+
SignInModalFooter,
|
|
2375
|
+
{
|
|
2376
|
+
privacyPolicyUrl,
|
|
2377
|
+
termsOfUseUrl
|
|
2378
|
+
}
|
|
2379
|
+
),
|
|
2380
|
+
children: [
|
|
2381
|
+
toastError ? /* @__PURE__ */ jsx(
|
|
2382
|
+
Toast,
|
|
2383
|
+
{
|
|
2384
|
+
message: toastError,
|
|
2385
|
+
variant: "error",
|
|
2386
|
+
duration: 5e3,
|
|
2387
|
+
onClose: () => setToastError(null)
|
|
2388
|
+
}
|
|
2389
|
+
) : null,
|
|
2390
|
+
/* @__PURE__ */ jsx(
|
|
2391
|
+
SignInModalSocialSection,
|
|
2392
|
+
{
|
|
2393
|
+
id: "SignInModalSocialSection",
|
|
2394
|
+
socialProviders: effectiveSocialProviders,
|
|
2395
|
+
isBusy,
|
|
2396
|
+
loadingProvider,
|
|
2397
|
+
onSocialClick: async (providerId) => {
|
|
2398
|
+
try {
|
|
2399
|
+
const session = await handleSocialClick(providerId);
|
|
2400
|
+
if (!session) return;
|
|
2401
|
+
const normalizedAuthSource = providerId === "x" ? "twitter" : providerId;
|
|
2402
|
+
onSuccess?.({
|
|
2403
|
+
...session,
|
|
2404
|
+
walletType: session.walletType ?? "social",
|
|
2405
|
+
authSource: session.authSource ?? normalizedAuthSource
|
|
2406
|
+
});
|
|
2407
|
+
} catch (error) {
|
|
2408
|
+
const msg = error instanceof Error ? error.message : "Social login failed";
|
|
2409
|
+
setToastError(msg);
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
),
|
|
2414
|
+
/* @__PURE__ */ jsx(
|
|
2415
|
+
SignInModalWalletGrid,
|
|
2416
|
+
{
|
|
2417
|
+
wallets: visibleWallets,
|
|
2418
|
+
isBusy,
|
|
2419
|
+
loadingWalletId,
|
|
2420
|
+
expanded,
|
|
2421
|
+
showExpandToggle,
|
|
2422
|
+
onWalletClick: async (walletId) => {
|
|
2423
|
+
try {
|
|
2424
|
+
const session = await handleWalletClick(walletId);
|
|
2425
|
+
if (session) {
|
|
2426
|
+
onSuccess?.(session);
|
|
2427
|
+
}
|
|
2428
|
+
} catch (error) {
|
|
2429
|
+
const msg = error instanceof Error ? error.message : "Wallet connect failed";
|
|
2430
|
+
setToastError(msg);
|
|
2431
|
+
}
|
|
2432
|
+
},
|
|
2433
|
+
onToggleExpanded: toggleExpanded
|
|
2434
|
+
}
|
|
2435
|
+
)
|
|
2436
|
+
]
|
|
2437
|
+
}
|
|
2438
|
+
);
|
|
2439
|
+
};
|
|
2440
|
+
var placeholderIcon = (label) => /* @__PURE__ */ jsx(
|
|
2441
|
+
"div",
|
|
2442
|
+
{
|
|
2443
|
+
style: {
|
|
2444
|
+
width: 40,
|
|
2445
|
+
height: 40,
|
|
2446
|
+
borderRadius: "12px",
|
|
2447
|
+
background: colors.cardRaised,
|
|
2448
|
+
display: "flex",
|
|
2449
|
+
alignItems: "center",
|
|
2450
|
+
justifyContent: "center",
|
|
2451
|
+
color: colors.textSecondary,
|
|
2452
|
+
fontWeight: 600
|
|
2453
|
+
},
|
|
2454
|
+
children: label.slice(0, 2).toUpperCase()
|
|
2455
|
+
}
|
|
2456
|
+
);
|
|
2457
|
+
var WalletSelectionModal = ({
|
|
2458
|
+
title = "Connect Wallet",
|
|
2459
|
+
options,
|
|
2460
|
+
onSelect
|
|
2461
|
+
}) => {
|
|
2462
|
+
const sections = [
|
|
2463
|
+
{
|
|
2464
|
+
id: "social",
|
|
2465
|
+
label: "Social Wallets",
|
|
2466
|
+
items: options.filter((item) => item.category === "social")
|
|
2467
|
+
},
|
|
2468
|
+
{
|
|
2469
|
+
id: "plugin",
|
|
2470
|
+
label: "Plugin Wallets",
|
|
2471
|
+
items: options.filter((item) => item.category === "plugin")
|
|
2472
|
+
}
|
|
2473
|
+
].filter((section) => section.items.length > 0);
|
|
2474
|
+
return /* @__PURE__ */ jsxs(
|
|
2475
|
+
"div",
|
|
2476
|
+
{
|
|
2477
|
+
style: {
|
|
2478
|
+
width: "min(720px, 90vw)",
|
|
2479
|
+
background: colors.card,
|
|
2480
|
+
borderRadius: radii.xl,
|
|
2481
|
+
border: `1px solid ${colors.border}`,
|
|
2482
|
+
padding: "40px",
|
|
2483
|
+
display: "flex",
|
|
2484
|
+
flexDirection: "column",
|
|
2485
|
+
gap: 32,
|
|
2486
|
+
color: colors.textPrimary,
|
|
2487
|
+
fontFamily: fonts.family
|
|
2488
|
+
},
|
|
2489
|
+
children: [
|
|
2490
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2491
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 26, fontWeight: 600 }, children: title }),
|
|
2492
|
+
/* @__PURE__ */ jsx("p", { style: { color: colors.textSecondary, marginTop: 8 }, children: "Choose social or plugin wallets" })
|
|
2493
|
+
] }),
|
|
2494
|
+
sections.map((section) => /* @__PURE__ */ jsxs("section", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
2495
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 14, textTransform: "uppercase", letterSpacing: 1.5, color: colors.textSecondary }, children: section.label }),
|
|
2496
|
+
/* @__PURE__ */ jsx(
|
|
2497
|
+
"div",
|
|
2498
|
+
{
|
|
2499
|
+
style: {
|
|
2500
|
+
display: "grid",
|
|
2501
|
+
gap: 16,
|
|
2502
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))"
|
|
2503
|
+
},
|
|
2504
|
+
children: section.items.map((option) => /* @__PURE__ */ jsxs(
|
|
2505
|
+
"button",
|
|
2506
|
+
{
|
|
2507
|
+
onClick: () => onSelect?.(option.id),
|
|
2508
|
+
style: {
|
|
2509
|
+
borderRadius: radii.lg,
|
|
2510
|
+
border: `1px solid ${colors.border}`,
|
|
2511
|
+
background: colors.cardRaised,
|
|
2512
|
+
padding: "20px",
|
|
2513
|
+
display: "flex",
|
|
2514
|
+
gap: 14,
|
|
2515
|
+
alignItems: "center",
|
|
2516
|
+
textAlign: "left",
|
|
2517
|
+
cursor: "pointer",
|
|
2518
|
+
color: colors.textPrimary
|
|
2519
|
+
},
|
|
2520
|
+
children: [
|
|
2521
|
+
option.icon ?? placeholderIcon(option.label),
|
|
2522
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
2523
|
+
/* @__PURE__ */ jsx("div", { style: { fontWeight: 600 }, children: option.label }),
|
|
2524
|
+
/* @__PURE__ */ jsx("div", { style: { color: colors.textSecondary, fontSize: 14 }, children: option.description })
|
|
2525
|
+
] })
|
|
2526
|
+
]
|
|
2527
|
+
},
|
|
2528
|
+
option.id
|
|
2529
|
+
))
|
|
2530
|
+
}
|
|
2531
|
+
)
|
|
2532
|
+
] }, section.id))
|
|
2533
|
+
]
|
|
2534
|
+
}
|
|
2535
|
+
);
|
|
2536
|
+
};
|
|
2537
|
+
var StepIndicator = ({ steps, stepActive, activeStep = 0 }) => {
|
|
2538
|
+
return /* @__PURE__ */ jsx(
|
|
2539
|
+
"div",
|
|
2540
|
+
{
|
|
2541
|
+
style: {
|
|
2542
|
+
display: "flex",
|
|
2543
|
+
flexDirection: "column",
|
|
2544
|
+
alignItems: "center",
|
|
2545
|
+
width: 20,
|
|
2546
|
+
paddingTop: 4,
|
|
2547
|
+
flexShrink: 0
|
|
2548
|
+
},
|
|
2549
|
+
children: Array.from({ length: steps }, (_, i) => {
|
|
2550
|
+
const isActive = stepActive && stepActive.length > i ? stepActive[i] : i <= activeStep;
|
|
2551
|
+
const isLast = i === steps - 1;
|
|
2552
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
|
|
2553
|
+
/* @__PURE__ */ jsx(
|
|
2554
|
+
"div",
|
|
2555
|
+
{
|
|
2556
|
+
style: {
|
|
2557
|
+
width: 20,
|
|
2558
|
+
height: 20,
|
|
2559
|
+
borderRadius: "50%",
|
|
2560
|
+
border: `2px solid ${isActive ? colors.stepActive : colors.stepInactive}`,
|
|
2561
|
+
display: "flex",
|
|
2562
|
+
alignItems: "center",
|
|
2563
|
+
justifyContent: "center",
|
|
2564
|
+
boxSizing: "border-box"
|
|
2565
|
+
},
|
|
2566
|
+
children: /* @__PURE__ */ jsx(
|
|
2567
|
+
"div",
|
|
2568
|
+
{
|
|
2569
|
+
style: {
|
|
2570
|
+
width: 7.5,
|
|
2571
|
+
height: 7.5,
|
|
2572
|
+
borderRadius: "50%",
|
|
2573
|
+
background: isActive ? colors.stepActive : colors.stepInactive
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
)
|
|
2577
|
+
}
|
|
2578
|
+
),
|
|
2579
|
+
!isLast && /* @__PURE__ */ jsx(
|
|
2580
|
+
"div",
|
|
2581
|
+
{
|
|
2582
|
+
style: {
|
|
2583
|
+
width: 1,
|
|
2584
|
+
height: 87,
|
|
2585
|
+
background: isActive ? colors.stepActive : colors.stepInactive,
|
|
2586
|
+
opacity: 0.3
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
)
|
|
2590
|
+
] }, i);
|
|
2591
|
+
})
|
|
2592
|
+
}
|
|
2593
|
+
);
|
|
2594
|
+
};
|
|
2595
|
+
var Chevron = ({ up }) => /* @__PURE__ */ jsx(
|
|
2596
|
+
"svg",
|
|
2597
|
+
{
|
|
2598
|
+
width: "16",
|
|
2599
|
+
height: "16",
|
|
2600
|
+
viewBox: "0 0 16 16",
|
|
2601
|
+
fill: "none",
|
|
2602
|
+
style: { transition: "transform .2s", transform: up ? "rotate(180deg)" : "none" },
|
|
2603
|
+
children: /* @__PURE__ */ jsx("path", { d: "M4 6L8 10L12 6", stroke: colors.textSecondary, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
2604
|
+
}
|
|
2605
|
+
);
|
|
2606
|
+
var DropdownField = ({
|
|
2607
|
+
label,
|
|
2608
|
+
placeholder,
|
|
2609
|
+
value,
|
|
2610
|
+
icon,
|
|
2611
|
+
focused,
|
|
2612
|
+
options,
|
|
2613
|
+
onSelect,
|
|
2614
|
+
onClick
|
|
2615
|
+
}) => {
|
|
2616
|
+
const [open, setOpen] = useState(false);
|
|
2617
|
+
const [triggerFocused, setTriggerFocused] = useState(false);
|
|
2618
|
+
const ref = useRef(null);
|
|
2619
|
+
useEffect(() => {
|
|
2620
|
+
if (!open) return;
|
|
2621
|
+
const handler = (e) => {
|
|
2622
|
+
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
2623
|
+
};
|
|
2624
|
+
document.addEventListener("mousedown", handler);
|
|
2625
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
2626
|
+
}, [open]);
|
|
2627
|
+
const hasOptions = options && options.length > 0;
|
|
2628
|
+
const handleClick = () => {
|
|
2629
|
+
if (hasOptions) {
|
|
2630
|
+
setOpen((p) => !p);
|
|
2631
|
+
} else {
|
|
2632
|
+
onClick?.();
|
|
2633
|
+
}
|
|
2634
|
+
};
|
|
2635
|
+
const handleSelect = (id) => {
|
|
2636
|
+
onSelect?.(id);
|
|
2637
|
+
setOpen(false);
|
|
2638
|
+
};
|
|
2639
|
+
const selected = hasOptions ? options.find((o) => o.id === value) : void 0;
|
|
2640
|
+
return /* @__PURE__ */ jsxs("div", { ref, style: { display: "flex", flexDirection: "column", gap: 8, width: "100%", position: "relative" }, children: [
|
|
2641
|
+
/* @__PURE__ */ jsx(
|
|
2642
|
+
"span",
|
|
2643
|
+
{
|
|
2644
|
+
style: {
|
|
2645
|
+
fontSize: 14,
|
|
2646
|
+
fontWeight: 400,
|
|
2647
|
+
lineHeight: 1.4,
|
|
2648
|
+
color: colors.textPrimary,
|
|
2649
|
+
fontFamily: fonts.family
|
|
2650
|
+
},
|
|
2651
|
+
children: label
|
|
2652
|
+
}
|
|
2653
|
+
),
|
|
2654
|
+
/* @__PURE__ */ jsxs(
|
|
2655
|
+
"button",
|
|
2656
|
+
{
|
|
2657
|
+
type: "button",
|
|
2658
|
+
onClick: handleClick,
|
|
2659
|
+
onFocus: () => setTriggerFocused(true),
|
|
2660
|
+
onBlur: () => setTriggerFocused(false),
|
|
2661
|
+
style: {
|
|
2662
|
+
display: "flex",
|
|
2663
|
+
alignItems: "center",
|
|
2664
|
+
justifyContent: "space-between",
|
|
2665
|
+
height: 44,
|
|
2666
|
+
padding: "0 16px",
|
|
2667
|
+
borderRadius: radii.input,
|
|
2668
|
+
border: `1px solid ${open || triggerFocused ? colors.borderFocused : colors.border}`,
|
|
2669
|
+
background: "transparent",
|
|
2670
|
+
cursor: "pointer",
|
|
2671
|
+
fontFamily: fonts.family,
|
|
2672
|
+
width: "100%",
|
|
2673
|
+
boxSizing: "border-box"
|
|
2674
|
+
},
|
|
2675
|
+
children: [
|
|
2676
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
2677
|
+
selected?.icon ?? icon,
|
|
2678
|
+
/* @__PURE__ */ jsx(
|
|
2679
|
+
"span",
|
|
2680
|
+
{
|
|
2681
|
+
style: {
|
|
2682
|
+
fontSize: 14,
|
|
2683
|
+
lineHeight: 1.4,
|
|
2684
|
+
color: value ? colors.textPrimary : colors.textSecondary,
|
|
2685
|
+
fontFamily: fonts.family
|
|
2686
|
+
},
|
|
2687
|
+
children: selected?.label ?? value ?? placeholder
|
|
2688
|
+
}
|
|
2689
|
+
)
|
|
2690
|
+
] }),
|
|
2691
|
+
/* @__PURE__ */ jsx(Chevron, { up: open })
|
|
2692
|
+
]
|
|
2693
|
+
}
|
|
2694
|
+
),
|
|
2695
|
+
open && hasOptions && /* @__PURE__ */ jsx(
|
|
2696
|
+
"div",
|
|
2697
|
+
{
|
|
2698
|
+
className: "dropdown-list-item",
|
|
2699
|
+
style: {
|
|
2700
|
+
position: "absolute",
|
|
2701
|
+
top: "calc(100% + 4px)",
|
|
2702
|
+
left: 0,
|
|
2703
|
+
right: 0,
|
|
2704
|
+
zIndex: 10,
|
|
2705
|
+
borderRadius: radii.input,
|
|
2706
|
+
border: `1px solid ${colors.border}`,
|
|
2707
|
+
background: colors.card,
|
|
2708
|
+
overflow: "hidden",
|
|
2709
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.4)"
|
|
2710
|
+
},
|
|
2711
|
+
children: options.map((opt) => /* @__PURE__ */ jsxs(
|
|
2712
|
+
"button",
|
|
2713
|
+
{
|
|
2714
|
+
type: "button",
|
|
2715
|
+
onClick: () => handleSelect(opt.id),
|
|
2716
|
+
style: {
|
|
2717
|
+
display: "flex",
|
|
2718
|
+
alignItems: "center",
|
|
2719
|
+
gap: 10,
|
|
2720
|
+
width: "100%",
|
|
2721
|
+
padding: "10px 16px",
|
|
2722
|
+
border: "none",
|
|
2723
|
+
background: opt.id === value ? "rgba(255,255,255,0.06)" : "transparent",
|
|
2724
|
+
cursor: "pointer",
|
|
2725
|
+
fontFamily: fonts.family,
|
|
2726
|
+
textAlign: "left",
|
|
2727
|
+
transition: "background .12s"
|
|
2728
|
+
},
|
|
2729
|
+
onMouseEnter: (e) => {
|
|
2730
|
+
e.currentTarget.style.background = "rgba(255,255,255,0.08)";
|
|
2731
|
+
},
|
|
2732
|
+
onMouseLeave: (e) => {
|
|
2733
|
+
e.currentTarget.style.background = opt.id === value ? "rgba(255,255,255,0.06)" : "transparent";
|
|
2734
|
+
},
|
|
2735
|
+
children: [
|
|
2736
|
+
opt.icon && /* @__PURE__ */ jsx("div", { style: { width: 28, height: 28, flexShrink: 0, display: "flex", alignItems: "center", justifyContent: "center" }, children: opt.icon }),
|
|
2737
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 1 }, children: [
|
|
2738
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, fontWeight: 500, color: colors.textPrimary }, children: opt.label }),
|
|
2739
|
+
opt.subtitle && /* @__PURE__ */ jsx("span", { style: { fontSize: 12, color: colors.textSecondary }, children: opt.subtitle })
|
|
2740
|
+
] })
|
|
2741
|
+
]
|
|
2742
|
+
},
|
|
2743
|
+
opt.id
|
|
2744
|
+
))
|
|
2745
|
+
}
|
|
2746
|
+
)
|
|
2747
|
+
] });
|
|
2748
|
+
};
|
|
2749
|
+
function getRemaining(expiresAt) {
|
|
2750
|
+
const end = typeof expiresAt === "string" ? new Date(expiresAt).getTime() : expiresAt;
|
|
2751
|
+
return Math.max(0, Math.floor((end - Date.now()) / 1e3));
|
|
2752
|
+
}
|
|
2753
|
+
function formatRemaining(seconds) {
|
|
2754
|
+
const m = Math.floor(seconds / 60);
|
|
2755
|
+
const s = seconds % 60;
|
|
2756
|
+
return `${m}:${s.toString().padStart(2, "0")}`;
|
|
2757
|
+
}
|
|
2758
|
+
function Countdown({
|
|
2759
|
+
expiresAt,
|
|
2760
|
+
expiredLabel = "Expired",
|
|
2761
|
+
style,
|
|
2762
|
+
isExpired = false,
|
|
2763
|
+
onExpired
|
|
2764
|
+
}) {
|
|
2765
|
+
const [remaining, setRemaining] = useState(() => getRemaining(expiresAt));
|
|
2766
|
+
const hasFiredExpired = useRef(false);
|
|
2767
|
+
useEffect(() => {
|
|
2768
|
+
hasFiredExpired.current = false;
|
|
2769
|
+
}, [expiresAt]);
|
|
2770
|
+
useEffect(() => {
|
|
2771
|
+
if (isExpired) {
|
|
2772
|
+
setRemaining(0);
|
|
2773
|
+
return;
|
|
2774
|
+
}
|
|
2775
|
+
const tick = () => {
|
|
2776
|
+
const r = getRemaining(expiresAt);
|
|
2777
|
+
setRemaining(r);
|
|
2778
|
+
if (r <= 0 && onExpired && !hasFiredExpired.current) {
|
|
2779
|
+
hasFiredExpired.current = true;
|
|
2780
|
+
onExpired();
|
|
2781
|
+
}
|
|
2782
|
+
};
|
|
2783
|
+
tick();
|
|
2784
|
+
const id = setInterval(tick, 1e3);
|
|
2785
|
+
return () => clearInterval(id);
|
|
2786
|
+
}, [expiresAt, isExpired, onExpired]);
|
|
2787
|
+
const text = remaining <= 0 ? expiredLabel : formatRemaining(remaining);
|
|
2788
|
+
const color = remaining <= 0 ? colors.warning : colors.textSecondary;
|
|
2789
|
+
return /* @__PURE__ */ jsxs("span", { style: { fontSize: 12, color, fontFamily: fonts.family, ...style }, children: [
|
|
2790
|
+
"Expires in ",
|
|
2791
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 600, color: "#fff" }, children: text })
|
|
2792
|
+
] });
|
|
2793
|
+
}
|
|
2794
|
+
function generateMatrix(data) {
|
|
2795
|
+
const qr = qrcode(0, "H");
|
|
2796
|
+
qr.addData(data);
|
|
2797
|
+
qr.make();
|
|
2798
|
+
const count = qr.getModuleCount();
|
|
2799
|
+
const matrix = [];
|
|
2800
|
+
for (let r = 0; r < count; r++) {
|
|
2801
|
+
const row = [];
|
|
2802
|
+
for (let c = 0; c < count; c++) {
|
|
2803
|
+
row.push(qr.isDark(r, c));
|
|
2804
|
+
}
|
|
2805
|
+
matrix.push(row);
|
|
2806
|
+
}
|
|
2807
|
+
return matrix;
|
|
2808
|
+
}
|
|
2809
|
+
function isFinderZone(row, col, size) {
|
|
2810
|
+
return row < 7 && col < 7 || row < 7 && col >= size - 7 || row >= size - 7 && col < 7;
|
|
2811
|
+
}
|
|
2812
|
+
var FinderEye = ({ ox, oy, s }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2813
|
+
/* @__PURE__ */ jsx("rect", { x: ox, y: oy, width: 7 * s, height: 7 * s, rx: s * 1.4, ry: s * 1.4, fill: "#fff" }),
|
|
2814
|
+
/* @__PURE__ */ jsx(
|
|
2815
|
+
"rect",
|
|
2816
|
+
{
|
|
2817
|
+
x: ox + s,
|
|
2818
|
+
y: oy + s,
|
|
2819
|
+
width: 5 * s,
|
|
2820
|
+
height: 5 * s,
|
|
2821
|
+
rx: s * 0.9,
|
|
2822
|
+
ry: s * 0.9,
|
|
2823
|
+
fill: colors.background
|
|
2824
|
+
}
|
|
2825
|
+
),
|
|
2826
|
+
/* @__PURE__ */ jsx(
|
|
2827
|
+
"rect",
|
|
2828
|
+
{
|
|
2829
|
+
x: ox + 2 * s,
|
|
2830
|
+
y: oy + 2 * s,
|
|
2831
|
+
width: 3 * s,
|
|
2832
|
+
height: 3 * s,
|
|
2833
|
+
rx: s * 0.7,
|
|
2834
|
+
ry: s * 0.7,
|
|
2835
|
+
fill: "#fff"
|
|
2836
|
+
}
|
|
2837
|
+
)
|
|
2838
|
+
] });
|
|
2839
|
+
var SVG_SIZE = 220;
|
|
2840
|
+
var QUIET_ZONE = 2;
|
|
2841
|
+
var StyledQR = ({ data }) => {
|
|
2842
|
+
const matrix = useMemo(() => generateMatrix(data), [data]);
|
|
2843
|
+
const n = matrix.length;
|
|
2844
|
+
const total = n + QUIET_ZONE * 2;
|
|
2845
|
+
const cell = SVG_SIZE / total;
|
|
2846
|
+
const off = QUIET_ZONE * cell;
|
|
2847
|
+
const dotR = cell * 0.42;
|
|
2848
|
+
const centerClearR = 3;
|
|
2849
|
+
const cx = n / 2;
|
|
2850
|
+
const cy = n / 2;
|
|
2851
|
+
const dots = [];
|
|
2852
|
+
for (let r = 0; r < n; r++) {
|
|
2853
|
+
for (let c = 0; c < n; c++) {
|
|
2854
|
+
if (!matrix[r][c]) continue;
|
|
2855
|
+
if (isFinderZone(r, c, n)) continue;
|
|
2856
|
+
if (Math.abs(c - cx) < centerClearR && Math.abs(r - cy) < centerClearR) continue;
|
|
2857
|
+
dots.push(
|
|
2858
|
+
/* @__PURE__ */ jsx(
|
|
2859
|
+
"circle",
|
|
2860
|
+
{
|
|
2861
|
+
cx: off + c * cell + cell / 2,
|
|
2862
|
+
cy: off + r * cell + cell / 2,
|
|
2863
|
+
r: dotR,
|
|
2864
|
+
fill: "#fff"
|
|
2865
|
+
},
|
|
2866
|
+
`${r}-${c}`
|
|
2867
|
+
)
|
|
2868
|
+
);
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
return /* @__PURE__ */ jsxs(
|
|
2872
|
+
"svg",
|
|
2873
|
+
{
|
|
2874
|
+
width: SVG_SIZE,
|
|
2875
|
+
height: SVG_SIZE,
|
|
2876
|
+
viewBox: `0 0 ${SVG_SIZE} ${SVG_SIZE}`,
|
|
2877
|
+
style: { borderRadius: 12 },
|
|
2878
|
+
children: [
|
|
2879
|
+
/* @__PURE__ */ jsx("rect", { width: SVG_SIZE, height: SVG_SIZE, fill: colors.background }),
|
|
2880
|
+
/* @__PURE__ */ jsx(FinderEye, { ox: off, oy: off, s: cell }),
|
|
2881
|
+
/* @__PURE__ */ jsx(FinderEye, { ox: off + (n - 7) * cell, oy: off, s: cell }),
|
|
2882
|
+
/* @__PURE__ */ jsx(FinderEye, { ox: off, oy: off + (n - 7) * cell, s: cell }),
|
|
2883
|
+
dots
|
|
2884
|
+
]
|
|
2885
|
+
}
|
|
2886
|
+
);
|
|
2887
|
+
};
|
|
2888
|
+
var CopyIcon = () => /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: [
|
|
2889
|
+
/* @__PURE__ */ jsx("rect", { x: "4.5", y: "4.5", width: "7", height: "7", rx: "1.5", stroke: colors.textPrimary, strokeWidth: "1.2" }),
|
|
2890
|
+
/* @__PURE__ */ jsx(
|
|
2891
|
+
"path",
|
|
2892
|
+
{
|
|
2893
|
+
d: "M9.5 4.5V3.5C9.5 2.67 8.83 2 8 2H3.5C2.67 2 2 2.67 2 3.5V8C2 8.83 2.67 9.5 3.5 9.5H4.5",
|
|
2894
|
+
stroke: colors.textPrimary,
|
|
2895
|
+
strokeWidth: "1.2"
|
|
2896
|
+
}
|
|
2897
|
+
)
|
|
2898
|
+
] });
|
|
2899
|
+
var DepositDetailsPanel = ({
|
|
2900
|
+
address,
|
|
2901
|
+
tokenIcon,
|
|
2902
|
+
minimumDeposit,
|
|
2903
|
+
onCopyAddress
|
|
2904
|
+
}) => {
|
|
2905
|
+
const canCopy = typeof address === "string" && address.trim().length > 0;
|
|
2906
|
+
const handleCopy = async () => {
|
|
2907
|
+
if (!canCopy) return;
|
|
2908
|
+
try {
|
|
2909
|
+
if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
|
|
2910
|
+
await navigator.clipboard.writeText(address);
|
|
2911
|
+
} else {
|
|
2912
|
+
const el = document.createElement("textarea");
|
|
2913
|
+
el.value = address;
|
|
2914
|
+
el.setAttribute("readonly", "");
|
|
2915
|
+
el.style.position = "absolute";
|
|
2916
|
+
el.style.left = "-9999px";
|
|
2917
|
+
document.body.appendChild(el);
|
|
2918
|
+
el.select();
|
|
2919
|
+
try {
|
|
2920
|
+
document.execCommand("copy");
|
|
2921
|
+
} catch {
|
|
2922
|
+
}
|
|
2923
|
+
document.body.removeChild(el);
|
|
2924
|
+
}
|
|
2925
|
+
} finally {
|
|
2926
|
+
onCopyAddress?.(address);
|
|
2927
|
+
}
|
|
2928
|
+
};
|
|
2929
|
+
return /* @__PURE__ */ jsxs(
|
|
2930
|
+
"div",
|
|
2931
|
+
{
|
|
2932
|
+
style: {
|
|
2933
|
+
display: "flex",
|
|
2934
|
+
flexDirection: "column",
|
|
2935
|
+
alignItems: "center",
|
|
2936
|
+
gap: 16,
|
|
2937
|
+
padding: "20px",
|
|
2938
|
+
borderRadius: radii.card,
|
|
2939
|
+
border: `1px solid ${colors.border}`,
|
|
2940
|
+
fontFamily: fonts.family
|
|
2941
|
+
},
|
|
2942
|
+
children: [
|
|
2943
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative", display: "inline-flex" }, children: [
|
|
2944
|
+
/* @__PURE__ */ jsx(StyledQR, { data: address }),
|
|
2945
|
+
tokenIcon && /* @__PURE__ */ jsx(
|
|
2946
|
+
"div",
|
|
2947
|
+
{
|
|
2948
|
+
style: {
|
|
2949
|
+
position: "absolute",
|
|
2950
|
+
top: "50%",
|
|
2951
|
+
left: "50%",
|
|
2952
|
+
transform: "translate(-50%, -50%)",
|
|
2953
|
+
width: 36,
|
|
2954
|
+
height: 36,
|
|
2955
|
+
borderRadius: "50%",
|
|
2956
|
+
background: "#3B5998",
|
|
2957
|
+
display: "flex",
|
|
2958
|
+
alignItems: "center",
|
|
2959
|
+
justifyContent: "center",
|
|
2960
|
+
boxShadow: `0 0 0 3px ${colors.background}`
|
|
2961
|
+
},
|
|
2962
|
+
children: tokenIcon
|
|
2963
|
+
}
|
|
2964
|
+
)
|
|
2965
|
+
] }),
|
|
2966
|
+
/* @__PURE__ */ jsx("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: 8 }, children: /* @__PURE__ */ jsx(
|
|
2967
|
+
"div",
|
|
2968
|
+
{
|
|
2969
|
+
style: {
|
|
2970
|
+
padding: "10px 14px",
|
|
2971
|
+
borderRadius: radii.input,
|
|
2972
|
+
background: "rgba(255,255,255,0.05)",
|
|
2973
|
+
fontSize: 13,
|
|
2974
|
+
color: colors.textPrimary,
|
|
2975
|
+
wordBreak: "break-all",
|
|
2976
|
+
lineHeight: 1.5
|
|
2977
|
+
},
|
|
2978
|
+
children: address
|
|
2979
|
+
}
|
|
2980
|
+
) }),
|
|
2981
|
+
minimumDeposit && /* @__PURE__ */ jsxs(
|
|
2982
|
+
"div",
|
|
2983
|
+
{
|
|
2984
|
+
style: {
|
|
2985
|
+
width: "100%",
|
|
2986
|
+
display: "flex",
|
|
2987
|
+
justifyContent: "space-between",
|
|
2988
|
+
fontSize: 13
|
|
2989
|
+
},
|
|
2990
|
+
children: [
|
|
2991
|
+
/* @__PURE__ */ jsx("span", { style: { color: colors.textSecondary }, children: "Minimum deposit" }),
|
|
2992
|
+
/* @__PURE__ */ jsx("span", { style: { color: colors.textPrimary, fontWeight: 500 }, children: minimumDeposit })
|
|
2993
|
+
]
|
|
2994
|
+
}
|
|
2995
|
+
),
|
|
2996
|
+
/* @__PURE__ */ jsxs(
|
|
2997
|
+
"button",
|
|
2998
|
+
{
|
|
2999
|
+
type: "button",
|
|
3000
|
+
onClick: handleCopy,
|
|
3001
|
+
disabled: !canCopy,
|
|
3002
|
+
style: {
|
|
3003
|
+
display: "flex",
|
|
3004
|
+
alignItems: "center",
|
|
3005
|
+
gap: 6,
|
|
3006
|
+
padding: "10px 28px",
|
|
3007
|
+
borderRadius: radii.pill,
|
|
3008
|
+
border: `1px solid ${colors.borderStrong}`,
|
|
3009
|
+
background: "transparent",
|
|
3010
|
+
color: colors.textPrimary,
|
|
3011
|
+
fontSize: 14,
|
|
3012
|
+
fontWeight: 500,
|
|
3013
|
+
cursor: canCopy ? "pointer" : "not-allowed",
|
|
3014
|
+
opacity: canCopy ? 1 : 0.6,
|
|
3015
|
+
fontFamily: fonts.family,
|
|
3016
|
+
transition: "background .15s"
|
|
3017
|
+
},
|
|
3018
|
+
onMouseEnter: (e) => {
|
|
3019
|
+
if (!canCopy) return;
|
|
3020
|
+
e.currentTarget.style.background = "rgba(255,255,255,0.06)";
|
|
3021
|
+
},
|
|
3022
|
+
onMouseLeave: (e) => {
|
|
3023
|
+
e.currentTarget.style.background = "transparent";
|
|
3024
|
+
},
|
|
3025
|
+
children: [
|
|
3026
|
+
/* @__PURE__ */ jsx(CopyIcon, {}),
|
|
3027
|
+
"Copy address"
|
|
3028
|
+
]
|
|
3029
|
+
}
|
|
3030
|
+
)
|
|
3031
|
+
]
|
|
3032
|
+
}
|
|
3033
|
+
);
|
|
3034
|
+
};
|
|
3035
|
+
var LockIcon = () => /* @__PURE__ */ jsxs("svg", { width: "48", height: "48", viewBox: "0 0 48 48", fill: "none", children: [
|
|
3036
|
+
/* @__PURE__ */ jsx("rect", { x: "10", y: "22", width: "28", height: "20", rx: "4", stroke: colors.textSecondary, strokeWidth: "2" }),
|
|
3037
|
+
/* @__PURE__ */ jsx("path", { d: "M16 22V16C16 11.5817 19.5817 8 24 8C28.4183 8 32 11.5817 32 16V22", stroke: colors.textSecondary, strokeWidth: "2", strokeLinecap: "round" }),
|
|
3038
|
+
/* @__PURE__ */ jsx("circle", { cx: "24", cy: "33", r: "3", fill: colors.textSecondary })
|
|
3039
|
+
] });
|
|
3040
|
+
var LoginRequiredOverlay = ({
|
|
3041
|
+
title,
|
|
3042
|
+
onSignIn,
|
|
3043
|
+
onClose
|
|
3044
|
+
}) => /* @__PURE__ */ jsx(ModalFrame, { onClose, contentStyle: { padding: "48px 24px" }, children: /* @__PURE__ */ jsxs(
|
|
3045
|
+
"div",
|
|
3046
|
+
{
|
|
3047
|
+
style: {
|
|
3048
|
+
display: "flex",
|
|
3049
|
+
flexDirection: "column",
|
|
3050
|
+
alignItems: "center",
|
|
3051
|
+
gap: 24,
|
|
3052
|
+
textAlign: "center"
|
|
3053
|
+
},
|
|
3054
|
+
children: [
|
|
3055
|
+
/* @__PURE__ */ jsx(LockIcon, {}),
|
|
3056
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
3057
|
+
/* @__PURE__ */ jsx(
|
|
3058
|
+
"h2",
|
|
3059
|
+
{
|
|
3060
|
+
style: {
|
|
3061
|
+
margin: 0,
|
|
3062
|
+
fontSize: 20,
|
|
3063
|
+
fontWeight: 600,
|
|
3064
|
+
color: colors.textPrimary
|
|
3065
|
+
},
|
|
3066
|
+
children: title
|
|
3067
|
+
}
|
|
3068
|
+
),
|
|
3069
|
+
/* @__PURE__ */ jsx(
|
|
3070
|
+
"p",
|
|
3071
|
+
{
|
|
3072
|
+
style: {
|
|
3073
|
+
margin: 0,
|
|
3074
|
+
fontSize: 14,
|
|
3075
|
+
color: colors.textSecondary,
|
|
3076
|
+
lineHeight: 1.5
|
|
3077
|
+
},
|
|
3078
|
+
children: "Please sign in to continue"
|
|
3079
|
+
}
|
|
3080
|
+
)
|
|
3081
|
+
] }),
|
|
3082
|
+
onSignIn && /* @__PURE__ */ jsx(
|
|
3083
|
+
"button",
|
|
3084
|
+
{
|
|
3085
|
+
type: "button",
|
|
3086
|
+
onClick: onSignIn,
|
|
3087
|
+
style: {
|
|
3088
|
+
padding: "12px 48px",
|
|
3089
|
+
borderRadius: radii.full,
|
|
3090
|
+
border: "none",
|
|
3091
|
+
background: colors.textPrimary,
|
|
3092
|
+
color: "#15181D",
|
|
3093
|
+
fontSize: 16,
|
|
3094
|
+
fontWeight: 500,
|
|
3095
|
+
fontFamily: fonts.family,
|
|
3096
|
+
cursor: "pointer"
|
|
3097
|
+
},
|
|
3098
|
+
children: "Sign In"
|
|
3099
|
+
}
|
|
3100
|
+
)
|
|
3101
|
+
]
|
|
3102
|
+
}
|
|
3103
|
+
) });
|
|
3104
|
+
function useSession() {
|
|
3105
|
+
const [session, setSession] = useState(
|
|
3106
|
+
() => sessionStore.getState().session
|
|
3107
|
+
);
|
|
3108
|
+
useEffect(() => {
|
|
3109
|
+
const unsub = sessionStore.on("session:changed", setSession);
|
|
3110
|
+
return () => {
|
|
3111
|
+
unsub();
|
|
3112
|
+
};
|
|
3113
|
+
}, []);
|
|
3114
|
+
return session;
|
|
3115
|
+
}
|
|
3116
|
+
var BackArrow = () => /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M15 6L9 12L15 18", stroke: colors.textPrimary, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
3117
|
+
var TransferIcon = () => /* @__PURE__ */ jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
|
|
3118
|
+
/* @__PURE__ */ jsx("circle", { cx: "18", cy: "18", r: "18", fill: "rgba(255,255,255,0.08)" }),
|
|
3119
|
+
/* @__PURE__ */ jsx("circle", { cx: "18", cy: "18", r: "7", stroke: colors.textPrimary, strokeWidth: "1.5" }),
|
|
3120
|
+
/* @__PURE__ */ jsx("circle", { cx: "18", cy: "18", r: "2.5", fill: colors.textPrimary }),
|
|
3121
|
+
/* @__PURE__ */ jsx("path", { d: "M18 7V11", stroke: colors.textPrimary, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
3122
|
+
/* @__PURE__ */ jsx("path", { d: "M18 25V29", stroke: colors.textPrimary, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
3123
|
+
/* @__PURE__ */ jsx("path", { d: "M7 18H11", stroke: colors.textPrimary, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
3124
|
+
/* @__PURE__ */ jsx("path", { d: "M25 18H29", stroke: colors.textPrimary, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
3125
|
+
] });
|
|
3126
|
+
var FiatIcon = () => /* @__PURE__ */ jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
|
|
3127
|
+
/* @__PURE__ */ jsx("circle", { cx: "18", cy: "18", r: "18", fill: "rgba(255,255,255,0.06)" }),
|
|
3128
|
+
/* @__PURE__ */ jsx("circle", { cx: "18", cy: "18", r: "10", stroke: colors.textSecondary, strokeWidth: "1.5" }),
|
|
3129
|
+
/* @__PURE__ */ jsx("path", { d: "M18 12V24", stroke: colors.textSecondary, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
3130
|
+
/* @__PURE__ */ jsx("path", { d: "M15 15.5C15 14.12 16.34 13 18 13C19.66 13 21 14.12 21 15.5C21 16.88 19.66 18 18 18C16.34 18 15 19.12 15 20.5C15 21.88 16.34 23 18 23C19.66 23 21 21.88 21 20.5", stroke: colors.textSecondary, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
3131
|
+
] });
|
|
3132
|
+
var DefaultCryptoIcons = () => {
|
|
3133
|
+
const tokens = [
|
|
3134
|
+
{ label: "B", bg: "#F7931A" },
|
|
3135
|
+
{ label: "E", bg: "#627EEA" },
|
|
3136
|
+
{ label: "\u2261", bg: "#26A17B" },
|
|
3137
|
+
{ label: "$", bg: "#2775CA" },
|
|
3138
|
+
{ label: "S", bg: "#9945FF" },
|
|
3139
|
+
{ label: "A", bg: "#E84142" }
|
|
3140
|
+
];
|
|
3141
|
+
return /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 0 }, children: tokens.map((t, i) => /* @__PURE__ */ jsx(
|
|
3142
|
+
"div",
|
|
3143
|
+
{
|
|
3144
|
+
style: {
|
|
3145
|
+
width: 24,
|
|
3146
|
+
height: 24,
|
|
3147
|
+
borderRadius: "50%",
|
|
3148
|
+
background: t.bg,
|
|
3149
|
+
display: "flex",
|
|
3150
|
+
alignItems: "center",
|
|
3151
|
+
justifyContent: "center",
|
|
3152
|
+
fontSize: 11,
|
|
3153
|
+
fontWeight: 700,
|
|
3154
|
+
color: "#fff",
|
|
3155
|
+
marginLeft: i > 0 ? -4 : 0,
|
|
3156
|
+
border: `2px solid ${colors.card}`,
|
|
3157
|
+
boxSizing: "content-box"
|
|
3158
|
+
},
|
|
3159
|
+
children: t.label
|
|
3160
|
+
},
|
|
3161
|
+
i
|
|
3162
|
+
)) });
|
|
3163
|
+
};
|
|
3164
|
+
function chainsToTokenOptions(chains) {
|
|
3165
|
+
const bySymbol = /* @__PURE__ */ new Map();
|
|
3166
|
+
for (const c of chains) {
|
|
3167
|
+
for (const t of c.tokens) {
|
|
3168
|
+
if (!bySymbol.has(t.symbol)) bySymbol.set(t.symbol, { symbol: t.symbol, decimals: t.decimals });
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
return Array.from(bySymbol.entries()).map(([id, { symbol }]) => ({
|
|
3172
|
+
id,
|
|
3173
|
+
label: symbol,
|
|
3174
|
+
subtitle: symbol
|
|
3175
|
+
}));
|
|
3176
|
+
}
|
|
3177
|
+
function chainsToChainOptionsForToken(chains, tokenSymbol) {
|
|
3178
|
+
return chains.filter((c) => c.tokens.some((t) => t.symbol === tokenSymbol)).map((c) => ({
|
|
3179
|
+
id: c.chain_id,
|
|
3180
|
+
label: c.network,
|
|
3181
|
+
subtitle: `chainId: ${c.chain_id}`,
|
|
3182
|
+
icon: /* @__PURE__ */ jsx(
|
|
3183
|
+
"span",
|
|
3184
|
+
{
|
|
3185
|
+
style: {
|
|
3186
|
+
display: "inline-flex",
|
|
3187
|
+
alignItems: "center",
|
|
3188
|
+
justifyContent: "center",
|
|
3189
|
+
minWidth: 28,
|
|
3190
|
+
height: 28,
|
|
3191
|
+
padding: "0 6px",
|
|
3192
|
+
borderRadius: radii.card,
|
|
3193
|
+
background: "rgba(255,255,255,0.08)",
|
|
3194
|
+
fontSize: 12,
|
|
3195
|
+
fontWeight: 600,
|
|
3196
|
+
color: colors.textPrimary,
|
|
3197
|
+
fontFamily: fonts.family
|
|
3198
|
+
},
|
|
3199
|
+
children: c.network
|
|
3200
|
+
}
|
|
3201
|
+
)
|
|
3202
|
+
}));
|
|
3203
|
+
}
|
|
3204
|
+
function getTokenAddressForChain(chains, chainId, tokenSymbol) {
|
|
3205
|
+
const chain = chains.find((c) => c.chain_id === chainId);
|
|
3206
|
+
return chain?.tokens.find((t) => t.symbol === tokenSymbol)?.address;
|
|
3207
|
+
}
|
|
3208
|
+
var FUNDING_TOKEN_SYMBOL = getEnv("FUNDING_TOKEN_SYMBOL");
|
|
3209
|
+
var DepositModal = ({
|
|
3210
|
+
token,
|
|
3211
|
+
chain,
|
|
3212
|
+
tokenOptions: tokenOptionsProp,
|
|
3213
|
+
chainOptions: chainOptionsProp,
|
|
3214
|
+
depositAddress,
|
|
3215
|
+
minimumDeposit,
|
|
3216
|
+
qrCenterIcon,
|
|
3217
|
+
cryptoIcons,
|
|
3218
|
+
depositAmount,
|
|
3219
|
+
onShowToast,
|
|
3220
|
+
txHash,
|
|
3221
|
+
explorerTxUrl,
|
|
3222
|
+
onTokenSelect,
|
|
3223
|
+
onChainSelect,
|
|
3224
|
+
onCopyAddress,
|
|
3225
|
+
onBuyCrypto,
|
|
3226
|
+
onSignIn,
|
|
3227
|
+
onBack,
|
|
3228
|
+
onClose
|
|
3229
|
+
}) => {
|
|
3230
|
+
const session = useSession();
|
|
3231
|
+
const [view, setView] = useState("entry");
|
|
3232
|
+
const [copySuccessMessage, setCopySuccessMessage] = useState(null);
|
|
3233
|
+
const [apiChains, setApiChains] = useState(null);
|
|
3234
|
+
const [apiQuote, setApiQuote] = useState(null);
|
|
3235
|
+
const [loadingChains, setLoadingChains] = useState(false);
|
|
3236
|
+
const [loadingQuote, setLoadingQuote] = useState(false);
|
|
3237
|
+
const [quoteRefreshKey, setQuoteRefreshKey] = useState(0);
|
|
3238
|
+
const [internalDepositAddress, setInternalDepositAddress] = useState(void 0);
|
|
3239
|
+
const lastEmittedAddressRef = useRef(void 0);
|
|
3240
|
+
const lastEmittedChainRef = useRef(void 0);
|
|
3241
|
+
const tokenOptions = useMemo(() => {
|
|
3242
|
+
if (tokenOptionsProp?.length) return tokenOptionsProp;
|
|
3243
|
+
if (!apiChains?.length) return void 0;
|
|
3244
|
+
return chainsToTokenOptions(apiChains);
|
|
3245
|
+
}, [tokenOptionsProp, apiChains]);
|
|
3246
|
+
const chainOptions = useMemo(() => {
|
|
3247
|
+
if (chainOptionsProp?.length) return chainOptionsProp;
|
|
3248
|
+
if (!apiChains?.length || !token) return void 0;
|
|
3249
|
+
return chainsToChainOptionsForToken(apiChains, token);
|
|
3250
|
+
}, [chainOptionsProp, apiChains, token]);
|
|
3251
|
+
useEffect(() => {
|
|
3252
|
+
if (chainOptions?.length !== 1 || !onChainSelect) return;
|
|
3253
|
+
const onlyId = chainOptions[0].id;
|
|
3254
|
+
if (chain === onlyId) return;
|
|
3255
|
+
onChainSelect(onlyId);
|
|
3256
|
+
}, [chainOptions, chain, onChainSelect]);
|
|
3257
|
+
useEffect(() => {
|
|
3258
|
+
if (view !== "transfer") return;
|
|
3259
|
+
setLoadingChains(true);
|
|
3260
|
+
getChains().then((res) => setApiChains(res?.chains ?? {})).finally(() => setLoadingChains(false));
|
|
3261
|
+
}, [view]);
|
|
3262
|
+
useEffect(() => {
|
|
3263
|
+
if (view !== "transfer") return;
|
|
3264
|
+
if (!session?.address || !chain) return;
|
|
3265
|
+
registerPlatform({
|
|
3266
|
+
platform_contract_address: session.address,
|
|
3267
|
+
chain_id: chain
|
|
3268
|
+
}).then((res) => {
|
|
3269
|
+
if (res?.deposit_address) {
|
|
3270
|
+
setInternalDepositAddress(res.deposit_address);
|
|
3271
|
+
}
|
|
3272
|
+
}).catch(() => {
|
|
3273
|
+
});
|
|
3274
|
+
}, [view, chain, session?.address]);
|
|
3275
|
+
useEffect(() => {
|
|
3276
|
+
if (!apiChains?.length || !token || !chain) {
|
|
3277
|
+
setApiQuote(null);
|
|
3278
|
+
return;
|
|
3279
|
+
}
|
|
3280
|
+
const tokenAddress = getTokenAddressForChain(apiChains, chain, token);
|
|
3281
|
+
if (!tokenAddress) {
|
|
3282
|
+
setApiQuote(null);
|
|
3283
|
+
return;
|
|
3284
|
+
}
|
|
3285
|
+
setLoadingQuote(true);
|
|
3286
|
+
console.log("setLoadingQuote", tokenAddress, depositAmount);
|
|
3287
|
+
quote({
|
|
3288
|
+
direction: "deposit",
|
|
3289
|
+
chain_id: chain,
|
|
3290
|
+
token_address: tokenAddress,
|
|
3291
|
+
token_amount: depositAmount || void 0
|
|
3292
|
+
}).then((q) => setApiQuote(q ?? null)).catch((err) => {
|
|
3293
|
+
const message = err?.message ?? String(err);
|
|
3294
|
+
console.error("setLoadingQuote", message);
|
|
3295
|
+
if (onShowToast) onShowToast(message);
|
|
3296
|
+
setApiQuote({
|
|
3297
|
+
token_address: tokenAddress,
|
|
3298
|
+
token_symbol: token,
|
|
3299
|
+
token_decimals: 18,
|
|
3300
|
+
rate: "1",
|
|
3301
|
+
chain_id: Number(chain) || 56,
|
|
3302
|
+
deposit_address: "0x" + "0".repeat(39) + "1",
|
|
3303
|
+
dst_token_amount: depositAmount ?? "0",
|
|
3304
|
+
expires_at: new Date(Date.now() + 6e4).toISOString()
|
|
3305
|
+
});
|
|
3306
|
+
}).finally(() => setLoadingQuote(false));
|
|
3307
|
+
}, [apiChains, token, chain, depositAmount, quoteRefreshKey, onShowToast]);
|
|
3308
|
+
useEffect(() => {
|
|
3309
|
+
if (!chain) return;
|
|
3310
|
+
if (!depositAddress) return;
|
|
3311
|
+
if (lastEmittedAddressRef.current === depositAddress && lastEmittedChainRef.current === chain) {
|
|
3312
|
+
return;
|
|
3313
|
+
}
|
|
3314
|
+
lastEmittedAddressRef.current = depositAddress;
|
|
3315
|
+
lastEmittedChainRef.current = chain;
|
|
3316
|
+
}, [depositAddress, chain]);
|
|
3317
|
+
const handleQuoteExpired = useCallback(() => {
|
|
3318
|
+
setQuoteRefreshKey((k) => k + 1);
|
|
3319
|
+
}, []);
|
|
3320
|
+
useEffect(() => {
|
|
3321
|
+
if (txHash && chain && onShowToast) {
|
|
3322
|
+
onShowToast("Transfer confirmed");
|
|
3323
|
+
}
|
|
3324
|
+
}, [txHash, chain, onShowToast]);
|
|
3325
|
+
if (!session) {
|
|
3326
|
+
return /* @__PURE__ */ jsx(LoginRequiredOverlay, { title: "Deposit", onSignIn, onClose });
|
|
3327
|
+
}
|
|
3328
|
+
const goToEntry = () => {
|
|
3329
|
+
setView("entry");
|
|
3330
|
+
onBack?.();
|
|
3331
|
+
};
|
|
3332
|
+
const handleCopyAddress = useCallback((address) => {
|
|
3333
|
+
onCopyAddress?.(address);
|
|
3334
|
+
onShowToast?.("Address copied");
|
|
3335
|
+
setCopySuccessMessage("Address copied");
|
|
3336
|
+
}, [onCopyAddress, onShowToast]);
|
|
3337
|
+
useEffect(() => {
|
|
3338
|
+
if (!copySuccessMessage) return;
|
|
3339
|
+
const t = setTimeout(() => setCopySuccessMessage(null), 2e3);
|
|
3340
|
+
return () => clearTimeout(t);
|
|
3341
|
+
}, [copySuccessMessage]);
|
|
3342
|
+
return /* @__PURE__ */ jsxs(ModalFrame, { onClose, contentStyle: { padding: "24px", position: "relative" }, children: [
|
|
3343
|
+
copySuccessMessage && /* @__PURE__ */ jsx(
|
|
3344
|
+
"div",
|
|
3345
|
+
{
|
|
3346
|
+
style: {
|
|
3347
|
+
position: "absolute",
|
|
3348
|
+
bottom: 24,
|
|
3349
|
+
left: "50%",
|
|
3350
|
+
transform: "translateX(-50%)",
|
|
3351
|
+
padding: "10px 20px",
|
|
3352
|
+
borderRadius: 8,
|
|
3353
|
+
background: "var(--pm-colors-card, #1a1a2e)",
|
|
3354
|
+
color: "var(--pm-colors-textPrimary, #fff)",
|
|
3355
|
+
fontSize: 13,
|
|
3356
|
+
fontWeight: 500,
|
|
3357
|
+
boxShadow: "0 4px 12px rgba(0,0,0,.25)",
|
|
3358
|
+
zIndex: 10
|
|
3359
|
+
},
|
|
3360
|
+
children: copySuccessMessage
|
|
3361
|
+
}
|
|
3362
|
+
),
|
|
3363
|
+
view === "entry" ? /* @__PURE__ */ jsx(
|
|
3364
|
+
EntryView,
|
|
3365
|
+
{
|
|
3366
|
+
cryptoIcons,
|
|
3367
|
+
onTransferCrypto: () => setView("transfer"),
|
|
3368
|
+
onBuyCrypto
|
|
3369
|
+
}
|
|
3370
|
+
) : /* @__PURE__ */ jsx(
|
|
3371
|
+
TransferView,
|
|
3372
|
+
{
|
|
3373
|
+
token,
|
|
3374
|
+
chain,
|
|
3375
|
+
tokenOptions,
|
|
3376
|
+
chainOptions,
|
|
3377
|
+
depositAddress: depositAddress ?? internalDepositAddress,
|
|
3378
|
+
minimumDeposit,
|
|
3379
|
+
qrCenterIcon,
|
|
3380
|
+
quote: apiQuote,
|
|
3381
|
+
quoteLoading: loadingQuote,
|
|
3382
|
+
txHash,
|
|
3383
|
+
chainIdForExplorer: chain,
|
|
3384
|
+
explorerTxUrl,
|
|
3385
|
+
loadingChains,
|
|
3386
|
+
onTokenSelect,
|
|
3387
|
+
onChainSelect,
|
|
3388
|
+
onCopyAddress: handleCopyAddress,
|
|
3389
|
+
onQuoteExpired: handleQuoteExpired,
|
|
3390
|
+
onRefreshQuote: () => {
|
|
3391
|
+
if (!apiChains?.length || !token || !chain) return;
|
|
3392
|
+
const tokenAddress = getTokenAddressForChain(apiChains, chain, token);
|
|
3393
|
+
if (tokenAddress) {
|
|
3394
|
+
setLoadingQuote(true);
|
|
3395
|
+
quote({ direction: "deposit", chain_id: chain, token_address: tokenAddress, token_amount: depositAmount }).then((q) => setApiQuote(q ?? null)).catch(() => {
|
|
3396
|
+
setApiQuote({
|
|
3397
|
+
token_address: tokenAddress,
|
|
3398
|
+
token_symbol: token,
|
|
3399
|
+
token_decimals: 18,
|
|
3400
|
+
rate: "1",
|
|
3401
|
+
chain_id: Number(chain) || 56,
|
|
3402
|
+
deposit_address: "0x" + "0".repeat(39) + "1",
|
|
3403
|
+
dst_token_amount: depositAmount ?? "0",
|
|
3404
|
+
expires_at: new Date(Date.now() + 6e4).toISOString()
|
|
3405
|
+
});
|
|
3406
|
+
}).finally(() => setLoadingQuote(false));
|
|
3407
|
+
}
|
|
3408
|
+
},
|
|
3409
|
+
onShowToast,
|
|
3410
|
+
onBack: goToEntry
|
|
3411
|
+
}
|
|
3412
|
+
)
|
|
3413
|
+
] });
|
|
3414
|
+
};
|
|
3415
|
+
var EntryView = ({
|
|
3416
|
+
cryptoIcons,
|
|
3417
|
+
onTransferCrypto,
|
|
3418
|
+
onBuyCrypto: _onBuyCrypto
|
|
3419
|
+
}) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 24 }, children: [
|
|
3420
|
+
/* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: 24, fontWeight: 600, lineHeight: 1.4 }, children: "Deposit" }),
|
|
3421
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
|
|
3422
|
+
/* @__PURE__ */ jsxs(
|
|
3423
|
+
"button",
|
|
3424
|
+
{
|
|
3425
|
+
type: "button",
|
|
3426
|
+
onClick: onTransferCrypto,
|
|
3427
|
+
style: {
|
|
3428
|
+
display: "flex",
|
|
3429
|
+
alignItems: "center",
|
|
3430
|
+
gap: 14,
|
|
3431
|
+
padding: "18px 20px",
|
|
3432
|
+
borderRadius: radii.card,
|
|
3433
|
+
border: `1px solid ${colors.border}`,
|
|
3434
|
+
background: "transparent",
|
|
3435
|
+
cursor: "pointer",
|
|
3436
|
+
textAlign: "left",
|
|
3437
|
+
fontFamily: fonts.family,
|
|
3438
|
+
width: "100%",
|
|
3439
|
+
transition: "border-color .15s"
|
|
3440
|
+
},
|
|
3441
|
+
onMouseEnter: (e) => {
|
|
3442
|
+
e.target.closest("button").style.borderColor = colors.borderStrong;
|
|
3443
|
+
},
|
|
3444
|
+
onMouseLeave: (e) => {
|
|
3445
|
+
e.target.closest("button").style.borderColor = colors.border;
|
|
3446
|
+
},
|
|
3447
|
+
children: [
|
|
3448
|
+
/* @__PURE__ */ jsx(TransferIcon, {}),
|
|
3449
|
+
/* @__PURE__ */ jsxs("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
3450
|
+
/* @__PURE__ */ jsx("span", { style: { color: colors.textPrimary, fontSize: 16, fontWeight: 600 }, children: "Transfer Crypto" }),
|
|
3451
|
+
/* @__PURE__ */ jsx("span", { style: { color: colors.textSecondary, fontSize: 13 }, children: "No limit \xB7 Instant" })
|
|
3452
|
+
] }),
|
|
3453
|
+
cryptoIcons ?? /* @__PURE__ */ jsx(DefaultCryptoIcons, {})
|
|
3454
|
+
]
|
|
3455
|
+
}
|
|
3456
|
+
),
|
|
3457
|
+
/* @__PURE__ */ jsxs(
|
|
3458
|
+
"div",
|
|
3459
|
+
{
|
|
3460
|
+
style: {
|
|
3461
|
+
display: "flex",
|
|
3462
|
+
alignItems: "center",
|
|
3463
|
+
gap: 14,
|
|
3464
|
+
padding: "18px 20px",
|
|
3465
|
+
borderRadius: radii.card,
|
|
3466
|
+
border: `1px solid ${colors.border}`,
|
|
3467
|
+
opacity: 0.55
|
|
3468
|
+
},
|
|
3469
|
+
children: [
|
|
3470
|
+
/* @__PURE__ */ jsx(FiatIcon, {}),
|
|
3471
|
+
/* @__PURE__ */ jsxs("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
3472
|
+
/* @__PURE__ */ jsx("span", { style: { color: colors.textSecondary, fontSize: 16, fontWeight: 600 }, children: "Buy Crypto" }),
|
|
3473
|
+
/* @__PURE__ */ jsx("span", { style: { color: colors.textSecondary, fontSize: 13 }, children: "Debit card, credit card, ACH" })
|
|
3474
|
+
] }),
|
|
3475
|
+
/* @__PURE__ */ jsx(
|
|
3476
|
+
"span",
|
|
3477
|
+
{
|
|
3478
|
+
style: {
|
|
3479
|
+
padding: "5px 12px",
|
|
3480
|
+
borderRadius: radii.pill,
|
|
3481
|
+
border: `1px solid ${colors.border}`,
|
|
3482
|
+
fontSize: 12,
|
|
3483
|
+
fontWeight: 500,
|
|
3484
|
+
color: colors.textSecondary,
|
|
3485
|
+
whiteSpace: "nowrap"
|
|
3486
|
+
},
|
|
3487
|
+
children: "Coming Soon"
|
|
3488
|
+
}
|
|
3489
|
+
)
|
|
3490
|
+
]
|
|
3491
|
+
}
|
|
3492
|
+
)
|
|
3493
|
+
] })
|
|
3494
|
+
] });
|
|
3495
|
+
var TransferView = ({
|
|
3496
|
+
token,
|
|
3497
|
+
chain,
|
|
3498
|
+
tokenOptions,
|
|
3499
|
+
chainOptions,
|
|
3500
|
+
depositAddress,
|
|
3501
|
+
minimumDeposit,
|
|
3502
|
+
qrCenterIcon,
|
|
3503
|
+
quote: quoteData,
|
|
3504
|
+
quoteLoading,
|
|
3505
|
+
txHash,
|
|
3506
|
+
chainIdForExplorer,
|
|
3507
|
+
explorerTxUrl,
|
|
3508
|
+
loadingChains,
|
|
3509
|
+
onTokenSelect,
|
|
3510
|
+
onChainSelect,
|
|
3511
|
+
onCopyAddress,
|
|
3512
|
+
onQuoteExpired,
|
|
3513
|
+
onRefreshQuote,
|
|
3514
|
+
onShowToast,
|
|
3515
|
+
onBack
|
|
3516
|
+
}) => {
|
|
3517
|
+
const activeStep = chain ? 2 : token ? 1 : 0;
|
|
3518
|
+
const stepActive = [!!token, !!chain, !!quoteData];
|
|
3519
|
+
const quoteExpired = useMemo(() => {
|
|
3520
|
+
if (!quoteData?.expires_at) return false;
|
|
3521
|
+
try {
|
|
3522
|
+
return new Date(quoteData.expires_at).getTime() < Date.now();
|
|
3523
|
+
} catch {
|
|
3524
|
+
return false;
|
|
3525
|
+
}
|
|
3526
|
+
}, [quoteData?.expires_at]);
|
|
3527
|
+
const didToastWait = useRef(false);
|
|
3528
|
+
useEffect(() => {
|
|
3529
|
+
if (!depositAddress || !onShowToast || didToastWait.current) return;
|
|
3530
|
+
didToastWait.current = true;
|
|
3531
|
+
onShowToast("Please wait for deposit-address balance to update");
|
|
3532
|
+
}, [depositAddress, onShowToast]);
|
|
3533
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 24 }, children: [
|
|
3534
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
3535
|
+
onBack && /* @__PURE__ */ jsx(
|
|
3536
|
+
"button",
|
|
3537
|
+
{
|
|
3538
|
+
type: "button",
|
|
3539
|
+
onClick: onBack,
|
|
3540
|
+
style: {
|
|
3541
|
+
background: "transparent",
|
|
3542
|
+
border: "none",
|
|
3543
|
+
cursor: "pointer",
|
|
3544
|
+
padding: 0,
|
|
3545
|
+
display: "flex",
|
|
3546
|
+
alignItems: "center"
|
|
3547
|
+
},
|
|
3548
|
+
children: /* @__PURE__ */ jsx(BackArrow, {})
|
|
3549
|
+
}
|
|
3550
|
+
),
|
|
3551
|
+
/* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: 24, fontWeight: 600, lineHeight: 1.4 }, children: "Transfer Crypto" })
|
|
3552
|
+
] }) }),
|
|
3553
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 16, position: "relative" }, children: [
|
|
3554
|
+
/* @__PURE__ */ jsx(StepIndicator, { steps: 3, stepActive, activeStep }),
|
|
3555
|
+
/* @__PURE__ */ jsxs("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: 40 }, children: [
|
|
3556
|
+
/* @__PURE__ */ jsx(
|
|
3557
|
+
DropdownField,
|
|
3558
|
+
{
|
|
3559
|
+
label: "Select token",
|
|
3560
|
+
placeholder: loadingChains ? "Loading\u2026" : "Token",
|
|
3561
|
+
value: token,
|
|
3562
|
+
options: tokenOptions,
|
|
3563
|
+
onSelect: onTokenSelect
|
|
3564
|
+
}
|
|
3565
|
+
),
|
|
3566
|
+
/* @__PURE__ */ jsx(
|
|
3567
|
+
DropdownField,
|
|
3568
|
+
{
|
|
3569
|
+
label: "Select chain",
|
|
3570
|
+
placeholder: loadingChains ? "Loading\u2026" : "Chain",
|
|
3571
|
+
value: chain,
|
|
3572
|
+
options: chainOptions,
|
|
3573
|
+
onSelect: onChainSelect
|
|
3574
|
+
}
|
|
3575
|
+
),
|
|
3576
|
+
quoteData && token && chain && /* @__PURE__ */ jsx(
|
|
3577
|
+
"div",
|
|
3578
|
+
{
|
|
3579
|
+
id: "quote-panel",
|
|
3580
|
+
style: {
|
|
3581
|
+
padding: "12px 16px",
|
|
3582
|
+
borderRadius: radii.card,
|
|
3583
|
+
margin: "-10px 0",
|
|
3584
|
+
border: `1px solid ${colors.border}`,
|
|
3585
|
+
display: "flex",
|
|
3586
|
+
flexDirection: "column",
|
|
3587
|
+
gap: 8
|
|
3588
|
+
},
|
|
3589
|
+
children: quoteLoading ? /* @__PURE__ */ jsx("span", { style: { fontSize: 13, color: colors.textSecondary }, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3590
|
+
/* @__PURE__ */ jsxs("span", { style: { fontSize: 13, color: colors.textSecondary }, children: [
|
|
3591
|
+
"1 ",
|
|
3592
|
+
quoteData.token_symbol,
|
|
3593
|
+
" = ",
|
|
3594
|
+
quoteData.rate,
|
|
3595
|
+
" ",
|
|
3596
|
+
FUNDING_TOKEN_SYMBOL
|
|
3597
|
+
] }),
|
|
3598
|
+
quoteData.expires_at && /* @__PURE__ */ jsx(
|
|
3599
|
+
Countdown,
|
|
3600
|
+
{
|
|
3601
|
+
expiresAt: quoteData.expires_at,
|
|
3602
|
+
isExpired: quoteExpired,
|
|
3603
|
+
onExpired: onQuoteExpired
|
|
3604
|
+
}
|
|
3605
|
+
),
|
|
3606
|
+
quoteExpired && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
3607
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 13, color: "#f59e0b" }, children: "Quote expired, please refresh" }),
|
|
3608
|
+
onRefreshQuote && /* @__PURE__ */ jsx(
|
|
3609
|
+
"button",
|
|
3610
|
+
{
|
|
3611
|
+
type: "button",
|
|
3612
|
+
onClick: onRefreshQuote,
|
|
3613
|
+
style: {
|
|
3614
|
+
padding: "4px 12px",
|
|
3615
|
+
fontSize: 12,
|
|
3616
|
+
borderRadius: radii.pill,
|
|
3617
|
+
border: `1px solid ${colors.border}`,
|
|
3618
|
+
background: "transparent",
|
|
3619
|
+
color: colors.textPrimary,
|
|
3620
|
+
cursor: "pointer",
|
|
3621
|
+
fontFamily: fonts.family
|
|
3622
|
+
},
|
|
3623
|
+
children: "Refresh"
|
|
3624
|
+
}
|
|
3625
|
+
)
|
|
3626
|
+
] })
|
|
3627
|
+
] })
|
|
3628
|
+
}
|
|
3629
|
+
),
|
|
3630
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8, marginTop: "-5px" }, id: "deposit-details", children: [
|
|
3631
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: "Deposit details" }),
|
|
3632
|
+
depositAddress ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3633
|
+
/* @__PURE__ */ jsx(
|
|
3634
|
+
DepositDetailsPanel,
|
|
3635
|
+
{
|
|
3636
|
+
address: depositAddress,
|
|
3637
|
+
tokenIcon: qrCenterIcon,
|
|
3638
|
+
minimumDeposit,
|
|
3639
|
+
onCopyAddress
|
|
3640
|
+
}
|
|
3641
|
+
),
|
|
3642
|
+
txHash && chainIdForExplorer && explorerTxUrl && /* @__PURE__ */ jsx(
|
|
3643
|
+
"a",
|
|
3644
|
+
{
|
|
3645
|
+
href: explorerTxUrl(chainIdForExplorer, txHash),
|
|
3646
|
+
target: "_blank",
|
|
3647
|
+
rel: "noopener noreferrer",
|
|
3648
|
+
style: {
|
|
3649
|
+
fontSize: 13,
|
|
3650
|
+
color: colors.textPrimary,
|
|
3651
|
+
textDecoration: "underline"
|
|
3652
|
+
},
|
|
3653
|
+
children: "View on explorer"
|
|
3654
|
+
}
|
|
3655
|
+
)
|
|
3656
|
+
] }) : /* @__PURE__ */ jsx(
|
|
3657
|
+
"div",
|
|
3658
|
+
{
|
|
3659
|
+
style: {
|
|
3660
|
+
padding: "20px",
|
|
3661
|
+
borderRadius: radii.card,
|
|
3662
|
+
border: `1px solid ${colors.border}`,
|
|
3663
|
+
color: colors.textSecondary,
|
|
3664
|
+
fontSize: 13,
|
|
3665
|
+
textAlign: "center"
|
|
3666
|
+
},
|
|
3667
|
+
children: "Select token and chain to view deposit details"
|
|
3668
|
+
}
|
|
3669
|
+
)
|
|
3670
|
+
] })
|
|
3671
|
+
] })
|
|
3672
|
+
] })
|
|
3673
|
+
] });
|
|
3674
|
+
};
|
|
3675
|
+
|
|
3676
|
+
// src/utils/explorer.ts
|
|
3677
|
+
var explorerTemplates = {
|
|
3678
|
+
"0": "",
|
|
3679
|
+
"1": "https://etherscan.io/tx/{txId}",
|
|
3680
|
+
"3": "https://dogechain.info/tx/{txId}",
|
|
3681
|
+
"10": "https://optimistic.etherscan.io/tx/{txId}",
|
|
3682
|
+
"56": "https://bscscan.com/tx/{txId}",
|
|
3683
|
+
"110": "",
|
|
3684
|
+
"126": "https://explorer.movementnetwork.xyz/txn/{txId}?network=mainnet",
|
|
3685
|
+
"137": "https://polygonscan.com/tx/{txId}",
|
|
3686
|
+
"204": "https://opbnb.bscscan.com/tx/{txId}",
|
|
3687
|
+
"223": "https://explorer.bsquared.network/tx/{txId}",
|
|
3688
|
+
"227": "https://promscan.io/tx/{txId}",
|
|
3689
|
+
"324": "https://mainnet.era.zksync.io/tx/{txId}",
|
|
3690
|
+
"400": "",
|
|
3691
|
+
"420": "https://scan.merlinchain.io/tx/{txId}",
|
|
3692
|
+
"480": "https://worldchain-mainnet.explorer.alchemy.com/tx/{txId}",
|
|
3693
|
+
"501": "https://solscan.io/tx/{txId}",
|
|
3694
|
+
"784": "",
|
|
3695
|
+
"1329": "https://seitrace.com/tx/{txId}",
|
|
3696
|
+
"1514": "https://mainnet.storyscan.xyz/tx/{txId}",
|
|
3697
|
+
"1625": "https://explorer.gravity.xyz/tx/{txId}",
|
|
3698
|
+
"2649": "https://mainnet-explorer.ailayer.xyz/tx/{txId}",
|
|
3699
|
+
"3030": "https://dashboard.tenderly.co/explorer/vnet/bd8df763-9888-4be3-9a78-26f1d5ab8d3d/tx/{txId}",
|
|
3700
|
+
"3131": "https://dashboard.tenderly.co/explorer/vnet/6593bc72-f548-497d-bff9-5be061436a48/tx/{txId}",
|
|
3701
|
+
"5545": "https://scan.duckchain.io/tx/{txId}",
|
|
3702
|
+
"8333": "https://mainnet-rpc.b3.fun/http/tx/{txId}",
|
|
3703
|
+
"8453": "https://base.blockscout.com/tx/{txId}",
|
|
3704
|
+
"19484": "https://tronscan.org/#/transaction/{txId}",
|
|
3705
|
+
"21000": "https://maizenet-explorer.usecorn.com/tx/{txId}",
|
|
3706
|
+
"42161": "https://arbiscan.io/tx/{txId}",
|
|
3707
|
+
"43114": "https://snowtrace.io/tx/{txId}",
|
|
3708
|
+
"47763": "https://neotube.io/transaction/{txId}",
|
|
3709
|
+
"59144": "https://lineascan.build/tx/{txId}",
|
|
3710
|
+
"60808": "https://rpc.gobob.xyz/tx/{txId}",
|
|
3711
|
+
"80094": "https://berascan.com/tx/{txId}",
|
|
3712
|
+
"81457": "https://blastscan.io/tx/{txId}",
|
|
3713
|
+
"200901": "https://rpc.bitlayer.org/tx/{txId}",
|
|
3714
|
+
"221122420": "https://blockscout.devnet.doge.xyz/tx/{txId}",
|
|
3715
|
+
"534352": "https://scrollscan.com/tx/{txId}"
|
|
3716
|
+
};
|
|
3717
|
+
function getExplorerUrl(chainId, data) {
|
|
3718
|
+
const template = explorerTemplates[chainId] ?? "";
|
|
3719
|
+
if (template === "") {
|
|
3720
|
+
throw new Error(`chainId ${chainId} tpl not found`);
|
|
3721
|
+
}
|
|
3722
|
+
return template.replace("{txId}", data.txId);
|
|
3723
|
+
}
|
|
3724
|
+
var SuccessIcon = () => {
|
|
3725
|
+
return /* @__PURE__ */ jsxs("svg", { width: "80", height: "81", viewBox: "0 0 80 81", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
3726
|
+
/* @__PURE__ */ jsx(
|
|
3727
|
+
"path",
|
|
3728
|
+
{
|
|
3729
|
+
d: "M40 80.5C62.0914 80.5 80 62.5914 80 40.5C80 18.4086 62.0914 0.5 40 0.5C17.9086 0.5 0 18.4086 0 40.5C0 62.5914 17.9086 80.5 40 80.5Z",
|
|
3730
|
+
fill: "#627EEA"
|
|
3731
|
+
}
|
|
3732
|
+
),
|
|
3733
|
+
/* @__PURE__ */ jsx(
|
|
3734
|
+
"path",
|
|
3735
|
+
{
|
|
3736
|
+
d: "M38.999 16.5V34.2437L53.9962 40.9451L38.999 16.5Z",
|
|
3737
|
+
fill: "white",
|
|
3738
|
+
fillOpacity: "0.602"
|
|
3739
|
+
}
|
|
3740
|
+
),
|
|
3741
|
+
/* @__PURE__ */ jsx("path", { d: "M38.9991 16.5L24 40.9451L38.9991 34.2437V16.5Z", fill: "white" }),
|
|
3742
|
+
/* @__PURE__ */ jsx(
|
|
3743
|
+
"path",
|
|
3744
|
+
{
|
|
3745
|
+
d: "M38.999 52.4434V64.4999L54.0061 43.7376L38.999 52.4434Z",
|
|
3746
|
+
fill: "white",
|
|
3747
|
+
fillOpacity: "0.602"
|
|
3748
|
+
}
|
|
3749
|
+
),
|
|
3750
|
+
/* @__PURE__ */ jsx("path", { d: "M38.9991 64.4999V52.4414L24 43.7376L38.9991 64.4999Z", fill: "white" }),
|
|
3751
|
+
/* @__PURE__ */ jsx(
|
|
3752
|
+
"path",
|
|
3753
|
+
{
|
|
3754
|
+
d: "M38.999 49.653L53.9962 40.9451L38.999 34.2477V49.653Z",
|
|
3755
|
+
fill: "white",
|
|
3756
|
+
fillOpacity: "0.2"
|
|
3757
|
+
}
|
|
3758
|
+
),
|
|
3759
|
+
/* @__PURE__ */ jsx(
|
|
3760
|
+
"path",
|
|
3761
|
+
{
|
|
3762
|
+
d: "M24 40.9451L38.9991 49.653V34.2477L24 40.9451Z",
|
|
3763
|
+
fill: "white",
|
|
3764
|
+
fillOpacity: "0.602"
|
|
3765
|
+
}
|
|
3766
|
+
),
|
|
3767
|
+
/* @__PURE__ */ jsx("g", { filter: "url(#filter0_ii_34_1690)", children: /* @__PURE__ */ jsx("circle", { cx: "40", cy: "40", r: "40", fill: "url(#paint0_linear_34_1690)" }) }),
|
|
3768
|
+
/* @__PURE__ */ jsx(
|
|
3769
|
+
"path",
|
|
3770
|
+
{
|
|
3771
|
+
d: "M25.8057 35.9858L38.7921 49.0324L56.7734 30.9678",
|
|
3772
|
+
stroke: "#58AE36",
|
|
3773
|
+
strokeWidth: "5.16129",
|
|
3774
|
+
fill: "none"
|
|
3775
|
+
}
|
|
3776
|
+
),
|
|
3777
|
+
/* @__PURE__ */ jsxs("defs", { children: [
|
|
3778
|
+
/* @__PURE__ */ jsxs(
|
|
3779
|
+
"filter",
|
|
3780
|
+
{
|
|
3781
|
+
id: "filter0_ii_34_1690",
|
|
3782
|
+
x: "0",
|
|
3783
|
+
y: "0",
|
|
3784
|
+
width: "80",
|
|
3785
|
+
height: "80",
|
|
3786
|
+
filterUnits: "userSpaceOnUse",
|
|
3787
|
+
colorInterpolationFilters: "sRGB",
|
|
3788
|
+
children: [
|
|
3789
|
+
/* @__PURE__ */ jsx("feFlood", { floodOpacity: "0", result: "BackgroundImageFix" }),
|
|
3790
|
+
/* @__PURE__ */ jsx("feBlend", { mode: "normal", in: "SourceGraphic", in2: "BackgroundImageFix", result: "shape" }),
|
|
3791
|
+
/* @__PURE__ */ jsx(
|
|
3792
|
+
"feColorMatrix",
|
|
3793
|
+
{
|
|
3794
|
+
in: "SourceAlpha",
|
|
3795
|
+
type: "matrix",
|
|
3796
|
+
values: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0",
|
|
3797
|
+
result: "hardAlpha"
|
|
3798
|
+
}
|
|
3799
|
+
),
|
|
3800
|
+
/* @__PURE__ */ jsx("feOffset", { dx: "-1.29032", dy: "-1.29032" }),
|
|
3801
|
+
/* @__PURE__ */ jsx("feComposite", { in2: "hardAlpha", operator: "arithmetic", k2: "-1", k3: "1" }),
|
|
3802
|
+
/* @__PURE__ */ jsx(
|
|
3803
|
+
"feColorMatrix",
|
|
3804
|
+
{
|
|
3805
|
+
type: "matrix",
|
|
3806
|
+
values: "0 0 0 0 0.584745 0 0 0 0 1 0 0 0 0 0.420982 0 0 0 1 0"
|
|
3807
|
+
}
|
|
3808
|
+
),
|
|
3809
|
+
/* @__PURE__ */ jsx("feBlend", { mode: "multiply", in2: "shape", result: "effect1_innerShadow_34_1690" }),
|
|
3810
|
+
/* @__PURE__ */ jsx(
|
|
3811
|
+
"feColorMatrix",
|
|
3812
|
+
{
|
|
3813
|
+
in: "SourceAlpha",
|
|
3814
|
+
type: "matrix",
|
|
3815
|
+
values: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0",
|
|
3816
|
+
result: "hardAlpha"
|
|
3817
|
+
}
|
|
3818
|
+
),
|
|
3819
|
+
/* @__PURE__ */ jsx("feOffset", { dx: "1.29032", dy: "1.29032" }),
|
|
3820
|
+
/* @__PURE__ */ jsx("feComposite", { in2: "hardAlpha", operator: "arithmetic", k2: "-1", k3: "1" }),
|
|
3821
|
+
/* @__PURE__ */ jsx("feColorMatrix", { type: "matrix", values: "0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0" }),
|
|
3822
|
+
/* @__PURE__ */ jsx("feBlend", { mode: "normal", in2: "effect1_innerShadow_34_1690", result: "effect2_innerShadow_34_1690" })
|
|
3823
|
+
]
|
|
3824
|
+
}
|
|
3825
|
+
),
|
|
3826
|
+
/* @__PURE__ */ jsxs(
|
|
3827
|
+
"linearGradient",
|
|
3828
|
+
{
|
|
3829
|
+
id: "paint0_linear_34_1690",
|
|
3830
|
+
x1: "27.4722",
|
|
3831
|
+
y1: "7.62951",
|
|
3832
|
+
x2: "70.4313",
|
|
3833
|
+
y2: "26.563",
|
|
3834
|
+
gradientUnits: "userSpaceOnUse",
|
|
3835
|
+
children: [
|
|
3836
|
+
/* @__PURE__ */ jsx("stop", { stopColor: "#BBFFA1" }),
|
|
3837
|
+
/* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#ACFE8B" })
|
|
3838
|
+
]
|
|
3839
|
+
}
|
|
3840
|
+
)
|
|
3841
|
+
] })
|
|
3842
|
+
] });
|
|
3843
|
+
};
|
|
3844
|
+
function CopyIcon2() {
|
|
3845
|
+
return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": true, children: [
|
|
3846
|
+
/* @__PURE__ */ jsx("rect", { x: "5", y: "5", width: "9", height: "9", rx: "1", stroke: "currentColor", strokeWidth: "1.2", fill: "none" }),
|
|
3847
|
+
/* @__PURE__ */ jsx("path", { d: "M3 11V3a1 1 0 0 1 1-1h8", stroke: "currentColor", strokeWidth: "1.2", fill: "none" })
|
|
3848
|
+
] });
|
|
3849
|
+
}
|
|
3850
|
+
var FUNDING_TOKEN_SYMBOL2 = getEnv("FUNDING_TOKEN_SYMBOL");
|
|
3851
|
+
function chainsToTokenOptions2(chains) {
|
|
3852
|
+
const bySymbol = /* @__PURE__ */ new Map();
|
|
3853
|
+
for (const c of chains) {
|
|
3854
|
+
for (const t of c.tokens) {
|
|
3855
|
+
if (!bySymbol.has(t.symbol)) bySymbol.set(t.symbol, t.symbol);
|
|
3856
|
+
}
|
|
3857
|
+
}
|
|
3858
|
+
return Array.from(bySymbol.entries()).map(([id, symbol]) => ({
|
|
3859
|
+
id,
|
|
3860
|
+
label: symbol,
|
|
3861
|
+
subtitle: symbol
|
|
3862
|
+
}));
|
|
3863
|
+
}
|
|
3864
|
+
function chainsToChainOptionsForToken2(chains, tokenSymbol) {
|
|
3865
|
+
return chains.filter((c) => c.tokens.some((t) => t.symbol === tokenSymbol)).map((c) => ({ id: c.chain_id, label: c.network, subtitle: c.chain_id }));
|
|
3866
|
+
}
|
|
3867
|
+
function getTokenAddressForChain2(chains, chainId, tokenSymbol) {
|
|
3868
|
+
const chain = chains.find((c) => c.chain_id === chainId);
|
|
3869
|
+
return chain?.tokens.find((t) => t.symbol === tokenSymbol)?.address;
|
|
3870
|
+
}
|
|
3871
|
+
function parseBalanceNumber(balance) {
|
|
3872
|
+
const match = balance.trim().match(/^(\d*\.?\d*)/);
|
|
3873
|
+
if (!match) return null;
|
|
3874
|
+
const n = Number(match[1]);
|
|
3875
|
+
return Number.isNaN(n) ? null : n;
|
|
3876
|
+
}
|
|
3877
|
+
function formatBalanceTo2Decimals(balance) {
|
|
3878
|
+
const match = balance.trim().match(/^(\d*\.?\d*)(.*)$/);
|
|
3879
|
+
if (!match) return balance;
|
|
3880
|
+
const numPart = match[1];
|
|
3881
|
+
const suffix = match[2].trim() ? " " + match[2].trim() : "";
|
|
3882
|
+
const n = Number(numPart);
|
|
3883
|
+
if (Number.isNaN(n)) return balance;
|
|
3884
|
+
const formatted = n.toFixed(2);
|
|
3885
|
+
return formatted + suffix;
|
|
3886
|
+
}
|
|
3887
|
+
function weiToEtherDisplay(wei) {
|
|
3888
|
+
const s = (wei || "0").trim().replace(/^0+/, "") || "0";
|
|
3889
|
+
if (s === "0") return "0";
|
|
3890
|
+
const padded = s.padStart(19, "0");
|
|
3891
|
+
const intPart = padded.slice(0, Math.max(0, padded.length - 18));
|
|
3892
|
+
const decPart = padded.slice(-18).replace(/0+$/, "");
|
|
3893
|
+
const combined = decPart ? `${intPart}.${decPart}` : intPart;
|
|
3894
|
+
const num = Number(combined);
|
|
3895
|
+
if (Number.isNaN(num)) return wei;
|
|
3896
|
+
const fixed = num.toFixed(6).replace(/\.?0+$/, "");
|
|
3897
|
+
return fixed;
|
|
3898
|
+
}
|
|
3899
|
+
var POLL_INTERVAL_MS = 4e3;
|
|
3900
|
+
var WithdrawModal = ({
|
|
3901
|
+
address = "",
|
|
3902
|
+
token,
|
|
3903
|
+
tokenSymbol,
|
|
3904
|
+
chain,
|
|
3905
|
+
amount = "",
|
|
3906
|
+
balance,
|
|
3907
|
+
status = "idle",
|
|
3908
|
+
receiveAmount: receiveAmountProp,
|
|
3909
|
+
txHash,
|
|
3910
|
+
tokenOptions: tokenOptionsProp,
|
|
3911
|
+
chainOptions: chainOptionsProp,
|
|
3912
|
+
useMerchantApi = false,
|
|
3913
|
+
orderId,
|
|
3914
|
+
withdrawMode,
|
|
3915
|
+
withdrawDirectResult,
|
|
3916
|
+
feeDisplay,
|
|
3917
|
+
fundingChainId,
|
|
3918
|
+
onShowToast,
|
|
3919
|
+
onAddressChange,
|
|
3920
|
+
onTokenSelect,
|
|
3921
|
+
onChainSelect,
|
|
3922
|
+
onAmountChange,
|
|
3923
|
+
onMaxClick,
|
|
3924
|
+
onSubmit,
|
|
3925
|
+
onWithdrawCompleted,
|
|
3926
|
+
onStartAnotherWithdrawal,
|
|
3927
|
+
onSignIn,
|
|
3928
|
+
onClose
|
|
3929
|
+
}) => {
|
|
3930
|
+
const session = useSession();
|
|
3931
|
+
const addressInputRef = useRef(null);
|
|
3932
|
+
const [addressInputFocused, setAddressInputFocused] = useState(false);
|
|
3933
|
+
const [amountInputFocused, setAmountInputFocused] = useState(false);
|
|
3934
|
+
const [apiChains, setApiChains] = useState(null);
|
|
3935
|
+
const [apiQuote, setApiQuote] = useState(null);
|
|
3936
|
+
const [withdrawOrder, setWithdrawOrder] = useState(null);
|
|
3937
|
+
const [loadingChains, setLoadingChains] = useState(false);
|
|
3938
|
+
const [loadingQuote, setLoadingQuote] = useState(false);
|
|
3939
|
+
const tokenOptions = useMemo(() => {
|
|
3940
|
+
const raw = tokenOptionsProp?.length ? tokenOptionsProp : apiChains?.length ? chainsToTokenOptions2(apiChains) : void 0;
|
|
3941
|
+
if (!raw?.length) return void 0;
|
|
3942
|
+
return raw;
|
|
3943
|
+
}, [tokenOptionsProp, apiChains]);
|
|
3944
|
+
const chainOptions = useMemo(() => {
|
|
3945
|
+
if (chainOptionsProp?.length) return chainOptionsProp;
|
|
3946
|
+
if (!apiChains?.length || !token) return void 0;
|
|
3947
|
+
return chainsToChainOptionsForToken2(apiChains, token);
|
|
3948
|
+
}, [chainOptionsProp, apiChains, token]);
|
|
3949
|
+
const resolvedTokenAddress = useMemo(() => {
|
|
3950
|
+
if (!apiChains?.length || !token || !chain) return void 0;
|
|
3951
|
+
return getTokenAddressForChain2(apiChains, chain, token);
|
|
3952
|
+
}, [apiChains, token, chain]);
|
|
3953
|
+
const [directActive, setDirectActive] = useState(false);
|
|
3954
|
+
useEffect(() => {
|
|
3955
|
+
setDirectActive(withdrawMode === "direct" && Boolean(withdrawDirectResult));
|
|
3956
|
+
}, [withdrawMode, withdrawDirectResult]);
|
|
3957
|
+
const trackingWithdraw = useMemo(
|
|
3958
|
+
() => Boolean(orderId) || directActive,
|
|
3959
|
+
[orderId, directActive]
|
|
3960
|
+
);
|
|
3961
|
+
useEffect(() => {
|
|
3962
|
+
if (trackingWithdraw) return;
|
|
3963
|
+
const t = requestAnimationFrame(() => {
|
|
3964
|
+
addressInputRef.current?.focus();
|
|
3965
|
+
});
|
|
3966
|
+
return () => cancelAnimationFrame(t);
|
|
3967
|
+
}, [trackingWithdraw]);
|
|
3968
|
+
const shouldLoadChains = useMerchantApi || Boolean(token && chain);
|
|
3969
|
+
useEffect(() => {
|
|
3970
|
+
if (!shouldLoadChains) return;
|
|
3971
|
+
setLoadingChains(true);
|
|
3972
|
+
getChains().then((res) => setApiChains(res?.chains ?? [])).finally(() => setLoadingChains(false));
|
|
3973
|
+
}, [shouldLoadChains]);
|
|
3974
|
+
useEffect(() => {
|
|
3975
|
+
if (!apiChains?.length || !token || !chain) {
|
|
3976
|
+
setApiQuote(null);
|
|
3977
|
+
return;
|
|
3978
|
+
}
|
|
3979
|
+
const tokenAddress = getTokenAddressForChain2(apiChains, chain, token);
|
|
3980
|
+
if (!tokenAddress) {
|
|
3981
|
+
setApiQuote(null);
|
|
3982
|
+
return;
|
|
3983
|
+
}
|
|
3984
|
+
const amountNum = amount && Number(amount) > 0 ? Number(amount) : 1;
|
|
3985
|
+
const amountWei = String(BigInt(Math.floor(amountNum * 1e18)));
|
|
3986
|
+
setLoadingQuote(true);
|
|
3987
|
+
quote({
|
|
3988
|
+
direction: "withdraw",
|
|
3989
|
+
chain_id: chain,
|
|
3990
|
+
token_address: tokenAddress,
|
|
3991
|
+
dst_token_amount: amountWei
|
|
3992
|
+
}).then((q) => setApiQuote(q ?? null)).catch(() => {
|
|
3993
|
+
setApiQuote({
|
|
3994
|
+
token_address: tokenAddress,
|
|
3995
|
+
token_symbol: token,
|
|
3996
|
+
token_decimals: 18,
|
|
3997
|
+
rate: "1",
|
|
3998
|
+
chain_id: Number(chain) || 56,
|
|
3999
|
+
token_amount: amountWei,
|
|
4000
|
+
expires_at: new Date(Date.now() + 6e4).toISOString()
|
|
4001
|
+
});
|
|
4002
|
+
}).finally(() => setLoadingQuote(false));
|
|
4003
|
+
}, [apiChains, token, chain, amount]);
|
|
4004
|
+
useEffect(() => {
|
|
4005
|
+
if (tokenOptions?.length !== 1 || !onTokenSelect) return;
|
|
4006
|
+
const onlyId = tokenOptions[0].id;
|
|
4007
|
+
if (token === onlyId) return;
|
|
4008
|
+
onTokenSelect(onlyId);
|
|
4009
|
+
}, [tokenOptions, token, onTokenSelect]);
|
|
4010
|
+
useEffect(() => {
|
|
4011
|
+
if (chainOptions?.length !== 1 || !onChainSelect) return;
|
|
4012
|
+
const onlyId = chainOptions[0].id;
|
|
4013
|
+
if (chain === onlyId) return;
|
|
4014
|
+
onChainSelect(onlyId);
|
|
4015
|
+
}, [chainOptions, chain, onChainSelect]);
|
|
4016
|
+
const mockWithdrawOrderState = useMemo(
|
|
4017
|
+
() => ({
|
|
4018
|
+
order_id: orderId ?? "",
|
|
4019
|
+
status: "pending",
|
|
4020
|
+
chain_id: "56",
|
|
4021
|
+
dst_token_amount: "0",
|
|
4022
|
+
target_chain_id: chain ?? "1",
|
|
4023
|
+
target_address: address ?? "0x",
|
|
4024
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4025
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4026
|
+
}),
|
|
4027
|
+
[orderId, chain, address]
|
|
4028
|
+
);
|
|
4029
|
+
useEffect(() => {
|
|
4030
|
+
if (orderId) {
|
|
4031
|
+
const t = setInterval(() => {
|
|
4032
|
+
getWithdrawOrder(orderId).then((order) => {
|
|
4033
|
+
setWithdrawOrder(order);
|
|
4034
|
+
if (order.status === "completed" && onShowToast) {
|
|
4035
|
+
onShowToast("Withdrawal completed");
|
|
4036
|
+
}
|
|
4037
|
+
}).catch(() => setWithdrawOrder(mockWithdrawOrderState));
|
|
4038
|
+
}, POLL_INTERVAL_MS);
|
|
4039
|
+
getWithdrawOrder(orderId).then(setWithdrawOrder).catch(() => setWithdrawOrder(mockWithdrawOrderState));
|
|
4040
|
+
return () => clearInterval(t);
|
|
4041
|
+
}
|
|
4042
|
+
if (!orderId && directActive) {
|
|
4043
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4044
|
+
const inferredAmountWei = (() => {
|
|
4045
|
+
if (withdrawDirectResult?.dst_token_amount) return withdrawDirectResult.dst_token_amount;
|
|
4046
|
+
const n = Number(amount || "0");
|
|
4047
|
+
return String(n > 0 ? BigInt(Math.floor(n * 1e18)) : 0n);
|
|
4048
|
+
})();
|
|
4049
|
+
const synthetic = {
|
|
4050
|
+
order_id: withdrawDirectResult?.order_id ?? `direct-${Date.now()}`,
|
|
4051
|
+
status: withdrawDirectResult?.status ?? "pending",
|
|
4052
|
+
chain_id: withdrawDirectResult?.chain_id ?? String(fundingChainId ?? "3131"),
|
|
4053
|
+
dst_token_amount: inferredAmountWei,
|
|
4054
|
+
fee: withdrawDirectResult?.fee ?? feeDisplay,
|
|
4055
|
+
target_chain_id: withdrawDirectResult?.target_chain_id ?? (chain ?? ""),
|
|
4056
|
+
target_address: withdrawDirectResult?.target_address ?? (address ?? ""),
|
|
4057
|
+
funding_tx_hash: withdrawDirectResult?.funding_tx_hash ?? txHash,
|
|
4058
|
+
dst_tx_hash: withdrawDirectResult?.dst_tx_hash,
|
|
4059
|
+
out_tx_hash: withdrawDirectResult?.out_tx_hash,
|
|
4060
|
+
created_at: withdrawDirectResult?.created_at ?? now,
|
|
4061
|
+
updated_at: withdrawDirectResult?.updated_at ?? now,
|
|
4062
|
+
one_time_address: withdrawDirectResult?.one_time_address
|
|
4063
|
+
};
|
|
4064
|
+
setWithdrawOrder(synthetic);
|
|
4065
|
+
return;
|
|
4066
|
+
}
|
|
4067
|
+
setWithdrawOrder(null);
|
|
4068
|
+
}, [orderId, directActive, withdrawDirectResult, amount, feeDisplay, chain, address, txHash, fundingChainId, onShowToast, mockWithdrawOrderState]);
|
|
4069
|
+
const completedKeyRef = useRef(null);
|
|
4070
|
+
useEffect(() => {
|
|
4071
|
+
if (withdrawOrder?.status !== "completed") return;
|
|
4072
|
+
const key = orderId ?? withdrawOrder.order_id;
|
|
4073
|
+
if (key && completedKeyRef.current !== key) {
|
|
4074
|
+
completedKeyRef.current = key;
|
|
4075
|
+
onWithdrawCompleted?.();
|
|
4076
|
+
}
|
|
4077
|
+
if (!trackingWithdraw) completedKeyRef.current = null;
|
|
4078
|
+
}, [withdrawOrder?.status, orderId, trackingWithdraw, onWithdrawCompleted]);
|
|
4079
|
+
const receiveAmount = useMemo(() => {
|
|
4080
|
+
if (receiveAmountProp) {
|
|
4081
|
+
const n = Number(receiveAmountProp);
|
|
4082
|
+
if (!Number.isNaN(n)) return n.toFixed(2);
|
|
4083
|
+
return receiveAmountProp;
|
|
4084
|
+
}
|
|
4085
|
+
if (!apiQuote?.token_amount || !apiQuote?.token_symbol) return void 0;
|
|
4086
|
+
const amount2 = Number(apiQuote.token_amount);
|
|
4087
|
+
const formatted = Number.isNaN(amount2) ? apiQuote.token_amount : amount2.toFixed(2);
|
|
4088
|
+
return `\u2248 ${formatted} (wei) ${apiQuote.token_symbol}`;
|
|
4089
|
+
}, [receiveAmountProp, apiQuote]);
|
|
4090
|
+
const quoteExpired = useMemo(() => {
|
|
4091
|
+
if (!apiQuote?.expires_at) return false;
|
|
4092
|
+
try {
|
|
4093
|
+
return new Date(apiQuote.expires_at).getTime() < Date.now();
|
|
4094
|
+
} catch {
|
|
4095
|
+
return false;
|
|
4096
|
+
}
|
|
4097
|
+
}, [apiQuote?.expires_at]);
|
|
4098
|
+
const handleRefreshQuote = useCallback(() => {
|
|
4099
|
+
if (!apiChains?.length || !token || !chain) return;
|
|
4100
|
+
const tokenAddress = getTokenAddressForChain2(apiChains, chain, token);
|
|
4101
|
+
if (!tokenAddress) return;
|
|
4102
|
+
const amountNum = amount && Number(amount) > 0 ? Number(amount) : 1;
|
|
4103
|
+
const amountWei = String(BigInt(Math.floor(amountNum * 1e18)));
|
|
4104
|
+
setLoadingQuote(true);
|
|
4105
|
+
quote({
|
|
4106
|
+
direction: "withdraw",
|
|
4107
|
+
chain_id: chain,
|
|
4108
|
+
token_address: tokenAddress,
|
|
4109
|
+
dst_token_amount: amountWei
|
|
4110
|
+
}).then((q) => setApiQuote(q ?? null)).catch(() => {
|
|
4111
|
+
setApiQuote({
|
|
4112
|
+
token_address: tokenAddress,
|
|
4113
|
+
token_symbol: token,
|
|
4114
|
+
token_decimals: 18,
|
|
4115
|
+
rate: "1",
|
|
4116
|
+
chain_id: Number(chain) || 56,
|
|
4117
|
+
token_amount: amountWei,
|
|
4118
|
+
expires_at: new Date(Date.now() + 6e4).toISOString()
|
|
4119
|
+
});
|
|
4120
|
+
}).finally(() => setLoadingQuote(false));
|
|
4121
|
+
}, [apiChains, token, chain, amount]);
|
|
4122
|
+
const handleAmountChange = useCallback(
|
|
4123
|
+
(e) => {
|
|
4124
|
+
const raw = e.target.value;
|
|
4125
|
+
const maxNum = balance ? parseBalanceNumber(balance) : null;
|
|
4126
|
+
if (maxNum != null && raw !== "" && raw !== ".") {
|
|
4127
|
+
const num = Number(raw);
|
|
4128
|
+
if (!Number.isNaN(num) && num > maxNum) {
|
|
4129
|
+
onAmountChange?.({
|
|
4130
|
+
...e,
|
|
4131
|
+
target: { ...e.target, value: String(maxNum) }
|
|
4132
|
+
});
|
|
4133
|
+
return;
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
4136
|
+
onAmountChange?.(e);
|
|
4137
|
+
},
|
|
4138
|
+
[balance, onAmountChange]
|
|
4139
|
+
);
|
|
4140
|
+
if (!session) {
|
|
4141
|
+
return /* @__PURE__ */ jsx(LoginRequiredOverlay, { title: "Withdraw", onSignIn, onClose });
|
|
4142
|
+
}
|
|
4143
|
+
const activeStep = amount ? 3 : chain ? 2 : token ? 1 : address ? 0 : 0;
|
|
4144
|
+
const canSubmit = address && token && chain && amount;
|
|
4145
|
+
const isSubmitting = status !== "idle";
|
|
4146
|
+
const orderInProgress = trackingWithdraw && (!withdrawOrder || withdrawOrder.status !== "completed");
|
|
4147
|
+
const orderSucceeded = trackingWithdraw && withdrawOrder?.status === "completed";
|
|
4148
|
+
return /* @__PURE__ */ jsxs(
|
|
4149
|
+
ModalFrame,
|
|
4150
|
+
{
|
|
4151
|
+
onClose,
|
|
4152
|
+
contentStyle: {
|
|
4153
|
+
justifyContent: "space-between",
|
|
4154
|
+
padding: "24px"
|
|
4155
|
+
},
|
|
4156
|
+
children: [
|
|
4157
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 32 }, children: [
|
|
4158
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: /* @__PURE__ */ jsx("h2", { style: { margin: 0, fontSize: 24, fontWeight: 600, lineHeight: 1.4 }, children: "Withdraw" }) }),
|
|
4159
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 16 }, children: [
|
|
4160
|
+
/* @__PURE__ */ jsx(
|
|
4161
|
+
"div",
|
|
4162
|
+
{
|
|
4163
|
+
style: {
|
|
4164
|
+
opacity: trackingWithdraw ? 0 : 1,
|
|
4165
|
+
maxWidth: trackingWithdraw ? 0 : 48,
|
|
4166
|
+
overflow: "hidden",
|
|
4167
|
+
transition: "opacity 0.3s ease, max-width 0.35s ease"
|
|
4168
|
+
},
|
|
4169
|
+
children: /* @__PURE__ */ jsx(
|
|
4170
|
+
StepIndicator,
|
|
4171
|
+
{
|
|
4172
|
+
steps: 4,
|
|
4173
|
+
stepActive: [!!address, !!token, !!chain, !!apiQuote],
|
|
4174
|
+
activeStep
|
|
4175
|
+
}
|
|
4176
|
+
)
|
|
4177
|
+
}
|
|
4178
|
+
),
|
|
4179
|
+
/* @__PURE__ */ jsxs("div", { style: { flex: 1, position: "relative", minHeight: 400 }, children: [
|
|
4180
|
+
/* @__PURE__ */ jsxs(
|
|
4181
|
+
"div",
|
|
4182
|
+
{
|
|
4183
|
+
style: {
|
|
4184
|
+
position: "absolute",
|
|
4185
|
+
inset: 0,
|
|
4186
|
+
display: "flex",
|
|
4187
|
+
flexDirection: "column",
|
|
4188
|
+
alignItems: "center",
|
|
4189
|
+
justifyContent: "center",
|
|
4190
|
+
gap: 12,
|
|
4191
|
+
padding: "0 16px",
|
|
4192
|
+
opacity: trackingWithdraw ? 1 : 0,
|
|
4193
|
+
maxHeight: trackingWithdraw ? 400 : 0,
|
|
4194
|
+
overflow: "hidden",
|
|
4195
|
+
pointerEvents: trackingWithdraw ? "auto" : "none",
|
|
4196
|
+
transition: "opacity 0.3s ease, max-height 0.35s ease"
|
|
4197
|
+
},
|
|
4198
|
+
children: [
|
|
4199
|
+
orderInProgress && /* @__PURE__ */ jsxs(
|
|
4200
|
+
"div",
|
|
4201
|
+
{
|
|
4202
|
+
style: {
|
|
4203
|
+
display: "flex",
|
|
4204
|
+
flexDirection: "column",
|
|
4205
|
+
alignItems: "center",
|
|
4206
|
+
justifyContent: "center",
|
|
4207
|
+
gap: 32
|
|
4208
|
+
},
|
|
4209
|
+
children: [
|
|
4210
|
+
/* @__PURE__ */ jsx(
|
|
4211
|
+
"span",
|
|
4212
|
+
{
|
|
4213
|
+
style: {
|
|
4214
|
+
display: "inline-block",
|
|
4215
|
+
width: 60,
|
|
4216
|
+
height: 60,
|
|
4217
|
+
border: `3px solid ${colors.border}`,
|
|
4218
|
+
borderTopColor: colors.textPrimary,
|
|
4219
|
+
borderRadius: "50%",
|
|
4220
|
+
animation: "withdraw-modal-spin 0.8s linear infinite"
|
|
4221
|
+
},
|
|
4222
|
+
"aria-hidden": true
|
|
4223
|
+
}
|
|
4224
|
+
),
|
|
4225
|
+
/* @__PURE__ */ jsx(
|
|
4226
|
+
"span",
|
|
4227
|
+
{
|
|
4228
|
+
style: {
|
|
4229
|
+
fontSize: 20,
|
|
4230
|
+
fontWeight: 600,
|
|
4231
|
+
color: colors.textPrimary,
|
|
4232
|
+
textAlign: "center",
|
|
4233
|
+
fontFamily: fonts.family,
|
|
4234
|
+
lineHeight: 1.4
|
|
4235
|
+
},
|
|
4236
|
+
children: "Processing withdrawal..."
|
|
4237
|
+
}
|
|
4238
|
+
)
|
|
4239
|
+
]
|
|
4240
|
+
}
|
|
4241
|
+
),
|
|
4242
|
+
orderSucceeded && (() => {
|
|
4243
|
+
const destTxHash = withdrawOrder.dst_tx_hash ?? withdrawOrder.out_tx_hash;
|
|
4244
|
+
const targetChainName = apiChains?.find((c) => c.chain_id === withdrawOrder.target_chain_id)?.network ?? withdrawOrder.target_chain_id ?? "\u2014";
|
|
4245
|
+
const explorerUrl = destTxHash && withdrawOrder.target_chain_id ? getExplorerUrl(withdrawOrder.target_chain_id, { txId: destTxHash }) : null;
|
|
4246
|
+
const copyHash = () => {
|
|
4247
|
+
if (destTxHash && typeof navigator?.clipboard?.writeText === "function") {
|
|
4248
|
+
navigator.clipboard.writeText(destTxHash);
|
|
4249
|
+
onShowToast?.("Copied");
|
|
4250
|
+
}
|
|
4251
|
+
};
|
|
4252
|
+
return /* @__PURE__ */ jsxs(
|
|
4253
|
+
"div",
|
|
4254
|
+
{
|
|
4255
|
+
style: {
|
|
4256
|
+
display: "flex",
|
|
4257
|
+
flexDirection: "column",
|
|
4258
|
+
alignItems: "center",
|
|
4259
|
+
gap: 20,
|
|
4260
|
+
width: "100%",
|
|
4261
|
+
maxWidth: 412
|
|
4262
|
+
},
|
|
4263
|
+
children: [
|
|
4264
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 24 }, children: [
|
|
4265
|
+
/* @__PURE__ */ jsx(
|
|
4266
|
+
"span",
|
|
4267
|
+
{
|
|
4268
|
+
style: {
|
|
4269
|
+
display: "flex",
|
|
4270
|
+
alignItems: "center",
|
|
4271
|
+
justifyContent: "center",
|
|
4272
|
+
width: 60,
|
|
4273
|
+
height: 60,
|
|
4274
|
+
borderRadius: "50%",
|
|
4275
|
+
color: "#22c55e",
|
|
4276
|
+
fontSize: 40,
|
|
4277
|
+
lineHeight: 1,
|
|
4278
|
+
fontWeight: 700
|
|
4279
|
+
},
|
|
4280
|
+
"aria-hidden": true,
|
|
4281
|
+
children: /* @__PURE__ */ jsx(SuccessIcon, {})
|
|
4282
|
+
}
|
|
4283
|
+
),
|
|
4284
|
+
/* @__PURE__ */ jsx(
|
|
4285
|
+
"span",
|
|
4286
|
+
{
|
|
4287
|
+
style: {
|
|
4288
|
+
fontSize: 20,
|
|
4289
|
+
fontWeight: 600,
|
|
4290
|
+
color: colors.textPrimary,
|
|
4291
|
+
textAlign: "center",
|
|
4292
|
+
fontFamily: fonts.family,
|
|
4293
|
+
lineHeight: 1.4
|
|
4294
|
+
},
|
|
4295
|
+
children: "Withdrawal successful"
|
|
4296
|
+
}
|
|
4297
|
+
)
|
|
4298
|
+
] }),
|
|
4299
|
+
/* @__PURE__ */ jsxs(
|
|
4300
|
+
"div",
|
|
4301
|
+
{
|
|
4302
|
+
style: {
|
|
4303
|
+
display: "flex",
|
|
4304
|
+
flexDirection: "column",
|
|
4305
|
+
gap: 4,
|
|
4306
|
+
width: "100%"
|
|
4307
|
+
},
|
|
4308
|
+
children: [
|
|
4309
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "8px 0", height: 36 }, children: [
|
|
4310
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textSecondary }, children: "Amount" }),
|
|
4311
|
+
/* @__PURE__ */ jsxs("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: [
|
|
4312
|
+
weiToEtherDisplay(withdrawOrder.dst_token_amount),
|
|
4313
|
+
" ",
|
|
4314
|
+
tokenSymbol
|
|
4315
|
+
] })
|
|
4316
|
+
] }),
|
|
4317
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "8px 0", height: 36 }, children: [
|
|
4318
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textSecondary }, children: "Fee" }),
|
|
4319
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: withdrawOrder.fee ?? feeDisplay ?? "\u2014" })
|
|
4320
|
+
] }),
|
|
4321
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "8px 0", height: 36 }, children: [
|
|
4322
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textSecondary }, children: "Network" }),
|
|
4323
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: targetChainName })
|
|
4324
|
+
] }),
|
|
4325
|
+
destTxHash && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "8px 0", minHeight: 38 }, children: [
|
|
4326
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textSecondary }, children: "Transaction Hash" }),
|
|
4327
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
4328
|
+
explorerUrl ? /* @__PURE__ */ jsxs(
|
|
4329
|
+
"a",
|
|
4330
|
+
{
|
|
4331
|
+
href: explorerUrl,
|
|
4332
|
+
target: "_blank",
|
|
4333
|
+
rel: "noopener noreferrer",
|
|
4334
|
+
style: { fontSize: 14, color: colors.textPrimary, textDecoration: "underline" },
|
|
4335
|
+
children: [
|
|
4336
|
+
destTxHash.slice(0, 10),
|
|
4337
|
+
"...",
|
|
4338
|
+
destTxHash.slice(-8)
|
|
4339
|
+
]
|
|
4340
|
+
}
|
|
4341
|
+
) : /* @__PURE__ */ jsxs("span", { style: { fontSize: 14, color: colors.textPrimary }, children: [
|
|
4342
|
+
destTxHash.slice(0, 10),
|
|
4343
|
+
"...",
|
|
4344
|
+
destTxHash.slice(-8)
|
|
4345
|
+
] }),
|
|
4346
|
+
/* @__PURE__ */ jsx(
|
|
4347
|
+
"button",
|
|
4348
|
+
{
|
|
4349
|
+
type: "button",
|
|
4350
|
+
onClick: copyHash,
|
|
4351
|
+
"aria-label": "Copy hash",
|
|
4352
|
+
style: {
|
|
4353
|
+
padding: 0,
|
|
4354
|
+
border: "none",
|
|
4355
|
+
background: "transparent",
|
|
4356
|
+
color: colors.textPrimary,
|
|
4357
|
+
cursor: "pointer",
|
|
4358
|
+
display: "flex",
|
|
4359
|
+
alignItems: "center",
|
|
4360
|
+
justifyContent: "center",
|
|
4361
|
+
width: 16,
|
|
4362
|
+
height: 16
|
|
4363
|
+
},
|
|
4364
|
+
children: /* @__PURE__ */ jsx(CopyIcon2, {})
|
|
4365
|
+
}
|
|
4366
|
+
)
|
|
4367
|
+
] })
|
|
4368
|
+
] })
|
|
4369
|
+
]
|
|
4370
|
+
}
|
|
4371
|
+
),
|
|
4372
|
+
/* @__PURE__ */ jsx("div", { style: { paddingTop: 24, width: "100%", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsx(
|
|
4373
|
+
"button",
|
|
4374
|
+
{
|
|
4375
|
+
type: "button",
|
|
4376
|
+
onClick: () => {
|
|
4377
|
+
setDirectActive(false);
|
|
4378
|
+
setWithdrawOrder(null);
|
|
4379
|
+
(onStartAnotherWithdrawal ?? onClose)?.();
|
|
4380
|
+
},
|
|
4381
|
+
style: {
|
|
4382
|
+
width: 274,
|
|
4383
|
+
padding: "12px 0",
|
|
4384
|
+
borderRadius: radii.full,
|
|
4385
|
+
border: `1px solid ${colors.buttonDisabledBorder}`,
|
|
4386
|
+
background: colors.textPrimary,
|
|
4387
|
+
color: "#121214",
|
|
4388
|
+
fontSize: 16,
|
|
4389
|
+
fontWeight: 500,
|
|
4390
|
+
lineHeight: 1.4,
|
|
4391
|
+
fontFamily: fonts.family,
|
|
4392
|
+
cursor: "pointer",
|
|
4393
|
+
textAlign: "center"
|
|
4394
|
+
},
|
|
4395
|
+
children: "Start another withdrawal"
|
|
4396
|
+
}
|
|
4397
|
+
) })
|
|
4398
|
+
]
|
|
4399
|
+
}
|
|
4400
|
+
);
|
|
4401
|
+
})()
|
|
4402
|
+
]
|
|
4403
|
+
}
|
|
4404
|
+
),
|
|
4405
|
+
/* @__PURE__ */ jsx(
|
|
4406
|
+
"div",
|
|
4407
|
+
{
|
|
4408
|
+
style: {
|
|
4409
|
+
opacity: trackingWithdraw ? 0 : 1,
|
|
4410
|
+
maxHeight: trackingWithdraw ? 0 : 1200,
|
|
4411
|
+
overflow: "hidden",
|
|
4412
|
+
pointerEvents: trackingWithdraw ? "none" : "auto",
|
|
4413
|
+
transition: "opacity 0.3s ease, max-height 0.35s ease"
|
|
4414
|
+
},
|
|
4415
|
+
children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 40 }, children: [
|
|
4416
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8, width: "100%" }, children: [
|
|
4417
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: "Recipient address" }),
|
|
4418
|
+
/* @__PURE__ */ jsx(
|
|
4419
|
+
"div",
|
|
4420
|
+
{
|
|
4421
|
+
style: {
|
|
4422
|
+
display: "flex",
|
|
4423
|
+
alignItems: "center",
|
|
4424
|
+
height: 44,
|
|
4425
|
+
padding: "0 16px",
|
|
4426
|
+
borderRadius: radii.input,
|
|
4427
|
+
border: `1px solid ${addressInputFocused ? colors.borderFocused : colors.border}`,
|
|
4428
|
+
boxSizing: "border-box"
|
|
4429
|
+
},
|
|
4430
|
+
children: /* @__PURE__ */ jsx(
|
|
4431
|
+
"input",
|
|
4432
|
+
{
|
|
4433
|
+
ref: addressInputRef,
|
|
4434
|
+
value: address,
|
|
4435
|
+
onChange: onAddressChange,
|
|
4436
|
+
onFocus: () => setAddressInputFocused(true),
|
|
4437
|
+
onBlur: () => setAddressInputFocused(false),
|
|
4438
|
+
spellCheck: false,
|
|
4439
|
+
placeholder: "0x",
|
|
4440
|
+
style: {
|
|
4441
|
+
flex: 1,
|
|
4442
|
+
border: "none",
|
|
4443
|
+
outline: "none",
|
|
4444
|
+
background: "transparent",
|
|
4445
|
+
color: colors.textPrimary,
|
|
4446
|
+
fontSize: 14,
|
|
4447
|
+
fontFamily: fonts.family,
|
|
4448
|
+
lineHeight: 1.4,
|
|
4449
|
+
padding: 0
|
|
4450
|
+
}
|
|
4451
|
+
}
|
|
4452
|
+
)
|
|
4453
|
+
}
|
|
4454
|
+
)
|
|
4455
|
+
] }),
|
|
4456
|
+
/* @__PURE__ */ jsx(
|
|
4457
|
+
DropdownField,
|
|
4458
|
+
{
|
|
4459
|
+
label: "Select token",
|
|
4460
|
+
placeholder: loadingChains ? "Loading\u2026" : "Token",
|
|
4461
|
+
value: token,
|
|
4462
|
+
options: tokenOptions,
|
|
4463
|
+
onSelect: onTokenSelect
|
|
4464
|
+
}
|
|
4465
|
+
),
|
|
4466
|
+
/* @__PURE__ */ jsx(
|
|
4467
|
+
DropdownField,
|
|
4468
|
+
{
|
|
4469
|
+
label: "Select chain",
|
|
4470
|
+
placeholder: loadingChains ? "Loading\u2026" : "Chain",
|
|
4471
|
+
value: chain,
|
|
4472
|
+
options: chainOptions,
|
|
4473
|
+
onSelect: onChainSelect
|
|
4474
|
+
}
|
|
4475
|
+
),
|
|
4476
|
+
apiQuote && token && chain && /* @__PURE__ */ jsx(
|
|
4477
|
+
"div",
|
|
4478
|
+
{
|
|
4479
|
+
style: {
|
|
4480
|
+
padding: "12px 16px",
|
|
4481
|
+
borderRadius: radii.card,
|
|
4482
|
+
border: `1px solid ${colors.border}`,
|
|
4483
|
+
display: "flex",
|
|
4484
|
+
flexDirection: "column",
|
|
4485
|
+
gap: 8
|
|
4486
|
+
},
|
|
4487
|
+
children: loadingQuote ? /* @__PURE__ */ jsx("span", { style: { fontSize: 13, color: colors.textSecondary }, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4488
|
+
/* @__PURE__ */ jsxs("span", { style: { fontSize: 13, color: colors.textSecondary }, children: [
|
|
4489
|
+
"Rate: 1 ",
|
|
4490
|
+
FUNDING_TOKEN_SYMBOL2,
|
|
4491
|
+
" = ",
|
|
4492
|
+
apiQuote.rate,
|
|
4493
|
+
" ",
|
|
4494
|
+
apiQuote.token_symbol
|
|
4495
|
+
] }),
|
|
4496
|
+
apiQuote.expires_at && /* @__PURE__ */ jsx(
|
|
4497
|
+
Countdown,
|
|
4498
|
+
{
|
|
4499
|
+
expiresAt: apiQuote.expires_at,
|
|
4500
|
+
isExpired: quoteExpired,
|
|
4501
|
+
onExpired: handleRefreshQuote
|
|
4502
|
+
}
|
|
4503
|
+
),
|
|
4504
|
+
quoteExpired && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
4505
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 13, color: "#f59e0b" }, children: "Quote expired, please refresh" }),
|
|
4506
|
+
/* @__PURE__ */ jsx(
|
|
4507
|
+
"button",
|
|
4508
|
+
{
|
|
4509
|
+
type: "button",
|
|
4510
|
+
onClick: handleRefreshQuote,
|
|
4511
|
+
style: {
|
|
4512
|
+
padding: "4px 12px",
|
|
4513
|
+
fontSize: 12,
|
|
4514
|
+
borderRadius: radii.pill,
|
|
4515
|
+
border: `1px solid ${colors.border}`,
|
|
4516
|
+
background: "transparent",
|
|
4517
|
+
color: colors.textPrimary,
|
|
4518
|
+
cursor: "pointer",
|
|
4519
|
+
fontFamily: fonts.family
|
|
4520
|
+
},
|
|
4521
|
+
children: "Refresh"
|
|
4522
|
+
}
|
|
4523
|
+
)
|
|
4524
|
+
] })
|
|
4525
|
+
] })
|
|
4526
|
+
}
|
|
4527
|
+
),
|
|
4528
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
4529
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
|
|
4530
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: "Amount" }),
|
|
4531
|
+
balance && /* @__PURE__ */ jsxs("span", { style: { fontSize: 13, lineHeight: 1.2, color: colors.textSecondary }, children: [
|
|
4532
|
+
"Balance: \xA0",
|
|
4533
|
+
formatBalanceTo2Decimals(balance),
|
|
4534
|
+
" ",
|
|
4535
|
+
FUNDING_TOKEN_SYMBOL2
|
|
4536
|
+
] })
|
|
4537
|
+
] }),
|
|
4538
|
+
/* @__PURE__ */ jsxs(
|
|
4539
|
+
"div",
|
|
4540
|
+
{
|
|
4541
|
+
style: {
|
|
4542
|
+
display: "flex",
|
|
4543
|
+
alignItems: "center",
|
|
4544
|
+
justifyContent: "space-between",
|
|
4545
|
+
height: 48,
|
|
4546
|
+
padding: "0 16px",
|
|
4547
|
+
borderRadius: radii.input,
|
|
4548
|
+
border: `1px solid ${amountInputFocused ? colors.borderFocused : colors.border}`,
|
|
4549
|
+
boxSizing: "border-box"
|
|
4550
|
+
},
|
|
4551
|
+
children: [
|
|
4552
|
+
/* @__PURE__ */ jsx(
|
|
4553
|
+
"input",
|
|
4554
|
+
{
|
|
4555
|
+
value: amount,
|
|
4556
|
+
onChange: handleAmountChange,
|
|
4557
|
+
onFocus: () => setAmountInputFocused(true),
|
|
4558
|
+
onBlur: () => setAmountInputFocused(false),
|
|
4559
|
+
placeholder: "0.00",
|
|
4560
|
+
type: "text",
|
|
4561
|
+
inputMode: "decimal",
|
|
4562
|
+
style: {
|
|
4563
|
+
flex: 1,
|
|
4564
|
+
border: "none",
|
|
4565
|
+
outline: "none",
|
|
4566
|
+
background: "transparent",
|
|
4567
|
+
color: amount ? colors.textPrimary : colors.textSecondary,
|
|
4568
|
+
fontSize: 14,
|
|
4569
|
+
fontFamily: fonts.family,
|
|
4570
|
+
lineHeight: 1.4,
|
|
4571
|
+
padding: 0
|
|
4572
|
+
}
|
|
4573
|
+
}
|
|
4574
|
+
),
|
|
4575
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: /* @__PURE__ */ jsx(
|
|
4576
|
+
"button",
|
|
4577
|
+
{
|
|
4578
|
+
type: "button",
|
|
4579
|
+
onClick: onMaxClick,
|
|
4580
|
+
style: {
|
|
4581
|
+
background: colors.textPrimary,
|
|
4582
|
+
border: "none",
|
|
4583
|
+
borderRadius: radii.pill,
|
|
4584
|
+
padding: "2px 8px",
|
|
4585
|
+
fontSize: 12,
|
|
4586
|
+
lineHeight: 1.4,
|
|
4587
|
+
fontWeight: 400,
|
|
4588
|
+
color: "#15181D",
|
|
4589
|
+
fontFamily: fonts.family,
|
|
4590
|
+
cursor: "pointer"
|
|
4591
|
+
},
|
|
4592
|
+
children: "Max"
|
|
4593
|
+
}
|
|
4594
|
+
) })
|
|
4595
|
+
]
|
|
4596
|
+
}
|
|
4597
|
+
)
|
|
4598
|
+
] }) })
|
|
4599
|
+
] })
|
|
4600
|
+
}
|
|
4601
|
+
)
|
|
4602
|
+
] })
|
|
4603
|
+
] })
|
|
4604
|
+
] }),
|
|
4605
|
+
/* @__PURE__ */ jsxs("div", { style: { padding: "20px 20px 0", display: "flex", flexDirection: "column", gap: 10, alignItems: "center" }, id: "WithdrawModalReceiveAmount", children: [
|
|
4606
|
+
!trackingWithdraw && amount && Number(amount) > 0 && /* @__PURE__ */ jsxs("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: [
|
|
4607
|
+
"You will receive : ",
|
|
4608
|
+
receiveAmount
|
|
4609
|
+
] }),
|
|
4610
|
+
orderInProgress && withdrawOrder && (() => {
|
|
4611
|
+
const fundingHash = txHash ?? withdrawOrder?.funding_tx_hash;
|
|
4612
|
+
const showFundingLink = fundingHash && fundingChainId;
|
|
4613
|
+
try {
|
|
4614
|
+
return /* @__PURE__ */ jsx("div", { style: { display: "none", flexDirection: "column", gap: 6, alignItems: "center" }, children: showFundingLink && /* @__PURE__ */ jsx(
|
|
4615
|
+
"a",
|
|
4616
|
+
{
|
|
4617
|
+
href: getExplorerUrl(fundingChainId, { txId: fundingHash }),
|
|
4618
|
+
target: "_blank",
|
|
4619
|
+
rel: "noopener noreferrer",
|
|
4620
|
+
style: { fontSize: 13, color: colors.textPrimary, textDecoration: "underline" },
|
|
4621
|
+
children: "Withdraw request transaction on explorer"
|
|
4622
|
+
}
|
|
4623
|
+
) });
|
|
4624
|
+
} catch {
|
|
4625
|
+
return /* @__PURE__ */ jsx("span", { style: { fontSize: 13, color: colors.textPrimary }, children: "Withdraw in progress." });
|
|
4626
|
+
}
|
|
4627
|
+
})(),
|
|
4628
|
+
orderInProgress && withdrawOrder && /* @__PURE__ */ jsxs("span", { style: { fontSize: 13, color: colors.textSecondary, display: "none", alignItems: "center", gap: 6 }, children: [
|
|
4629
|
+
"Order status: ",
|
|
4630
|
+
withdrawOrder.status,
|
|
4631
|
+
/* @__PURE__ */ jsx(
|
|
4632
|
+
"span",
|
|
4633
|
+
{
|
|
4634
|
+
style: {
|
|
4635
|
+
display: "inline-block",
|
|
4636
|
+
width: 10,
|
|
4637
|
+
height: 10,
|
|
4638
|
+
border: `2px solid ${colors.textSecondary}`,
|
|
4639
|
+
borderTopColor: "transparent",
|
|
4640
|
+
borderRadius: "50%",
|
|
4641
|
+
animation: "withdraw-modal-spin 0.7s linear infinite"
|
|
4642
|
+
},
|
|
4643
|
+
"aria-hidden": true
|
|
4644
|
+
}
|
|
4645
|
+
)
|
|
4646
|
+
] }),
|
|
4647
|
+
/* @__PURE__ */ jsx("style", { children: `@keyframes withdraw-modal-spin { to { transform: rotate(360deg); } }` }),
|
|
4648
|
+
orderSucceeded || trackingWithdraw ? null : /* @__PURE__ */ jsx(
|
|
4649
|
+
SubmitButton,
|
|
4650
|
+
{
|
|
4651
|
+
disabled: !canSubmit || isSubmitting,
|
|
4652
|
+
status,
|
|
4653
|
+
onClick: () => onSubmit?.({
|
|
4654
|
+
toAddress: address,
|
|
4655
|
+
amount: amount ?? "",
|
|
4656
|
+
token: token ?? "",
|
|
4657
|
+
tokenAddress: resolvedTokenAddress ?? apiQuote?.token_address ?? "",
|
|
4658
|
+
chain: chain ?? ""
|
|
4659
|
+
})
|
|
4660
|
+
}
|
|
4661
|
+
)
|
|
4662
|
+
] })
|
|
4663
|
+
]
|
|
4664
|
+
}
|
|
4665
|
+
);
|
|
4666
|
+
};
|
|
4667
|
+
var SubmitButton = ({ disabled, status, onClick }) => {
|
|
4668
|
+
const labels = {
|
|
4669
|
+
idle: disabled ? "Please fill in withdrawal information" : "Submit",
|
|
4670
|
+
pending: "Processing...",
|
|
4671
|
+
success: "Withdrawal successful",
|
|
4672
|
+
manual_review: "Under manual review"
|
|
4673
|
+
};
|
|
4674
|
+
const isDisabled = disabled || status !== "idle";
|
|
4675
|
+
return /* @__PURE__ */ jsx(
|
|
4676
|
+
"button",
|
|
4677
|
+
{
|
|
4678
|
+
type: "button",
|
|
4679
|
+
disabled: isDisabled,
|
|
4680
|
+
onClick,
|
|
4681
|
+
style: {
|
|
4682
|
+
width: 364,
|
|
4683
|
+
padding: "12px 0",
|
|
4684
|
+
borderRadius: radii.full,
|
|
4685
|
+
border: isDisabled ? `1px solid ${colors.buttonDisabledBorder}` : "none",
|
|
4686
|
+
background: isDisabled ? colors.buttonDisabledBg : colors.textPrimary,
|
|
4687
|
+
color: isDisabled ? colors.textSecondary : "#15181D",
|
|
4688
|
+
fontSize: 16,
|
|
4689
|
+
fontWeight: 500,
|
|
4690
|
+
lineHeight: 1.4,
|
|
4691
|
+
fontFamily: fonts.family,
|
|
4692
|
+
cursor: isDisabled ? "not-allowed" : "pointer",
|
|
4693
|
+
textAlign: "center"
|
|
4694
|
+
},
|
|
4695
|
+
children: labels[status]
|
|
4696
|
+
}
|
|
4697
|
+
);
|
|
4698
|
+
};
|
|
4699
|
+
|
|
4700
|
+
export { ClientIds, DEFAULT_FUNDING_CHAIN_ID, DEFAULT_FUNDING_TOKEN_ADDRESS, DepositDetailsPanel, DepositModal, DropdownField, SignInModal, WalletSelectionModal, WithdrawModal, clearSocialAccountInstance2 as clearSocialAccountInstance, configureMerchantApi, createDepositController, createFundingWithdrawExecutor, createMarketDataProvider, createOrder, createPredicateMarketPolicyAdapter, createWithdrawController, fetchErc20Balance, fetchFundingTokenBalance, findTokenDataFromChains, getChainInfo, getChains, getDepositOrder, getEnv, getExplorerUrl, getFixedAuthConfig, getFundingTokenAddress, getMerchantApiClient, getSDKConfig, getWithdrawOrder, initSDK, isFedCMSupported, isUsdtWithdrawDirect, notifyTwitterCallback, parseUnits, quote, registerPlatform, signInWithGoogle, signInWithTwitter, tryAutoReconnect };
|