@swype-org/react-sdk 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1766 -623
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -5
- package/dist/index.d.ts +87 -5
- package/dist/index.js +1768 -626
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { createContext, useRef,
|
|
1
|
+
import { createContext, useRef, useState, useCallback, useMemo, useContext, useEffect } from 'react';
|
|
2
2
|
import { PrivyProvider, usePrivy } from '@privy-io/react-auth';
|
|
3
|
-
import { createConfig, http, WagmiProvider,
|
|
3
|
+
import { createConfig, http, WagmiProvider, useConfig, useConnect, useSwitchChain } from 'wagmi';
|
|
4
4
|
import { mainnet, arbitrum, base } from 'wagmi/chains';
|
|
5
5
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
|
+
import { walletActions, createClient, custom } from 'viem';
|
|
8
|
+
import { parseAccount, getAddress } from 'viem/utils';
|
|
7
9
|
|
|
8
10
|
var __defProp = Object.defineProperty;
|
|
9
11
|
var __export = (target, all) => {
|
|
@@ -82,13 +84,19 @@ function SwypeProvider({
|
|
|
82
84
|
if (!queryClientRef.current) {
|
|
83
85
|
queryClientRef.current = new QueryClient();
|
|
84
86
|
}
|
|
87
|
+
const [depositAmount, setDepositAmountRaw] = useState(null);
|
|
88
|
+
const setDepositAmount = useCallback((amount) => {
|
|
89
|
+
setDepositAmountRaw(amount);
|
|
90
|
+
}, []);
|
|
85
91
|
const value = useMemo(
|
|
86
92
|
() => ({
|
|
87
93
|
apiBaseUrl,
|
|
88
94
|
theme,
|
|
89
|
-
tokens: getTheme(theme)
|
|
95
|
+
tokens: getTheme(theme),
|
|
96
|
+
depositAmount,
|
|
97
|
+
setDepositAmount
|
|
90
98
|
}),
|
|
91
|
-
[apiBaseUrl, theme]
|
|
99
|
+
[apiBaseUrl, theme, depositAmount, setDepositAmount]
|
|
92
100
|
);
|
|
93
101
|
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClientRef.current, children: /* @__PURE__ */ jsx(WagmiProvider, { config: wagmiConfig, children: /* @__PURE__ */ jsx(
|
|
94
102
|
PrivyProvider,
|
|
@@ -110,6 +118,20 @@ function useSwypeConfig() {
|
|
|
110
118
|
}
|
|
111
119
|
return ctx;
|
|
112
120
|
}
|
|
121
|
+
function useSwypeDepositAmount() {
|
|
122
|
+
const ctx = useContext(SwypeContext);
|
|
123
|
+
if (!ctx) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
"useSwypeDepositAmount must be used within a <SwypeProvider>"
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
/** Current deposit amount, or null if not set */
|
|
130
|
+
amount: ctx.depositAmount,
|
|
131
|
+
/** Set the deposit amount (pass null to clear) */
|
|
132
|
+
setAmount: ctx.setDepositAmount
|
|
133
|
+
};
|
|
134
|
+
}
|
|
113
135
|
|
|
114
136
|
// src/api.ts
|
|
115
137
|
var api_exports = {};
|
|
@@ -121,7 +143,9 @@ __export(api_exports, {
|
|
|
121
143
|
fetchProviders: () => fetchProviders,
|
|
122
144
|
fetchTransfer: () => fetchTransfer,
|
|
123
145
|
reportActionCompletion: () => reportActionCompletion,
|
|
124
|
-
|
|
146
|
+
signTransfer: () => signTransfer,
|
|
147
|
+
updateUserConfig: () => updateUserConfig,
|
|
148
|
+
updateUserConfigBySession: () => updateUserConfigBySession
|
|
125
149
|
});
|
|
126
150
|
async function throwApiError(res) {
|
|
127
151
|
const body = await res.json().catch(() => null);
|
|
@@ -188,6 +212,18 @@ async function fetchTransfer(apiBaseUrl, token, transferId) {
|
|
|
188
212
|
if (!res.ok) await throwApiError(res);
|
|
189
213
|
return await res.json();
|
|
190
214
|
}
|
|
215
|
+
async function signTransfer(apiBaseUrl, token, transferId, signedUserOp) {
|
|
216
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
|
|
217
|
+
method: "PATCH",
|
|
218
|
+
headers: {
|
|
219
|
+
"Content-Type": "application/json",
|
|
220
|
+
Authorization: `Bearer ${token}`
|
|
221
|
+
},
|
|
222
|
+
body: JSON.stringify({ signedUserOp })
|
|
223
|
+
});
|
|
224
|
+
if (!res.ok) await throwApiError(res);
|
|
225
|
+
return await res.json();
|
|
226
|
+
}
|
|
191
227
|
async function fetchAuthorizationSession(apiBaseUrl, sessionId) {
|
|
192
228
|
const res = await fetch(
|
|
193
229
|
`${apiBaseUrl}/v1/authorization-sessions/${sessionId}`
|
|
@@ -206,6 +242,17 @@ async function updateUserConfig(apiBaseUrl, token, config) {
|
|
|
206
242
|
});
|
|
207
243
|
if (!res.ok) await throwApiError(res);
|
|
208
244
|
}
|
|
245
|
+
async function updateUserConfigBySession(apiBaseUrl, sessionId, config) {
|
|
246
|
+
const res = await fetch(
|
|
247
|
+
`${apiBaseUrl}/v1/authorization-sessions/${sessionId}/user-config`,
|
|
248
|
+
{
|
|
249
|
+
method: "PATCH",
|
|
250
|
+
headers: { "Content-Type": "application/json" },
|
|
251
|
+
body: JSON.stringify({ config })
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
if (!res.ok) await throwApiError(res);
|
|
255
|
+
}
|
|
209
256
|
async function reportActionCompletion(apiBaseUrl, actionId, result) {
|
|
210
257
|
const res = await fetch(
|
|
211
258
|
`${apiBaseUrl}/v1/authorization-actions/${actionId}`,
|
|
@@ -218,6 +265,443 @@ async function reportActionCompletion(apiBaseUrl, actionId, result) {
|
|
|
218
265
|
if (!res.ok) await throwApiError(res);
|
|
219
266
|
return await res.json();
|
|
220
267
|
}
|
|
268
|
+
|
|
269
|
+
// node_modules/@wagmi/core/dist/esm/version.js
|
|
270
|
+
var version = "2.22.1";
|
|
271
|
+
|
|
272
|
+
// node_modules/@wagmi/core/dist/esm/utils/getVersion.js
|
|
273
|
+
var getVersion = () => `@wagmi/core@${version}`;
|
|
274
|
+
|
|
275
|
+
// node_modules/@wagmi/core/dist/esm/errors/base.js
|
|
276
|
+
var __classPrivateFieldGet = function(receiver, state, kind, f) {
|
|
277
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
278
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
279
|
+
};
|
|
280
|
+
var _BaseError_instances;
|
|
281
|
+
var _BaseError_walk;
|
|
282
|
+
var BaseError = class _BaseError extends Error {
|
|
283
|
+
get docsBaseUrl() {
|
|
284
|
+
return "https://wagmi.sh/core";
|
|
285
|
+
}
|
|
286
|
+
get version() {
|
|
287
|
+
return getVersion();
|
|
288
|
+
}
|
|
289
|
+
constructor(shortMessage, options = {}) {
|
|
290
|
+
super();
|
|
291
|
+
_BaseError_instances.add(this);
|
|
292
|
+
Object.defineProperty(this, "details", {
|
|
293
|
+
enumerable: true,
|
|
294
|
+
configurable: true,
|
|
295
|
+
writable: true,
|
|
296
|
+
value: void 0
|
|
297
|
+
});
|
|
298
|
+
Object.defineProperty(this, "docsPath", {
|
|
299
|
+
enumerable: true,
|
|
300
|
+
configurable: true,
|
|
301
|
+
writable: true,
|
|
302
|
+
value: void 0
|
|
303
|
+
});
|
|
304
|
+
Object.defineProperty(this, "metaMessages", {
|
|
305
|
+
enumerable: true,
|
|
306
|
+
configurable: true,
|
|
307
|
+
writable: true,
|
|
308
|
+
value: void 0
|
|
309
|
+
});
|
|
310
|
+
Object.defineProperty(this, "shortMessage", {
|
|
311
|
+
enumerable: true,
|
|
312
|
+
configurable: true,
|
|
313
|
+
writable: true,
|
|
314
|
+
value: void 0
|
|
315
|
+
});
|
|
316
|
+
Object.defineProperty(this, "name", {
|
|
317
|
+
enumerable: true,
|
|
318
|
+
configurable: true,
|
|
319
|
+
writable: true,
|
|
320
|
+
value: "WagmiCoreError"
|
|
321
|
+
});
|
|
322
|
+
const details = options.cause instanceof _BaseError ? options.cause.details : options.cause?.message ? options.cause.message : options.details;
|
|
323
|
+
const docsPath = options.cause instanceof _BaseError ? options.cause.docsPath || options.docsPath : options.docsPath;
|
|
324
|
+
this.message = [
|
|
325
|
+
shortMessage || "An error occurred.",
|
|
326
|
+
"",
|
|
327
|
+
...options.metaMessages ? [...options.metaMessages, ""] : [],
|
|
328
|
+
...docsPath ? [
|
|
329
|
+
`Docs: ${this.docsBaseUrl}${docsPath}.html${options.docsSlug ? `#${options.docsSlug}` : ""}`
|
|
330
|
+
] : [],
|
|
331
|
+
...details ? [`Details: ${details}`] : [],
|
|
332
|
+
`Version: ${this.version}`
|
|
333
|
+
].join("\n");
|
|
334
|
+
if (options.cause)
|
|
335
|
+
this.cause = options.cause;
|
|
336
|
+
this.details = details;
|
|
337
|
+
this.docsPath = docsPath;
|
|
338
|
+
this.metaMessages = options.metaMessages;
|
|
339
|
+
this.shortMessage = shortMessage;
|
|
340
|
+
}
|
|
341
|
+
walk(fn) {
|
|
342
|
+
return __classPrivateFieldGet(this, _BaseError_instances, "m", _BaseError_walk).call(this, this, fn);
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
_BaseError_instances = /* @__PURE__ */ new WeakSet(), _BaseError_walk = function _BaseError_walk2(err, fn) {
|
|
346
|
+
if (fn?.(err))
|
|
347
|
+
return err;
|
|
348
|
+
if (err.cause)
|
|
349
|
+
return __classPrivateFieldGet(this, _BaseError_instances, "m", _BaseError_walk2).call(this, err.cause, fn);
|
|
350
|
+
return err;
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
// node_modules/@wagmi/core/dist/esm/errors/config.js
|
|
354
|
+
var ConnectorNotConnectedError = class extends BaseError {
|
|
355
|
+
constructor() {
|
|
356
|
+
super("Connector not connected.");
|
|
357
|
+
Object.defineProperty(this, "name", {
|
|
358
|
+
enumerable: true,
|
|
359
|
+
configurable: true,
|
|
360
|
+
writable: true,
|
|
361
|
+
value: "ConnectorNotConnectedError"
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
var ConnectorAccountNotFoundError = class extends BaseError {
|
|
366
|
+
constructor({ address, connector }) {
|
|
367
|
+
super(`Account "${address}" not found for connector "${connector.name}".`);
|
|
368
|
+
Object.defineProperty(this, "name", {
|
|
369
|
+
enumerable: true,
|
|
370
|
+
configurable: true,
|
|
371
|
+
writable: true,
|
|
372
|
+
value: "ConnectorAccountNotFoundError"
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
var ConnectorChainMismatchError = class extends BaseError {
|
|
377
|
+
constructor({ connectionChainId, connectorChainId }) {
|
|
378
|
+
super(`The current chain of the connector (id: ${connectorChainId}) does not match the connection's chain (id: ${connectionChainId}).`, {
|
|
379
|
+
metaMessages: [
|
|
380
|
+
`Current Chain ID: ${connectorChainId}`,
|
|
381
|
+
`Expected Chain ID: ${connectionChainId}`
|
|
382
|
+
]
|
|
383
|
+
});
|
|
384
|
+
Object.defineProperty(this, "name", {
|
|
385
|
+
enumerable: true,
|
|
386
|
+
configurable: true,
|
|
387
|
+
writable: true,
|
|
388
|
+
value: "ConnectorChainMismatchError"
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
var ConnectorUnavailableReconnectingError = class extends BaseError {
|
|
393
|
+
constructor({ connector }) {
|
|
394
|
+
super(`Connector "${connector.name}" unavailable while reconnecting.`, {
|
|
395
|
+
details: [
|
|
396
|
+
"During the reconnection step, the only connector methods guaranteed to be available are: `id`, `name`, `type`, `uid`.",
|
|
397
|
+
"All other methods are not guaranteed to be available until reconnection completes and connectors are fully restored.",
|
|
398
|
+
"This error commonly occurs for connectors that asynchronously inject after reconnection has already started."
|
|
399
|
+
].join(" ")
|
|
400
|
+
});
|
|
401
|
+
Object.defineProperty(this, "name", {
|
|
402
|
+
enumerable: true,
|
|
403
|
+
configurable: true,
|
|
404
|
+
writable: true,
|
|
405
|
+
value: "ConnectorUnavailableReconnectingError"
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
async function getConnectorClient(config, parameters = {}) {
|
|
410
|
+
const { assertChainId = true } = parameters;
|
|
411
|
+
let connection;
|
|
412
|
+
if (parameters.connector) {
|
|
413
|
+
const { connector: connector2 } = parameters;
|
|
414
|
+
if (config.state.status === "reconnecting" && !connector2.getAccounts && !connector2.getChainId)
|
|
415
|
+
throw new ConnectorUnavailableReconnectingError({ connector: connector2 });
|
|
416
|
+
const [accounts, chainId2] = await Promise.all([
|
|
417
|
+
connector2.getAccounts().catch((e) => {
|
|
418
|
+
if (parameters.account === null)
|
|
419
|
+
return [];
|
|
420
|
+
throw e;
|
|
421
|
+
}),
|
|
422
|
+
connector2.getChainId()
|
|
423
|
+
]);
|
|
424
|
+
connection = {
|
|
425
|
+
accounts,
|
|
426
|
+
chainId: chainId2,
|
|
427
|
+
connector: connector2
|
|
428
|
+
};
|
|
429
|
+
} else
|
|
430
|
+
connection = config.state.connections.get(config.state.current);
|
|
431
|
+
if (!connection)
|
|
432
|
+
throw new ConnectorNotConnectedError();
|
|
433
|
+
const chainId = parameters.chainId ?? connection.chainId;
|
|
434
|
+
const connectorChainId = await connection.connector.getChainId();
|
|
435
|
+
if (assertChainId && connectorChainId !== chainId)
|
|
436
|
+
throw new ConnectorChainMismatchError({
|
|
437
|
+
connectionChainId: chainId,
|
|
438
|
+
connectorChainId
|
|
439
|
+
});
|
|
440
|
+
const connector = connection.connector;
|
|
441
|
+
if (connector.getClient)
|
|
442
|
+
return connector.getClient({ chainId });
|
|
443
|
+
const account = parseAccount(parameters.account ?? connection.accounts[0]);
|
|
444
|
+
if (account)
|
|
445
|
+
account.address = getAddress(account.address);
|
|
446
|
+
if (parameters.account && !connection.accounts.some((x) => x.toLowerCase() === account.address.toLowerCase()))
|
|
447
|
+
throw new ConnectorAccountNotFoundError({
|
|
448
|
+
address: account.address,
|
|
449
|
+
connector
|
|
450
|
+
});
|
|
451
|
+
const chain = config.chains.find((chain2) => chain2.id === chainId);
|
|
452
|
+
const provider = await connection.connector.getProvider({ chainId });
|
|
453
|
+
return createClient({
|
|
454
|
+
account,
|
|
455
|
+
chain,
|
|
456
|
+
name: "Connector Client",
|
|
457
|
+
transport: (opts) => custom(provider)({ ...opts, retryCount: 0 })
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// node_modules/@wagmi/core/dist/esm/actions/getAccount.js
|
|
462
|
+
function getAccount(config) {
|
|
463
|
+
const uid = config.state.current;
|
|
464
|
+
const connection = config.state.connections.get(uid);
|
|
465
|
+
const addresses = connection?.accounts;
|
|
466
|
+
const address = addresses?.[0];
|
|
467
|
+
const chain = config.chains.find((chain2) => chain2.id === connection?.chainId);
|
|
468
|
+
const status = config.state.status;
|
|
469
|
+
switch (status) {
|
|
470
|
+
case "connected":
|
|
471
|
+
return {
|
|
472
|
+
address,
|
|
473
|
+
addresses,
|
|
474
|
+
chain,
|
|
475
|
+
chainId: connection?.chainId,
|
|
476
|
+
connector: connection?.connector,
|
|
477
|
+
isConnected: true,
|
|
478
|
+
isConnecting: false,
|
|
479
|
+
isDisconnected: false,
|
|
480
|
+
isReconnecting: false,
|
|
481
|
+
status
|
|
482
|
+
};
|
|
483
|
+
case "reconnecting":
|
|
484
|
+
return {
|
|
485
|
+
address,
|
|
486
|
+
addresses,
|
|
487
|
+
chain,
|
|
488
|
+
chainId: connection?.chainId,
|
|
489
|
+
connector: connection?.connector,
|
|
490
|
+
isConnected: !!address,
|
|
491
|
+
isConnecting: false,
|
|
492
|
+
isDisconnected: false,
|
|
493
|
+
isReconnecting: true,
|
|
494
|
+
status
|
|
495
|
+
};
|
|
496
|
+
case "connecting":
|
|
497
|
+
return {
|
|
498
|
+
address,
|
|
499
|
+
addresses,
|
|
500
|
+
chain,
|
|
501
|
+
chainId: connection?.chainId,
|
|
502
|
+
connector: connection?.connector,
|
|
503
|
+
isConnected: false,
|
|
504
|
+
isConnecting: true,
|
|
505
|
+
isDisconnected: false,
|
|
506
|
+
isReconnecting: false,
|
|
507
|
+
status
|
|
508
|
+
};
|
|
509
|
+
case "disconnected":
|
|
510
|
+
return {
|
|
511
|
+
address: void 0,
|
|
512
|
+
addresses: void 0,
|
|
513
|
+
chain: void 0,
|
|
514
|
+
chainId: void 0,
|
|
515
|
+
connector: void 0,
|
|
516
|
+
isConnected: false,
|
|
517
|
+
isConnecting: false,
|
|
518
|
+
isDisconnected: true,
|
|
519
|
+
isReconnecting: false,
|
|
520
|
+
status
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
async function getWalletClient(config, parameters = {}) {
|
|
525
|
+
const client = await getConnectorClient(config, parameters);
|
|
526
|
+
return client.extend(walletActions);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// src/authorization/upgrade.ts
|
|
530
|
+
function isNonEmptyString(value) {
|
|
531
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
532
|
+
}
|
|
533
|
+
function isValidChainId(value) {
|
|
534
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0;
|
|
535
|
+
}
|
|
536
|
+
function isRpcClient(value) {
|
|
537
|
+
return typeof value === "object" && value !== null && "request" in value && typeof value.request === "function";
|
|
538
|
+
}
|
|
539
|
+
function sleep(ms) {
|
|
540
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
541
|
+
}
|
|
542
|
+
async function pollCallsStatus(client, bundleId, label, timeoutMs = 12e4, intervalMs = 3e3) {
|
|
543
|
+
const deadline = Date.now() + timeoutMs;
|
|
544
|
+
while (Date.now() < deadline) {
|
|
545
|
+
const raw = await client.request({
|
|
546
|
+
method: "wallet_getCallsStatus",
|
|
547
|
+
params: [bundleId]
|
|
548
|
+
});
|
|
549
|
+
const result = raw;
|
|
550
|
+
const status = result.status;
|
|
551
|
+
console.info(`[swype-sdk][upgrade] ${label} status:`, status);
|
|
552
|
+
if (status === 200 || status === "CONFIRMED" || status === "confirmed") {
|
|
553
|
+
const txHash = result.receipts?.[0]?.transactionHash ?? "";
|
|
554
|
+
if (!txHash) {
|
|
555
|
+
console.warn(`[swype-sdk][upgrade] ${label}: confirmed but no receipt txHash.`);
|
|
556
|
+
}
|
|
557
|
+
return txHash;
|
|
558
|
+
}
|
|
559
|
+
if (typeof status === "number" && status >= 400) {
|
|
560
|
+
throw new Error(
|
|
561
|
+
`${label} failed with status ${status}. Receipts: ${JSON.stringify(result.receipts ?? [])}`
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
if (typeof status === "string" && (status.toLowerCase().includes("fail") || status.toLowerCase().includes("error"))) {
|
|
565
|
+
throw new Error(
|
|
566
|
+
`${label} failed: ${status}. Receipts: ${JSON.stringify(result.receipts ?? [])}`
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
await sleep(intervalMs);
|
|
570
|
+
}
|
|
571
|
+
throw new Error(`${label} timed out after ${timeoutMs / 1e3}s.`);
|
|
572
|
+
}
|
|
573
|
+
async function sendCalls(client, callsParams, label) {
|
|
574
|
+
try {
|
|
575
|
+
const result = await client.request({
|
|
576
|
+
method: "wallet_sendCalls",
|
|
577
|
+
params: [callsParams]
|
|
578
|
+
});
|
|
579
|
+
const bundleId = typeof result === "string" ? result : result?.id;
|
|
580
|
+
if (!bundleId) {
|
|
581
|
+
throw new Error(`${label}: wallet_sendCalls returned an unexpected result: ${JSON.stringify(result)}`);
|
|
582
|
+
}
|
|
583
|
+
return bundleId;
|
|
584
|
+
} catch (err) {
|
|
585
|
+
const msg = err.message ?? "";
|
|
586
|
+
if (msg.includes("Unauthorized") || msg.includes("-32006")) {
|
|
587
|
+
throw new Error(
|
|
588
|
+
"MetaMask smart accounts may not be enabled or may not be supported on this chain. Please ensure you are using a supported network and that smart accounts are enabled in MetaMask Settings \u2192 Experimental."
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
throw new Error(`${label} failed: ${msg}`);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
async function submitUpgradeTransaction(params) {
|
|
595
|
+
const { walletClient, sender, metadata } = params;
|
|
596
|
+
const addKeyCalldata = metadata?.addKeyCalldata;
|
|
597
|
+
if (!isNonEmptyString(addKeyCalldata)) {
|
|
598
|
+
throw new Error("Incomplete upgrade metadata: missing addKeyCalldata.");
|
|
599
|
+
}
|
|
600
|
+
const resolvedSmartAccountAddress = metadata?.smartAccountAddress ?? sender;
|
|
601
|
+
if (!isNonEmptyString(resolvedSmartAccountAddress)) {
|
|
602
|
+
throw new Error("No connected account address found for smart account upgrade.");
|
|
603
|
+
}
|
|
604
|
+
const chainId = metadata?.upgradePayload?.authorization?.chainId;
|
|
605
|
+
if (!isValidChainId(chainId)) {
|
|
606
|
+
throw new Error("Invalid or missing chainId in upgrade metadata.");
|
|
607
|
+
}
|
|
608
|
+
if (!isRpcClient(walletClient)) {
|
|
609
|
+
throw new Error(
|
|
610
|
+
"Connected wallet client does not support request(). EIP-7702 upgrade requires a wallet client with raw RPC access."
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
const hexChainId = `0x${chainId.toString(16)}`;
|
|
614
|
+
console.info(
|
|
615
|
+
"[swype-sdk][upgrade] Step 1/2: Triggering EIP-7702 upgrade via wallet_sendCalls.",
|
|
616
|
+
{ from: resolvedSmartAccountAddress, chainId: hexChainId }
|
|
617
|
+
);
|
|
618
|
+
const upgradeBundleId = await sendCalls(
|
|
619
|
+
walletClient,
|
|
620
|
+
{
|
|
621
|
+
version: "2.0.0",
|
|
622
|
+
from: resolvedSmartAccountAddress,
|
|
623
|
+
chainId: hexChainId,
|
|
624
|
+
atomicRequired: false,
|
|
625
|
+
calls: [{ to: resolvedSmartAccountAddress, value: "0x0" }]
|
|
626
|
+
},
|
|
627
|
+
"EIP-7702 upgrade"
|
|
628
|
+
);
|
|
629
|
+
console.info("[swype-sdk][upgrade] Upgrade bundle submitted. Polling for confirmation\u2026", {
|
|
630
|
+
bundleId: upgradeBundleId
|
|
631
|
+
});
|
|
632
|
+
const upgradeTxHash = await pollCallsStatus(
|
|
633
|
+
walletClient,
|
|
634
|
+
upgradeBundleId,
|
|
635
|
+
"EIP-7702 upgrade"
|
|
636
|
+
);
|
|
637
|
+
console.info("[swype-sdk][upgrade] Step 1/2 complete: account upgraded.", {
|
|
638
|
+
txHash: upgradeTxHash
|
|
639
|
+
});
|
|
640
|
+
console.info(
|
|
641
|
+
"[swype-sdk][upgrade] Step 2/2: Registering passkey via wallet_sendCalls (addKey)."
|
|
642
|
+
);
|
|
643
|
+
const addKeyBundleId = await sendCalls(
|
|
644
|
+
walletClient,
|
|
645
|
+
{
|
|
646
|
+
version: "2.0.0",
|
|
647
|
+
from: resolvedSmartAccountAddress,
|
|
648
|
+
chainId: hexChainId,
|
|
649
|
+
atomicRequired: false,
|
|
650
|
+
calls: [
|
|
651
|
+
{
|
|
652
|
+
to: resolvedSmartAccountAddress,
|
|
653
|
+
value: "0x0",
|
|
654
|
+
data: addKeyCalldata
|
|
655
|
+
}
|
|
656
|
+
]
|
|
657
|
+
},
|
|
658
|
+
"Passkey registration (addKey)"
|
|
659
|
+
);
|
|
660
|
+
console.info("[swype-sdk][upgrade] addKey bundle submitted. Polling for confirmation\u2026", {
|
|
661
|
+
bundleId: addKeyBundleId
|
|
662
|
+
});
|
|
663
|
+
const addKeyTxHash = await pollCallsStatus(
|
|
664
|
+
walletClient,
|
|
665
|
+
addKeyBundleId,
|
|
666
|
+
"Passkey registration"
|
|
667
|
+
);
|
|
668
|
+
console.info("[swype-sdk][upgrade] Step 2/2 complete: passkey registered.", {
|
|
669
|
+
txHash: addKeyTxHash
|
|
670
|
+
});
|
|
671
|
+
return {
|
|
672
|
+
txHash: addKeyTxHash || upgradeTxHash,
|
|
673
|
+
smartAccountAddress: resolvedSmartAccountAddress
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// src/hooks.ts
|
|
678
|
+
async function waitForWalletClient(wagmiConfig2, maxAttempts = 15, intervalMs = 200) {
|
|
679
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
680
|
+
try {
|
|
681
|
+
return await getWalletClient(wagmiConfig2);
|
|
682
|
+
} catch {
|
|
683
|
+
if (i === maxAttempts - 1) {
|
|
684
|
+
throw new Error("Wallet not ready. Please try again.");
|
|
685
|
+
}
|
|
686
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
throw new Error("Wallet not ready. Please try again.");
|
|
690
|
+
}
|
|
691
|
+
function extractErrorMessage(err) {
|
|
692
|
+
if (err instanceof Error) return err.message;
|
|
693
|
+
if (typeof err === "string") return err;
|
|
694
|
+
if (err && typeof err === "object") {
|
|
695
|
+
const maybeMessage = err.message;
|
|
696
|
+
if (typeof maybeMessage === "string") return maybeMessage;
|
|
697
|
+
}
|
|
698
|
+
return "Failed to upgrade account";
|
|
699
|
+
}
|
|
700
|
+
function isMetaMaskConnector(account) {
|
|
701
|
+
const connectorName = account.connector?.name?.toLowerCase() ?? "";
|
|
702
|
+
const connectorId = account.connector?.id?.toLowerCase() ?? "";
|
|
703
|
+
return connectorName.includes("metamask") || connectorId.includes("metamask");
|
|
704
|
+
}
|
|
221
705
|
function useTransferPolling(intervalMs = 3e3) {
|
|
222
706
|
const { apiBaseUrl } = useSwypeConfig();
|
|
223
707
|
const { getAccessToken } = usePrivy();
|
|
@@ -268,31 +752,45 @@ function useTransferPolling(intervalMs = 3e3) {
|
|
|
268
752
|
}
|
|
269
753
|
function useAuthorizationExecutor() {
|
|
270
754
|
const { apiBaseUrl } = useSwypeConfig();
|
|
271
|
-
const
|
|
755
|
+
const wagmiConfig2 = useConfig();
|
|
272
756
|
const { connectAsync, connectors } = useConnect();
|
|
273
757
|
const { switchChainAsync } = useSwitchChain();
|
|
274
|
-
const { signTypedDataAsync } = useSignTypedData();
|
|
275
|
-
const publicClient = usePublicClient();
|
|
276
|
-
const { data: walletClient } = useWalletClient();
|
|
277
758
|
const [executing, setExecuting] = useState(false);
|
|
278
759
|
const [results, setResults] = useState([]);
|
|
279
760
|
const [error, setError] = useState(null);
|
|
761
|
+
const [currentAction, setCurrentAction] = useState(null);
|
|
280
762
|
const executingRef = useRef(false);
|
|
763
|
+
const [pendingSelectSource, setPendingSelectSource] = useState(null);
|
|
764
|
+
const selectSourceResolverRef = useRef(null);
|
|
765
|
+
const resolveSelectSource = useCallback((selection) => {
|
|
766
|
+
if (selectSourceResolverRef.current) {
|
|
767
|
+
selectSourceResolverRef.current(selection);
|
|
768
|
+
selectSourceResolverRef.current = null;
|
|
769
|
+
setPendingSelectSource(null);
|
|
770
|
+
}
|
|
771
|
+
}, []);
|
|
772
|
+
const sessionIdRef = useRef(null);
|
|
281
773
|
const executeOpenProvider = useCallback(
|
|
282
774
|
async (action) => {
|
|
283
775
|
try {
|
|
284
|
-
|
|
285
|
-
|
|
776
|
+
const account = getAccount(wagmiConfig2);
|
|
777
|
+
if (account.isConnected && account.address) {
|
|
778
|
+
const hexChainId2 = account.chainId ? `0x${account.chainId.toString(16)}` : void 0;
|
|
286
779
|
return {
|
|
287
780
|
actionId: action.id,
|
|
288
781
|
type: action.type,
|
|
289
782
|
status: "success",
|
|
290
|
-
message: `Connected. Account: ${address}, Chain: ${hexChainId2}`,
|
|
291
|
-
data: { accounts: [address], chainId: hexChainId2 }
|
|
783
|
+
message: `Connected. Account: ${account.address}, Chain: ${hexChainId2}`,
|
|
784
|
+
data: { accounts: [account.address], chainId: hexChainId2 }
|
|
292
785
|
};
|
|
293
786
|
}
|
|
294
787
|
const targetId = action.metadata?.wagmiConnectorId;
|
|
295
|
-
const
|
|
788
|
+
const metaMaskConnector = connectors.find((c) => {
|
|
789
|
+
const id = c.id.toLowerCase();
|
|
790
|
+
const name = c.name.toLowerCase();
|
|
791
|
+
return id.includes("metamask") || name.includes("metamask");
|
|
792
|
+
});
|
|
793
|
+
const connector = targetId ? connectors.find((c) => c.id === targetId) ?? metaMaskConnector ?? connectors[0] : metaMaskConnector ?? connectors[0];
|
|
296
794
|
if (!connector) {
|
|
297
795
|
return {
|
|
298
796
|
actionId: action.id,
|
|
@@ -319,243 +817,231 @@ function useAuthorizationExecutor() {
|
|
|
319
817
|
};
|
|
320
818
|
}
|
|
321
819
|
},
|
|
322
|
-
[
|
|
820
|
+
[wagmiConfig2, connectors, connectAsync]
|
|
323
821
|
);
|
|
324
|
-
const
|
|
822
|
+
const executeSelectSource = useCallback(
|
|
325
823
|
async (action) => {
|
|
326
824
|
try {
|
|
327
|
-
const
|
|
328
|
-
|
|
825
|
+
const options = action.metadata?.options;
|
|
826
|
+
const recommended = action.metadata?.recommended;
|
|
827
|
+
if (!options || options.length <= 1) {
|
|
828
|
+
const selection2 = recommended ?? { chainName: "Base", tokenSymbol: "USDC" };
|
|
329
829
|
return {
|
|
330
830
|
actionId: action.id,
|
|
331
831
|
type: action.type,
|
|
332
|
-
status: "
|
|
333
|
-
message:
|
|
832
|
+
status: "success",
|
|
833
|
+
message: `Auto-selected ${selection2.tokenSymbol} on ${selection2.chainName}.`,
|
|
834
|
+
data: {
|
|
835
|
+
selectedChainName: selection2.chainName,
|
|
836
|
+
selectedTokenSymbol: selection2.tokenSymbol
|
|
837
|
+
}
|
|
334
838
|
};
|
|
335
839
|
}
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
840
|
+
const selection = await new Promise((resolve) => {
|
|
841
|
+
selectSourceResolverRef.current = resolve;
|
|
842
|
+
setPendingSelectSource(action);
|
|
843
|
+
});
|
|
339
844
|
return {
|
|
340
845
|
actionId: action.id,
|
|
341
846
|
type: action.type,
|
|
342
847
|
status: "success",
|
|
343
|
-
message: `
|
|
344
|
-
data: {
|
|
848
|
+
message: `Selected ${selection.tokenSymbol} on ${selection.chainName}.`,
|
|
849
|
+
data: {
|
|
850
|
+
selectedChainName: selection.chainName,
|
|
851
|
+
selectedTokenSymbol: selection.tokenSymbol
|
|
852
|
+
}
|
|
345
853
|
};
|
|
346
854
|
} catch (err) {
|
|
347
855
|
return {
|
|
348
856
|
actionId: action.id,
|
|
349
857
|
type: action.type,
|
|
350
858
|
status: "error",
|
|
351
|
-
message: err instanceof Error ? err.message : "Failed to
|
|
859
|
+
message: err instanceof Error ? err.message : "Failed to select source"
|
|
352
860
|
};
|
|
353
861
|
}
|
|
354
862
|
},
|
|
355
|
-
[
|
|
863
|
+
[]
|
|
356
864
|
);
|
|
357
|
-
const
|
|
865
|
+
const executeSwitchChain = useCallback(
|
|
358
866
|
async (action) => {
|
|
359
867
|
try {
|
|
360
|
-
const
|
|
361
|
-
const
|
|
362
|
-
if (!
|
|
868
|
+
const account = getAccount(wagmiConfig2);
|
|
869
|
+
const targetChainIdHex = action.metadata?.targetChainId;
|
|
870
|
+
if (!targetChainIdHex) {
|
|
363
871
|
return {
|
|
364
872
|
actionId: action.id,
|
|
365
873
|
type: action.type,
|
|
366
874
|
status: "error",
|
|
367
|
-
message: "
|
|
875
|
+
message: "No targetChainId in action metadata."
|
|
368
876
|
};
|
|
369
877
|
}
|
|
370
|
-
|
|
878
|
+
const targetChainIdNum = parseInt(targetChainIdHex, 16);
|
|
879
|
+
const hexChainId = `0x${targetChainIdNum.toString(16)}`;
|
|
880
|
+
if (account.chainId === targetChainIdNum) {
|
|
371
881
|
return {
|
|
372
882
|
actionId: action.id,
|
|
373
883
|
type: action.type,
|
|
374
|
-
status: "
|
|
375
|
-
message:
|
|
884
|
+
status: "success",
|
|
885
|
+
message: `Already on chain ${hexChainId}. Skipped.`,
|
|
886
|
+
data: { chainId: hexChainId, switched: false }
|
|
376
887
|
};
|
|
377
888
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
889
|
+
await switchChainAsync({ chainId: targetChainIdNum });
|
|
890
|
+
return {
|
|
891
|
+
actionId: action.id,
|
|
892
|
+
type: action.type,
|
|
893
|
+
status: "success",
|
|
894
|
+
message: `Switched to chain ${hexChainId}.`,
|
|
895
|
+
data: { chainId: hexChainId, switched: true }
|
|
896
|
+
};
|
|
897
|
+
} catch (err) {
|
|
898
|
+
return {
|
|
899
|
+
actionId: action.id,
|
|
900
|
+
type: action.type,
|
|
901
|
+
status: "error",
|
|
902
|
+
message: err instanceof Error ? err.message : "Failed to switch chain"
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
},
|
|
906
|
+
[wagmiConfig2, switchChainAsync]
|
|
907
|
+
);
|
|
908
|
+
const executeRegisterPasskey = useCallback(
|
|
909
|
+
async (action) => {
|
|
910
|
+
try {
|
|
911
|
+
const account = getAccount(wagmiConfig2);
|
|
912
|
+
const challenge = new Uint8Array(32);
|
|
913
|
+
crypto.getRandomValues(challenge);
|
|
914
|
+
const credential = await navigator.credentials.create({
|
|
915
|
+
publicKey: {
|
|
916
|
+
challenge,
|
|
917
|
+
rp: {
|
|
918
|
+
name: "Swype",
|
|
919
|
+
id: window.location.hostname
|
|
920
|
+
},
|
|
921
|
+
user: {
|
|
922
|
+
id: new TextEncoder().encode(account.address ?? "user"),
|
|
923
|
+
name: account.address ?? "Swype User",
|
|
924
|
+
displayName: "Swype User"
|
|
925
|
+
},
|
|
926
|
+
pubKeyCredParams: [
|
|
927
|
+
{ alg: -7, type: "public-key" },
|
|
928
|
+
// ES256 (P-256)
|
|
929
|
+
{ alg: -257, type: "public-key" }
|
|
930
|
+
// RS256
|
|
396
931
|
],
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
abi: ERC20_ABI,
|
|
404
|
-
functionName: "allowance",
|
|
405
|
-
args: [address, permit2Address]
|
|
406
|
-
});
|
|
407
|
-
if (currentAllowance > 0n) {
|
|
408
|
-
return {
|
|
409
|
-
actionId: action.id,
|
|
410
|
-
type: action.type,
|
|
411
|
-
status: "success",
|
|
412
|
-
message: `Permit2 already approved (allowance: ${currentAllowance.toString()}). Skipped.`,
|
|
413
|
-
data: { skipped: true, existingAllowance: currentAllowance.toString() }
|
|
414
|
-
};
|
|
932
|
+
authenticatorSelection: {
|
|
933
|
+
authenticatorAttachment: "platform",
|
|
934
|
+
residentKey: "preferred",
|
|
935
|
+
userVerification: "required"
|
|
936
|
+
},
|
|
937
|
+
timeout: 6e4
|
|
415
938
|
}
|
|
416
|
-
}
|
|
417
|
-
if (!
|
|
939
|
+
});
|
|
940
|
+
if (!credential) {
|
|
418
941
|
return {
|
|
419
942
|
actionId: action.id,
|
|
420
943
|
type: action.type,
|
|
421
944
|
status: "error",
|
|
422
|
-
message: "
|
|
945
|
+
message: "Passkey creation was cancelled."
|
|
423
946
|
};
|
|
424
947
|
}
|
|
425
|
-
const
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
});
|
|
432
|
-
if (publicClient) {
|
|
433
|
-
await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
434
|
-
}
|
|
948
|
+
const response = credential.response;
|
|
949
|
+
const publicKeyBytes = response.getPublicKey?.();
|
|
950
|
+
const credentialId = btoa(
|
|
951
|
+
String.fromCharCode(...new Uint8Array(credential.rawId))
|
|
952
|
+
);
|
|
953
|
+
const publicKey = publicKeyBytes ? btoa(String.fromCharCode(...new Uint8Array(publicKeyBytes))) : "";
|
|
435
954
|
return {
|
|
436
955
|
actionId: action.id,
|
|
437
956
|
type: action.type,
|
|
438
957
|
status: "success",
|
|
439
|
-
message:
|
|
440
|
-
data: {
|
|
958
|
+
message: "Passkey created successfully.",
|
|
959
|
+
data: {
|
|
960
|
+
credentialId,
|
|
961
|
+
publicKey
|
|
962
|
+
}
|
|
441
963
|
};
|
|
442
964
|
} catch (err) {
|
|
443
965
|
return {
|
|
444
966
|
actionId: action.id,
|
|
445
967
|
type: action.type,
|
|
446
968
|
status: "error",
|
|
447
|
-
message: err instanceof Error ? err.message : "Failed to
|
|
969
|
+
message: err instanceof Error ? err.message : "Failed to create passkey"
|
|
448
970
|
};
|
|
449
971
|
}
|
|
450
972
|
},
|
|
451
|
-
[
|
|
973
|
+
[wagmiConfig2]
|
|
452
974
|
);
|
|
453
|
-
const
|
|
975
|
+
const executeUpgradeSmartAccount = useCallback(
|
|
454
976
|
async (action) => {
|
|
455
977
|
try {
|
|
456
|
-
const
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
978
|
+
const account = getAccount(wagmiConfig2);
|
|
979
|
+
const walletClient = await waitForWalletClient(wagmiConfig2);
|
|
980
|
+
const sender = account.address ?? walletClient.account?.address;
|
|
981
|
+
if (!sender) {
|
|
982
|
+
throw new Error("Wallet account not available. Please connect your wallet.");
|
|
983
|
+
}
|
|
984
|
+
if (!isMetaMaskConnector(account)) {
|
|
985
|
+
throw new Error(
|
|
986
|
+
"EIP-7702 smart account upgrade requires a MetaMask-compatible wallet. Please reconnect using MetaMask and try again."
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
const metadata = action.metadata;
|
|
990
|
+
const { txHash, smartAccountAddress } = await submitUpgradeTransaction({
|
|
991
|
+
walletClient,
|
|
992
|
+
sender,
|
|
993
|
+
metadata
|
|
994
|
+
});
|
|
995
|
+
return {
|
|
996
|
+
actionId: action.id,
|
|
997
|
+
type: action.type,
|
|
998
|
+
status: "success",
|
|
999
|
+
message: "Account upgrade transaction submitted.",
|
|
1000
|
+
data: {
|
|
1001
|
+
txHash,
|
|
1002
|
+
smartAccountAddress
|
|
472
1003
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const
|
|
477
|
-
const
|
|
478
|
-
|
|
1004
|
+
};
|
|
1005
|
+
} catch (err) {
|
|
1006
|
+
console.error("Failed to upgrade account", err);
|
|
1007
|
+
const message = extractErrorMessage(err);
|
|
1008
|
+
const isRejected = message.includes("rejected") || message.includes("denied") || message.includes("user rejected");
|
|
1009
|
+
return {
|
|
1010
|
+
actionId: action.id,
|
|
1011
|
+
type: action.type,
|
|
1012
|
+
status: "error",
|
|
1013
|
+
message: isRejected ? "You rejected the upgrade transaction. Please approve the transaction prompt in your wallet to continue." : message
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
},
|
|
1017
|
+
[wagmiConfig2]
|
|
1018
|
+
);
|
|
1019
|
+
const executeGrantPermissions = useCallback(
|
|
1020
|
+
async (action) => {
|
|
1021
|
+
try {
|
|
1022
|
+
const walletClient = await waitForWalletClient(wagmiConfig2);
|
|
1023
|
+
const signingPayload = action.metadata?.signingPayload;
|
|
1024
|
+
const tokens = action.metadata?.tokens;
|
|
1025
|
+
if (!signingPayload) {
|
|
479
1026
|
return {
|
|
480
1027
|
actionId: action.id,
|
|
481
1028
|
type: action.type,
|
|
482
1029
|
status: "error",
|
|
483
|
-
message: "
|
|
1030
|
+
message: "No signing payload in action metadata."
|
|
484
1031
|
};
|
|
485
1032
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
const [existingAmount, existingExpiration] = await publicClient.readContract({
|
|
489
|
-
address: PERMIT2_ADDRESS,
|
|
490
|
-
abi: PERMIT2_ALLOWANCE_ABI,
|
|
491
|
-
functionName: "allowance",
|
|
492
|
-
args: [address, tokenAddress, spenderAddress]
|
|
493
|
-
});
|
|
494
|
-
const requiredSmallestUnit = BigInt(
|
|
495
|
-
Math.ceil(metadataAmount * 1e6)
|
|
496
|
-
);
|
|
497
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
498
|
-
if (existingAmount >= requiredSmallestUnit && existingExpiration > now) {
|
|
499
|
-
return {
|
|
500
|
-
actionId: action.id,
|
|
501
|
-
type: action.type,
|
|
502
|
-
status: "success",
|
|
503
|
-
message: `Permit2 allowance already sufficient (${existingAmount.toString()}). Skipped.`,
|
|
504
|
-
data: { skipped: true, existingAllowance: existingAmount.toString() }
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
} catch {
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
const metadataAllowance = action.metadata?.allowance;
|
|
511
|
-
const permitAmount = metadataAllowance ? BigInt(Math.ceil(metadataAllowance * 1e6)) : metadataAmount ? BigInt(Math.ceil(metadataAmount * 1e6)) : BigInt(5e6);
|
|
512
|
-
const permit2ChainId = metadataChainId ? parseInt(metadataChainId, 16) : currentChainId;
|
|
513
|
-
const nonce = Number(action.metadata?.nonce ?? 0);
|
|
514
|
-
const sigDeadline = BigInt(Math.floor(Date.now() / 1e3) + 3600);
|
|
515
|
-
const expiration = Math.floor(Date.now() / 1e3) + 30 * 24 * 60 * 60;
|
|
516
|
-
const signature = await signTypedDataAsync({
|
|
517
|
-
domain: {
|
|
518
|
-
name: "Permit2",
|
|
519
|
-
chainId: permit2ChainId,
|
|
520
|
-
verifyingContract: PERMIT2_ADDRESS
|
|
521
|
-
},
|
|
522
|
-
types: {
|
|
523
|
-
PermitSingle: [
|
|
524
|
-
{ name: "details", type: "PermitDetails" },
|
|
525
|
-
{ name: "spender", type: "address" },
|
|
526
|
-
{ name: "sigDeadline", type: "uint256" }
|
|
527
|
-
],
|
|
528
|
-
PermitDetails: [
|
|
529
|
-
{ name: "token", type: "address" },
|
|
530
|
-
{ name: "amount", type: "uint160" },
|
|
531
|
-
{ name: "expiration", type: "uint48" },
|
|
532
|
-
{ name: "nonce", type: "uint48" }
|
|
533
|
-
]
|
|
534
|
-
},
|
|
535
|
-
primaryType: "PermitSingle",
|
|
536
|
-
message: {
|
|
537
|
-
details: {
|
|
538
|
-
token: tokenAddress,
|
|
539
|
-
amount: permitAmount,
|
|
540
|
-
expiration,
|
|
541
|
-
nonce
|
|
542
|
-
},
|
|
543
|
-
spender: spenderAddress,
|
|
544
|
-
sigDeadline
|
|
545
|
-
}
|
|
1033
|
+
const signature = await walletClient.signMessage({
|
|
1034
|
+
message: JSON.stringify(signingPayload)
|
|
546
1035
|
});
|
|
1036
|
+
const tokenSummary = tokens?.map((t) => `${t.symbol} on ${t.chainName}`).join(", ") ?? "all tokens";
|
|
547
1037
|
return {
|
|
548
1038
|
actionId: action.id,
|
|
549
1039
|
type: action.type,
|
|
550
1040
|
status: "success",
|
|
551
|
-
message:
|
|
1041
|
+
message: `Permissions granted for ${tokenSummary}.`,
|
|
552
1042
|
data: {
|
|
553
|
-
signature,
|
|
554
|
-
|
|
555
|
-
nonce: nonce.toString(),
|
|
556
|
-
sigDeadline: sigDeadline.toString(),
|
|
557
|
-
expiration: expiration.toString(),
|
|
558
|
-
amount: permitAmount.toString()
|
|
1043
|
+
signedDelegation: signature,
|
|
1044
|
+
tokens
|
|
559
1045
|
}
|
|
560
1046
|
};
|
|
561
1047
|
} catch (err) {
|
|
@@ -563,23 +1049,28 @@ function useAuthorizationExecutor() {
|
|
|
563
1049
|
actionId: action.id,
|
|
564
1050
|
type: action.type,
|
|
565
1051
|
status: "error",
|
|
566
|
-
message: err instanceof Error ? err.message : "Failed to
|
|
1052
|
+
message: err instanceof Error ? err.message : "Failed to grant permissions"
|
|
567
1053
|
};
|
|
568
1054
|
}
|
|
569
1055
|
},
|
|
570
|
-
[
|
|
1056
|
+
[wagmiConfig2]
|
|
571
1057
|
);
|
|
572
1058
|
const executeAction = useCallback(
|
|
573
1059
|
async (action) => {
|
|
1060
|
+
setCurrentAction(action);
|
|
574
1061
|
switch (action.type) {
|
|
575
1062
|
case "OPEN_PROVIDER":
|
|
576
1063
|
return executeOpenProvider(action);
|
|
1064
|
+
case "SELECT_SOURCE":
|
|
1065
|
+
return executeSelectSource(action);
|
|
577
1066
|
case "SWITCH_CHAIN":
|
|
578
1067
|
return executeSwitchChain(action);
|
|
579
|
-
case "
|
|
580
|
-
return
|
|
581
|
-
case "
|
|
582
|
-
return
|
|
1068
|
+
case "REGISTER_PASSKEY":
|
|
1069
|
+
return executeRegisterPasskey(action);
|
|
1070
|
+
case "UPGRADE_SMART_ACCOUNT":
|
|
1071
|
+
return executeUpgradeSmartAccount(action);
|
|
1072
|
+
case "GRANT_PERMISSIONS":
|
|
1073
|
+
return executeGrantPermissions(action);
|
|
583
1074
|
default:
|
|
584
1075
|
return {
|
|
585
1076
|
actionId: action.id,
|
|
@@ -589,18 +1080,18 @@ function useAuthorizationExecutor() {
|
|
|
589
1080
|
};
|
|
590
1081
|
}
|
|
591
1082
|
},
|
|
592
|
-
[executeOpenProvider, executeSwitchChain,
|
|
1083
|
+
[executeOpenProvider, executeSelectSource, executeSwitchChain, executeRegisterPasskey, executeUpgradeSmartAccount, executeGrantPermissions]
|
|
593
1084
|
);
|
|
594
1085
|
const executeSession = useCallback(
|
|
595
1086
|
async (transfer) => {
|
|
596
1087
|
if (executingRef.current) return;
|
|
597
1088
|
executingRef.current = true;
|
|
598
1089
|
if (!transfer.authorizationSessions || transfer.authorizationSessions.length === 0) {
|
|
599
|
-
setError("No authorization sessions available.");
|
|
600
1090
|
executingRef.current = false;
|
|
601
|
-
|
|
1091
|
+
throw new Error("No authorization sessions available.");
|
|
602
1092
|
}
|
|
603
1093
|
const sessionId = transfer.authorizationSessions[0].id;
|
|
1094
|
+
sessionIdRef.current = sessionId;
|
|
604
1095
|
setExecuting(true);
|
|
605
1096
|
setError(null);
|
|
606
1097
|
setResults([]);
|
|
@@ -609,6 +1100,18 @@ function useAuthorizationExecutor() {
|
|
|
609
1100
|
const allResults = [];
|
|
610
1101
|
const completedActionIds = /* @__PURE__ */ new Set();
|
|
611
1102
|
let pendingActions = currentSession.actions.filter((a) => a.status === "PENDING").sort((a, b) => a.orderIndex - b.orderIndex);
|
|
1103
|
+
const ACTION_POLL_INTERVAL_MS = 500;
|
|
1104
|
+
const ACTION_POLL_MAX_RETRIES = 20;
|
|
1105
|
+
let actionPollRetries = 0;
|
|
1106
|
+
while (pendingActions.length === 0 && currentSession.status !== "AUTHORIZED" && actionPollRetries < ACTION_POLL_MAX_RETRIES) {
|
|
1107
|
+
await new Promise((r) => setTimeout(r, ACTION_POLL_INTERVAL_MS));
|
|
1108
|
+
currentSession = await fetchAuthorizationSession(apiBaseUrl, sessionId);
|
|
1109
|
+
pendingActions = currentSession.actions.filter((a) => a.status === "PENDING").sort((a, b) => a.orderIndex - b.orderIndex);
|
|
1110
|
+
actionPollRetries++;
|
|
1111
|
+
}
|
|
1112
|
+
if (pendingActions.length === 0 && currentSession.status !== "AUTHORIZED") {
|
|
1113
|
+
throw new Error("Authorization actions were not created in time. Please try again.");
|
|
1114
|
+
}
|
|
612
1115
|
while (pendingActions.length > 0) {
|
|
613
1116
|
const action = pendingActions[0];
|
|
614
1117
|
if (completedActionIds.has(action.id)) break;
|
|
@@ -616,8 +1119,7 @@ function useAuthorizationExecutor() {
|
|
|
616
1119
|
if (result.status === "error") {
|
|
617
1120
|
allResults.push(result);
|
|
618
1121
|
setResults([...allResults]);
|
|
619
|
-
|
|
620
|
-
break;
|
|
1122
|
+
throw new Error(result.message);
|
|
621
1123
|
}
|
|
622
1124
|
completedActionIds.add(action.id);
|
|
623
1125
|
const updatedSession = await reportActionCompletion(
|
|
@@ -629,7 +1131,6 @@ function useAuthorizationExecutor() {
|
|
|
629
1131
|
pendingActions = currentSession.actions.filter((a) => a.status === "PENDING" && !completedActionIds.has(a.id)).sort((a, b) => a.orderIndex - b.orderIndex);
|
|
630
1132
|
if (action.type === "OPEN_PROVIDER" && pendingActions.length > 0) {
|
|
631
1133
|
const chainResults = [result];
|
|
632
|
-
let chainBroken = false;
|
|
633
1134
|
while (pendingActions.length > 0) {
|
|
634
1135
|
const nextAction = pendingActions[0];
|
|
635
1136
|
const nextResult = await executeAction(nextAction);
|
|
@@ -637,9 +1138,7 @@ function useAuthorizationExecutor() {
|
|
|
637
1138
|
chainResults.push(nextResult);
|
|
638
1139
|
allResults.push(...chainResults);
|
|
639
1140
|
setResults([...allResults]);
|
|
640
|
-
|
|
641
|
-
chainBroken = true;
|
|
642
|
-
break;
|
|
1141
|
+
throw new Error(nextResult.message);
|
|
643
1142
|
}
|
|
644
1143
|
completedActionIds.add(nextAction.id);
|
|
645
1144
|
const nextSession = await reportActionCompletion(
|
|
@@ -651,7 +1150,6 @@ function useAuthorizationExecutor() {
|
|
|
651
1150
|
chainResults.push(nextResult);
|
|
652
1151
|
pendingActions = currentSession.actions.filter((a) => a.status === "PENDING" && !completedActionIds.has(a.id)).sort((a, b) => a.orderIndex - b.orderIndex);
|
|
653
1152
|
}
|
|
654
|
-
if (chainBroken) break;
|
|
655
1153
|
allResults.push(...chainResults);
|
|
656
1154
|
setResults([...allResults]);
|
|
657
1155
|
continue;
|
|
@@ -660,15 +1158,113 @@ function useAuthorizationExecutor() {
|
|
|
660
1158
|
setResults([...allResults]);
|
|
661
1159
|
}
|
|
662
1160
|
} catch (err) {
|
|
663
|
-
|
|
1161
|
+
const msg = err instanceof Error ? err.message : "Authorization failed";
|
|
1162
|
+
setError(msg);
|
|
1163
|
+
throw err;
|
|
664
1164
|
} finally {
|
|
1165
|
+
setCurrentAction(null);
|
|
665
1166
|
setExecuting(false);
|
|
666
1167
|
executingRef.current = false;
|
|
667
1168
|
}
|
|
668
1169
|
},
|
|
669
1170
|
[apiBaseUrl, executeAction]
|
|
670
1171
|
);
|
|
671
|
-
return {
|
|
1172
|
+
return {
|
|
1173
|
+
executing,
|
|
1174
|
+
results,
|
|
1175
|
+
error,
|
|
1176
|
+
currentAction,
|
|
1177
|
+
pendingSelectSource,
|
|
1178
|
+
resolveSelectSource,
|
|
1179
|
+
executeSession
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
function useTransferSigning(pollIntervalMs = 2e3) {
|
|
1183
|
+
const { apiBaseUrl } = useSwypeConfig();
|
|
1184
|
+
const { getAccessToken } = usePrivy();
|
|
1185
|
+
const [signing, setSigning] = useState(false);
|
|
1186
|
+
const [signPayload, setSignPayload] = useState(null);
|
|
1187
|
+
const [error, setError] = useState(null);
|
|
1188
|
+
const signTransfer2 = useCallback(
|
|
1189
|
+
async (transferId) => {
|
|
1190
|
+
setSigning(true);
|
|
1191
|
+
setError(null);
|
|
1192
|
+
setSignPayload(null);
|
|
1193
|
+
try {
|
|
1194
|
+
const token = await getAccessToken();
|
|
1195
|
+
if (!token) {
|
|
1196
|
+
throw new Error("Could not get access token");
|
|
1197
|
+
}
|
|
1198
|
+
const MAX_POLLS = 60;
|
|
1199
|
+
let payload = null;
|
|
1200
|
+
for (let i = 0; i < MAX_POLLS; i++) {
|
|
1201
|
+
const transfer = await fetchTransfer(apiBaseUrl, token, transferId);
|
|
1202
|
+
if (transfer.signPayload) {
|
|
1203
|
+
payload = transfer.signPayload;
|
|
1204
|
+
setSignPayload(payload);
|
|
1205
|
+
break;
|
|
1206
|
+
}
|
|
1207
|
+
if (transfer.status !== "AUTHORIZED" && transfer.status !== "CREATED") {
|
|
1208
|
+
throw new Error(`Unexpected transfer status: ${transfer.status}`);
|
|
1209
|
+
}
|
|
1210
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
1211
|
+
}
|
|
1212
|
+
if (!payload) {
|
|
1213
|
+
throw new Error("Timed out waiting for sign payload. Please try again.");
|
|
1214
|
+
}
|
|
1215
|
+
const userOpHashHex = payload.userOpHash;
|
|
1216
|
+
const hashBytes = new Uint8Array(
|
|
1217
|
+
(userOpHashHex.startsWith("0x") ? userOpHashHex.slice(2) : userOpHashHex).match(/.{1,2}/g).map((byte) => parseInt(byte, 16))
|
|
1218
|
+
);
|
|
1219
|
+
const assertion = await navigator.credentials.get({
|
|
1220
|
+
publicKey: {
|
|
1221
|
+
challenge: hashBytes,
|
|
1222
|
+
rpId: window.location.hostname,
|
|
1223
|
+
userVerification: "required",
|
|
1224
|
+
timeout: 6e4
|
|
1225
|
+
}
|
|
1226
|
+
});
|
|
1227
|
+
if (!assertion) {
|
|
1228
|
+
throw new Error("Passkey authentication was cancelled.");
|
|
1229
|
+
}
|
|
1230
|
+
const response = assertion.response;
|
|
1231
|
+
const signature = btoa(
|
|
1232
|
+
String.fromCharCode(...new Uint8Array(response.signature))
|
|
1233
|
+
);
|
|
1234
|
+
const authenticatorData = btoa(
|
|
1235
|
+
String.fromCharCode(
|
|
1236
|
+
...new Uint8Array(response.authenticatorData)
|
|
1237
|
+
)
|
|
1238
|
+
);
|
|
1239
|
+
const clientDataJSON = btoa(
|
|
1240
|
+
String.fromCharCode(
|
|
1241
|
+
...new Uint8Array(response.clientDataJSON)
|
|
1242
|
+
)
|
|
1243
|
+
);
|
|
1244
|
+
const signedUserOp = {
|
|
1245
|
+
...payload.userOp,
|
|
1246
|
+
signature,
|
|
1247
|
+
authenticatorData,
|
|
1248
|
+
clientDataJSON
|
|
1249
|
+
};
|
|
1250
|
+
const updatedTransfer = await signTransfer(
|
|
1251
|
+
apiBaseUrl,
|
|
1252
|
+
token,
|
|
1253
|
+
transferId,
|
|
1254
|
+
signedUserOp
|
|
1255
|
+
);
|
|
1256
|
+
return updatedTransfer;
|
|
1257
|
+
} catch (err) {
|
|
1258
|
+
const msg = err instanceof Error ? err.message : "Failed to sign transfer";
|
|
1259
|
+
setError(msg);
|
|
1260
|
+
throw err;
|
|
1261
|
+
} finally {
|
|
1262
|
+
setSigning(false);
|
|
1263
|
+
}
|
|
1264
|
+
},
|
|
1265
|
+
[apiBaseUrl, getAccessToken, pollIntervalMs]
|
|
1266
|
+
);
|
|
1267
|
+
return { signing, signPayload, error, signTransfer: signTransfer2 };
|
|
672
1268
|
}
|
|
673
1269
|
function Spinner({ size = 40, label }) {
|
|
674
1270
|
const { tokens } = useSwypeConfig();
|
|
@@ -786,163 +1382,232 @@ function ProviderCard({ provider, selected, onClick }) {
|
|
|
786
1382
|
}
|
|
787
1383
|
);
|
|
788
1384
|
}
|
|
789
|
-
function
|
|
1385
|
+
function AccountDropdown({
|
|
790
1386
|
accounts,
|
|
791
|
-
|
|
792
|
-
onSelect
|
|
1387
|
+
selectedAccountId,
|
|
1388
|
+
onSelect,
|
|
1389
|
+
selectedWalletId,
|
|
1390
|
+
onWalletSelect
|
|
793
1391
|
}) {
|
|
794
1392
|
const { tokens } = useSwypeConfig();
|
|
795
|
-
const [
|
|
796
|
-
const
|
|
797
|
-
|
|
1393
|
+
const [open, setOpen] = useState(false);
|
|
1394
|
+
const containerRef = useRef(null);
|
|
1395
|
+
const selected = accounts.find((a) => a.id === selectedAccountId);
|
|
1396
|
+
const selectedWallet = selected?.wallets.find(
|
|
1397
|
+
(w) => w.id === selectedWalletId
|
|
798
1398
|
);
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
setExpandedAccountId(accountId);
|
|
805
|
-
}
|
|
806
|
-
};
|
|
807
|
-
const handleWalletClick = (account, wallet) => {
|
|
808
|
-
const isAlreadySelected = selection?.accountId === account.id && selection?.walletId === wallet.id;
|
|
809
|
-
if (isAlreadySelected) {
|
|
810
|
-
onSelect(null);
|
|
811
|
-
} else {
|
|
812
|
-
onSelect({
|
|
813
|
-
accountId: account.id,
|
|
814
|
-
walletId: wallet.id,
|
|
815
|
-
accountName: account.name,
|
|
816
|
-
walletName: wallet.name,
|
|
817
|
-
chainName: wallet.chain.name
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
const formatBalance = (wallet) => {
|
|
822
|
-
const parts = [];
|
|
823
|
-
for (const src of wallet.sources) {
|
|
824
|
-
if (src.token.status === "ACTIVE") {
|
|
825
|
-
parts.push(
|
|
826
|
-
`${src.balance.available.amount.toFixed(2)} ${src.balance.available.currency} (${src.token.symbol})`
|
|
827
|
-
);
|
|
1399
|
+
useEffect(() => {
|
|
1400
|
+
if (!open) return;
|
|
1401
|
+
const handleClick = (e) => {
|
|
1402
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
1403
|
+
setOpen(false);
|
|
828
1404
|
}
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
/* @__PURE__ */
|
|
837
|
-
"
|
|
1405
|
+
};
|
|
1406
|
+
document.addEventListener("mousedown", handleClick);
|
|
1407
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
1408
|
+
}, [open]);
|
|
1409
|
+
if (accounts.length === 0) return null;
|
|
1410
|
+
const hasMultipleChoices = accounts.length > 1 || accounts.length === 1 && onWalletSelect && accounts[0].wallets.filter((w) => w.balance.available.amount > 0).length > 1;
|
|
1411
|
+
if (!hasMultipleChoices) {
|
|
1412
|
+
return /* @__PURE__ */ jsxs(
|
|
1413
|
+
"div",
|
|
838
1414
|
{
|
|
839
1415
|
style: {
|
|
840
|
-
display: "
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
textTransform: "uppercase",
|
|
846
|
-
letterSpacing: "0.05em"
|
|
1416
|
+
display: "flex",
|
|
1417
|
+
alignItems: "center",
|
|
1418
|
+
gap: "6px",
|
|
1419
|
+
fontSize: "0.85rem",
|
|
1420
|
+
color: tokens.textSecondary
|
|
847
1421
|
},
|
|
848
|
-
children:
|
|
1422
|
+
children: [
|
|
1423
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: accounts[0].name }),
|
|
1424
|
+
(selectedWallet ?? accounts[0].wallets[0]) && /* @__PURE__ */ jsx(
|
|
1425
|
+
"span",
|
|
1426
|
+
{
|
|
1427
|
+
style: {
|
|
1428
|
+
fontSize: "0.75rem",
|
|
1429
|
+
color: tokens.textMuted,
|
|
1430
|
+
fontFamily: '"SF Mono", "Fira Code", monospace'
|
|
1431
|
+
},
|
|
1432
|
+
children: selectedWallet ? `${selectedWallet.chain.name} \xB7 ${selectedWallet.name}` : accounts[0].wallets[0]?.name
|
|
1433
|
+
}
|
|
1434
|
+
)
|
|
1435
|
+
]
|
|
849
1436
|
}
|
|
850
|
-
)
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1439
|
+
const getAccountBalance = (account) => {
|
|
1440
|
+
let total = 0;
|
|
1441
|
+
for (const w of account.wallets) {
|
|
1442
|
+
total += w.balance.available.amount;
|
|
1443
|
+
}
|
|
1444
|
+
return total > 0 ? `$${total.toFixed(2)}` : "";
|
|
1445
|
+
};
|
|
1446
|
+
const hasActiveWallet = (account) => account.wallets.some((w) => w.status === "ACTIVE");
|
|
1447
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, style: { position: "relative" }, children: [
|
|
1448
|
+
/* @__PURE__ */ jsxs(
|
|
1449
|
+
"button",
|
|
1450
|
+
{
|
|
1451
|
+
onClick: () => setOpen(!open),
|
|
1452
|
+
style: {
|
|
1453
|
+
display: "flex",
|
|
1454
|
+
alignItems: "center",
|
|
1455
|
+
gap: "6px",
|
|
1456
|
+
background: "transparent",
|
|
1457
|
+
border: "none",
|
|
1458
|
+
cursor: "pointer",
|
|
1459
|
+
padding: "4px 0",
|
|
1460
|
+
color: tokens.textSecondary,
|
|
1461
|
+
fontFamily: "inherit",
|
|
1462
|
+
fontSize: "0.85rem",
|
|
1463
|
+
outline: "none"
|
|
1464
|
+
},
|
|
1465
|
+
children: [
|
|
1466
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500, color: tokens.text }, children: selected?.name ?? "Select account" }),
|
|
1467
|
+
(selectedWallet ?? selected?.wallets?.[0]) && /* @__PURE__ */ jsx(
|
|
1468
|
+
"span",
|
|
1469
|
+
{
|
|
1470
|
+
style: {
|
|
1471
|
+
fontSize: "0.75rem",
|
|
1472
|
+
color: tokens.textMuted,
|
|
1473
|
+
fontFamily: '"SF Mono", "Fira Code", monospace'
|
|
1474
|
+
},
|
|
1475
|
+
children: selectedWallet ? `${selectedWallet.chain.name} \xB7 ${selectedWallet.name}` : selected.wallets[0].name
|
|
1476
|
+
}
|
|
1477
|
+
),
|
|
1478
|
+
/* @__PURE__ */ jsx(
|
|
1479
|
+
"svg",
|
|
1480
|
+
{
|
|
1481
|
+
width: "12",
|
|
1482
|
+
height: "12",
|
|
1483
|
+
viewBox: "0 0 24 24",
|
|
1484
|
+
fill: "none",
|
|
1485
|
+
style: {
|
|
1486
|
+
transform: open ? "rotate(180deg)" : "rotate(0deg)",
|
|
1487
|
+
transition: "transform 0.15s ease",
|
|
1488
|
+
flexShrink: 0
|
|
1489
|
+
},
|
|
1490
|
+
children: /* @__PURE__ */ jsx(
|
|
1491
|
+
"path",
|
|
1492
|
+
{
|
|
1493
|
+
d: "M7 10l5 5 5-5",
|
|
1494
|
+
stroke: tokens.textMuted,
|
|
1495
|
+
strokeWidth: "2",
|
|
1496
|
+
strokeLinecap: "round",
|
|
1497
|
+
strokeLinejoin: "round"
|
|
1498
|
+
}
|
|
1499
|
+
)
|
|
1500
|
+
}
|
|
1501
|
+
)
|
|
1502
|
+
]
|
|
1503
|
+
}
|
|
1504
|
+
),
|
|
1505
|
+
open && /* @__PURE__ */ jsx(
|
|
1506
|
+
"div",
|
|
1507
|
+
{
|
|
1508
|
+
style: {
|
|
1509
|
+
position: "absolute",
|
|
1510
|
+
top: "100%",
|
|
1511
|
+
left: 0,
|
|
1512
|
+
right: 0,
|
|
1513
|
+
marginTop: "4px",
|
|
1514
|
+
background: tokens.bgCard,
|
|
1515
|
+
border: `1px solid ${tokens.border}`,
|
|
1516
|
+
borderRadius: tokens.radius,
|
|
1517
|
+
boxShadow: tokens.shadowLg,
|
|
1518
|
+
zIndex: 50,
|
|
1519
|
+
overflow: "hidden",
|
|
1520
|
+
minWidth: "220px"
|
|
1521
|
+
},
|
|
1522
|
+
children: accounts.map((account) => {
|
|
1523
|
+
const isAcctSelected = account.id === selectedAccountId;
|
|
1524
|
+
const balance = getAccountBalance(account);
|
|
1525
|
+
const active = hasActiveWallet(account);
|
|
1526
|
+
const walletsWithBalance = account.wallets.filter(
|
|
1527
|
+
(w) => w.balance.available.amount > 0
|
|
1528
|
+
);
|
|
1529
|
+
const showWallets = onWalletSelect && walletsWithBalance.length > 0;
|
|
1530
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
865
1531
|
/* @__PURE__ */ jsxs(
|
|
866
1532
|
"button",
|
|
867
1533
|
{
|
|
868
|
-
onClick: () =>
|
|
1534
|
+
onClick: () => {
|
|
1535
|
+
onSelect(account.id);
|
|
1536
|
+
if (!showWallets) setOpen(false);
|
|
1537
|
+
},
|
|
869
1538
|
style: {
|
|
870
|
-
width: "100%",
|
|
871
1539
|
display: "flex",
|
|
872
1540
|
alignItems: "center",
|
|
873
1541
|
justifyContent: "space-between",
|
|
874
|
-
|
|
875
|
-
|
|
1542
|
+
width: "100%",
|
|
1543
|
+
padding: "10px 14px",
|
|
1544
|
+
background: isAcctSelected && !selectedWalletId ? tokens.accent + "12" : "transparent",
|
|
876
1545
|
border: "none",
|
|
1546
|
+
borderBottom: showWallets ? "none" : `1px solid ${tokens.border}`,
|
|
877
1547
|
cursor: "pointer",
|
|
878
1548
|
color: tokens.text,
|
|
879
1549
|
fontFamily: "inherit",
|
|
880
|
-
fontSize: "0.
|
|
881
|
-
fontWeight: 500,
|
|
1550
|
+
fontSize: "0.85rem",
|
|
882
1551
|
textAlign: "left",
|
|
883
1552
|
outline: "none",
|
|
884
|
-
transition: "background 0.
|
|
1553
|
+
transition: "background 0.1s ease"
|
|
885
1554
|
},
|
|
886
1555
|
children: [
|
|
887
|
-
/* @__PURE__ */ jsxs("div", { style: {
|
|
888
|
-
/* @__PURE__ */
|
|
1556
|
+
/* @__PURE__ */ jsxs("div", { style: { minWidth: 0, flex: 1 }, children: [
|
|
1557
|
+
/* @__PURE__ */ jsxs(
|
|
889
1558
|
"div",
|
|
890
1559
|
{
|
|
891
1560
|
style: {
|
|
892
|
-
width: 28,
|
|
893
|
-
height: 28,
|
|
894
|
-
borderRadius: "6px",
|
|
895
|
-
background: tokens.accent + "25",
|
|
896
1561
|
display: "flex",
|
|
897
1562
|
alignItems: "center",
|
|
898
|
-
|
|
899
|
-
fontSize: "0.75rem",
|
|
900
|
-
fontWeight: 700,
|
|
901
|
-
color: tokens.accent,
|
|
902
|
-
flexShrink: 0
|
|
1563
|
+
gap: "6px"
|
|
903
1564
|
},
|
|
904
|
-
children:
|
|
1565
|
+
children: [
|
|
1566
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: account.name }),
|
|
1567
|
+
active && /* @__PURE__ */ jsx(
|
|
1568
|
+
"span",
|
|
1569
|
+
{
|
|
1570
|
+
style: {
|
|
1571
|
+
fontSize: "0.6rem",
|
|
1572
|
+
fontWeight: 600,
|
|
1573
|
+
color: tokens.success,
|
|
1574
|
+
background: tokens.successBg,
|
|
1575
|
+
padding: "1px 5px",
|
|
1576
|
+
borderRadius: "3px",
|
|
1577
|
+
textTransform: "uppercase",
|
|
1578
|
+
letterSpacing: "0.03em"
|
|
1579
|
+
},
|
|
1580
|
+
children: "Active"
|
|
1581
|
+
}
|
|
1582
|
+
)
|
|
1583
|
+
]
|
|
905
1584
|
}
|
|
906
1585
|
),
|
|
907
|
-
/* @__PURE__ */
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
activeWallets.length,
|
|
919
|
-
" wallet",
|
|
920
|
-
activeWallets.length !== 1 ? "s" : ""
|
|
921
|
-
]
|
|
922
|
-
}
|
|
923
|
-
)
|
|
924
|
-
] })
|
|
1586
|
+
balance && /* @__PURE__ */ jsx(
|
|
1587
|
+
"div",
|
|
1588
|
+
{
|
|
1589
|
+
style: {
|
|
1590
|
+
fontSize: "0.75rem",
|
|
1591
|
+
color: tokens.textMuted,
|
|
1592
|
+
marginTop: "2px"
|
|
1593
|
+
},
|
|
1594
|
+
children: balance
|
|
1595
|
+
}
|
|
1596
|
+
)
|
|
925
1597
|
] }),
|
|
926
|
-
/* @__PURE__ */ jsx(
|
|
1598
|
+
isAcctSelected && !selectedWalletId && /* @__PURE__ */ jsx(
|
|
927
1599
|
"svg",
|
|
928
1600
|
{
|
|
929
1601
|
width: "14",
|
|
930
1602
|
height: "14",
|
|
931
1603
|
viewBox: "0 0 24 24",
|
|
932
1604
|
fill: "none",
|
|
933
|
-
style: {
|
|
934
|
-
transform: isExpanded ? "rotate(180deg)" : "rotate(0deg)",
|
|
935
|
-
transition: "transform 0.2s ease",
|
|
936
|
-
flexShrink: 0
|
|
937
|
-
},
|
|
1605
|
+
style: { flexShrink: 0, marginLeft: "8px" },
|
|
938
1606
|
children: /* @__PURE__ */ jsx(
|
|
939
1607
|
"path",
|
|
940
1608
|
{
|
|
941
|
-
d: "
|
|
942
|
-
|
|
943
|
-
strokeWidth: "2",
|
|
944
|
-
strokeLinecap: "round",
|
|
945
|
-
strokeLinejoin: "round"
|
|
1609
|
+
d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
|
|
1610
|
+
fill: tokens.accent
|
|
946
1611
|
}
|
|
947
1612
|
)
|
|
948
1613
|
}
|
|
@@ -950,128 +1615,383 @@ function AccountWalletSelector({
|
|
|
950
1615
|
]
|
|
951
1616
|
}
|
|
952
1617
|
),
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
{
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1618
|
+
showWallets && walletsWithBalance.map((wallet, wIdx) => {
|
|
1619
|
+
const isWalletSelected = isAcctSelected && wallet.id === selectedWalletId;
|
|
1620
|
+
const walletBal = wallet.balance.available.amount > 0 ? `$${wallet.balance.available.amount.toFixed(2)}` : "";
|
|
1621
|
+
const isLastWallet = wIdx === walletsWithBalance.length - 1;
|
|
1622
|
+
return /* @__PURE__ */ jsxs(
|
|
1623
|
+
"button",
|
|
1624
|
+
{
|
|
1625
|
+
onClick: () => {
|
|
1626
|
+
onWalletSelect(account.id, wallet.id);
|
|
1627
|
+
setOpen(false);
|
|
1628
|
+
},
|
|
1629
|
+
style: {
|
|
1630
|
+
display: "flex",
|
|
1631
|
+
alignItems: "center",
|
|
1632
|
+
justifyContent: "space-between",
|
|
1633
|
+
width: "100%",
|
|
1634
|
+
padding: "8px 14px 8px 28px",
|
|
1635
|
+
background: isWalletSelected ? tokens.accent + "12" : "transparent",
|
|
1636
|
+
border: "none",
|
|
1637
|
+
borderBottom: isLastWallet ? `1px solid ${tokens.border}` : "none",
|
|
1638
|
+
cursor: "pointer",
|
|
1639
|
+
color: tokens.text,
|
|
1640
|
+
fontFamily: "inherit",
|
|
1641
|
+
fontSize: "0.8rem",
|
|
1642
|
+
textAlign: "left",
|
|
1643
|
+
outline: "none",
|
|
1644
|
+
transition: "background 0.1s ease"
|
|
1645
|
+
},
|
|
1646
|
+
children: [
|
|
1647
|
+
/* @__PURE__ */ jsxs(
|
|
1648
|
+
"div",
|
|
1649
|
+
{
|
|
1650
|
+
style: {
|
|
1651
|
+
display: "flex",
|
|
1652
|
+
alignItems: "center",
|
|
1653
|
+
gap: "6px",
|
|
1654
|
+
minWidth: 0,
|
|
1655
|
+
flex: 1
|
|
1656
|
+
},
|
|
1657
|
+
children: [
|
|
1658
|
+
/* @__PURE__ */ jsx(
|
|
1659
|
+
"span",
|
|
987
1660
|
{
|
|
988
1661
|
style: {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
gap: "6px"
|
|
1662
|
+
fontWeight: 500,
|
|
1663
|
+
fontSize: "0.8rem"
|
|
992
1664
|
},
|
|
993
|
-
children:
|
|
994
|
-
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: wallet.name }),
|
|
995
|
-
/* @__PURE__ */ jsx(
|
|
996
|
-
"span",
|
|
997
|
-
{
|
|
998
|
-
style: {
|
|
999
|
-
fontSize: "0.7rem",
|
|
1000
|
-
color: tokens.textMuted,
|
|
1001
|
-
background: tokens.bgHover,
|
|
1002
|
-
padding: "1px 6px",
|
|
1003
|
-
borderRadius: "4px"
|
|
1004
|
-
},
|
|
1005
|
-
children: wallet.chain.name
|
|
1006
|
-
}
|
|
1007
|
-
)
|
|
1008
|
-
]
|
|
1665
|
+
children: wallet.chain.name
|
|
1009
1666
|
}
|
|
1010
1667
|
),
|
|
1011
1668
|
/* @__PURE__ */ jsx(
|
|
1012
|
-
"
|
|
1669
|
+
"span",
|
|
1670
|
+
{
|
|
1671
|
+
style: {
|
|
1672
|
+
fontSize: "0.7rem",
|
|
1673
|
+
color: tokens.textMuted,
|
|
1674
|
+
fontFamily: '"SF Mono", "Fira Code", monospace'
|
|
1675
|
+
},
|
|
1676
|
+
children: wallet.name
|
|
1677
|
+
}
|
|
1678
|
+
),
|
|
1679
|
+
walletBal && /* @__PURE__ */ jsx(
|
|
1680
|
+
"span",
|
|
1013
1681
|
{
|
|
1014
1682
|
style: {
|
|
1015
|
-
fontSize: "0.
|
|
1016
|
-
color: tokens.
|
|
1017
|
-
|
|
1683
|
+
fontSize: "0.7rem",
|
|
1684
|
+
color: tokens.textMuted,
|
|
1685
|
+
marginLeft: "auto"
|
|
1018
1686
|
},
|
|
1019
|
-
children:
|
|
1687
|
+
children: walletBal
|
|
1020
1688
|
}
|
|
1021
1689
|
)
|
|
1022
|
-
]
|
|
1023
|
-
|
|
1024
|
-
|
|
1690
|
+
]
|
|
1691
|
+
}
|
|
1692
|
+
),
|
|
1693
|
+
isWalletSelected && /* @__PURE__ */ jsx(
|
|
1694
|
+
"svg",
|
|
1695
|
+
{
|
|
1696
|
+
width: "12",
|
|
1697
|
+
height: "12",
|
|
1698
|
+
viewBox: "0 0 24 24",
|
|
1699
|
+
fill: "none",
|
|
1700
|
+
style: {
|
|
1701
|
+
flexShrink: 0,
|
|
1702
|
+
marginLeft: "8px"
|
|
1703
|
+
},
|
|
1704
|
+
children: /* @__PURE__ */ jsx(
|
|
1705
|
+
"path",
|
|
1025
1706
|
{
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
viewBox: "0 0 24 24",
|
|
1029
|
-
fill: "none",
|
|
1030
|
-
style: { flexShrink: 0, marginLeft: "8px" },
|
|
1031
|
-
children: /* @__PURE__ */ jsx(
|
|
1032
|
-
"path",
|
|
1033
|
-
{
|
|
1034
|
-
d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
|
|
1035
|
-
fill: tokens.accent
|
|
1036
|
-
}
|
|
1037
|
-
)
|
|
1707
|
+
d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
|
|
1708
|
+
fill: tokens.accent
|
|
1038
1709
|
}
|
|
1039
1710
|
)
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
)
|
|
1047
|
-
]
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1711
|
+
}
|
|
1712
|
+
)
|
|
1713
|
+
]
|
|
1714
|
+
},
|
|
1715
|
+
wallet.id
|
|
1716
|
+
);
|
|
1717
|
+
})
|
|
1718
|
+
] }, account.id);
|
|
1719
|
+
})
|
|
1720
|
+
}
|
|
1721
|
+
)
|
|
1722
|
+
] });
|
|
1723
|
+
}
|
|
1724
|
+
var ASSETS = ["USDC", "USDT"];
|
|
1725
|
+
function AdvancedSettings({
|
|
1726
|
+
settings,
|
|
1727
|
+
onChange,
|
|
1728
|
+
chains,
|
|
1729
|
+
providers,
|
|
1730
|
+
onConnectNewAccount,
|
|
1731
|
+
connectingNewAccount
|
|
1732
|
+
}) {
|
|
1733
|
+
const { tokens } = useSwypeConfig();
|
|
1734
|
+
const [open, setOpen] = useState(false);
|
|
1735
|
+
const [showProviders, setShowProviders] = useState(false);
|
|
1736
|
+
return /* @__PURE__ */ jsxs("div", { style: { marginTop: "12px" }, children: [
|
|
1737
|
+
/* @__PURE__ */ jsxs(
|
|
1738
|
+
"button",
|
|
1054
1739
|
{
|
|
1740
|
+
onClick: () => setOpen(!open),
|
|
1055
1741
|
style: {
|
|
1056
|
-
marginTop: "8px",
|
|
1057
|
-
fontSize: "0.8rem",
|
|
1058
|
-
color: tokens.accent,
|
|
1059
1742
|
display: "flex",
|
|
1060
1743
|
alignItems: "center",
|
|
1061
|
-
gap: "6px"
|
|
1744
|
+
gap: "6px",
|
|
1745
|
+
background: "transparent",
|
|
1746
|
+
border: "none",
|
|
1747
|
+
cursor: "pointer",
|
|
1748
|
+
padding: "4px 0",
|
|
1749
|
+
color: tokens.textMuted,
|
|
1750
|
+
fontFamily: "inherit",
|
|
1751
|
+
fontSize: "0.8rem",
|
|
1752
|
+
fontWeight: 500,
|
|
1753
|
+
outline: "none",
|
|
1754
|
+
letterSpacing: "0.02em"
|
|
1062
1755
|
},
|
|
1063
1756
|
children: [
|
|
1064
|
-
/* @__PURE__ */ jsx(
|
|
1065
|
-
"
|
|
1757
|
+
/* @__PURE__ */ jsx(
|
|
1758
|
+
"svg",
|
|
1066
1759
|
{
|
|
1067
|
-
|
|
1068
|
-
|
|
1760
|
+
width: "10",
|
|
1761
|
+
height: "10",
|
|
1762
|
+
viewBox: "0 0 24 24",
|
|
1763
|
+
fill: "none",
|
|
1764
|
+
style: {
|
|
1765
|
+
transform: open ? "rotate(180deg)" : "rotate(0deg)",
|
|
1766
|
+
transition: "transform 0.15s ease"
|
|
1767
|
+
},
|
|
1768
|
+
children: /* @__PURE__ */ jsx(
|
|
1769
|
+
"path",
|
|
1770
|
+
{
|
|
1771
|
+
d: "M7 10l5 5 5-5",
|
|
1772
|
+
stroke: tokens.textMuted,
|
|
1773
|
+
strokeWidth: "2.5",
|
|
1774
|
+
strokeLinecap: "round",
|
|
1775
|
+
strokeLinejoin: "round"
|
|
1776
|
+
}
|
|
1777
|
+
)
|
|
1778
|
+
}
|
|
1779
|
+
),
|
|
1780
|
+
"Advanced options"
|
|
1781
|
+
]
|
|
1782
|
+
}
|
|
1783
|
+
),
|
|
1784
|
+
open && /* @__PURE__ */ jsxs(
|
|
1785
|
+
"div",
|
|
1786
|
+
{
|
|
1787
|
+
style: {
|
|
1788
|
+
marginTop: "10px",
|
|
1789
|
+
padding: "14px",
|
|
1790
|
+
background: tokens.bgInput,
|
|
1791
|
+
borderRadius: tokens.radius,
|
|
1792
|
+
border: `1px solid ${tokens.border}`
|
|
1793
|
+
},
|
|
1794
|
+
children: [
|
|
1795
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "14px" }, children: [
|
|
1796
|
+
/* @__PURE__ */ jsx(
|
|
1797
|
+
"label",
|
|
1798
|
+
{
|
|
1799
|
+
style: {
|
|
1800
|
+
display: "block",
|
|
1801
|
+
fontSize: "0.7rem",
|
|
1802
|
+
fontWeight: 600,
|
|
1803
|
+
color: tokens.textMuted,
|
|
1804
|
+
textTransform: "uppercase",
|
|
1805
|
+
letterSpacing: "0.05em",
|
|
1806
|
+
marginBottom: "6px"
|
|
1807
|
+
},
|
|
1808
|
+
children: "Asset"
|
|
1809
|
+
}
|
|
1810
|
+
),
|
|
1811
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px" }, children: ASSETS.map((asset) => {
|
|
1812
|
+
const isSelected = settings.asset === asset;
|
|
1813
|
+
return /* @__PURE__ */ jsx(
|
|
1814
|
+
"button",
|
|
1815
|
+
{
|
|
1816
|
+
onClick: () => onChange({
|
|
1817
|
+
...settings,
|
|
1818
|
+
asset: isSelected ? null : asset
|
|
1819
|
+
}),
|
|
1820
|
+
style: {
|
|
1821
|
+
padding: "6px 14px",
|
|
1822
|
+
fontSize: "0.8rem",
|
|
1823
|
+
fontWeight: 600,
|
|
1824
|
+
fontFamily: "inherit",
|
|
1825
|
+
borderRadius: "6px",
|
|
1826
|
+
border: `1.5px solid ${isSelected ? tokens.accent : tokens.border}`,
|
|
1827
|
+
background: isSelected ? tokens.accent + "18" : "transparent",
|
|
1828
|
+
color: isSelected ? tokens.accent : tokens.text,
|
|
1829
|
+
cursor: "pointer",
|
|
1830
|
+
outline: "none",
|
|
1831
|
+
transition: "all 0.12s ease"
|
|
1832
|
+
},
|
|
1833
|
+
children: asset
|
|
1834
|
+
},
|
|
1835
|
+
asset
|
|
1836
|
+
);
|
|
1837
|
+
}) })
|
|
1838
|
+
] }),
|
|
1839
|
+
chains.length > 0 && /* @__PURE__ */ jsxs("div", { style: { marginBottom: "14px" }, children: [
|
|
1840
|
+
/* @__PURE__ */ jsx(
|
|
1841
|
+
"label",
|
|
1842
|
+
{
|
|
1843
|
+
style: {
|
|
1844
|
+
display: "block",
|
|
1845
|
+
fontSize: "0.7rem",
|
|
1846
|
+
fontWeight: 600,
|
|
1847
|
+
color: tokens.textMuted,
|
|
1848
|
+
textTransform: "uppercase",
|
|
1849
|
+
letterSpacing: "0.05em",
|
|
1850
|
+
marginBottom: "6px"
|
|
1851
|
+
},
|
|
1852
|
+
children: "Chain"
|
|
1853
|
+
}
|
|
1854
|
+
),
|
|
1855
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: chains.map((chain) => {
|
|
1856
|
+
const isSelected = settings.chain === chain.name;
|
|
1857
|
+
return /* @__PURE__ */ jsx(
|
|
1858
|
+
"button",
|
|
1859
|
+
{
|
|
1860
|
+
onClick: () => onChange({
|
|
1861
|
+
...settings,
|
|
1862
|
+
chain: isSelected ? null : chain.name
|
|
1863
|
+
}),
|
|
1864
|
+
style: {
|
|
1865
|
+
padding: "6px 14px",
|
|
1866
|
+
fontSize: "0.8rem",
|
|
1867
|
+
fontWeight: 600,
|
|
1868
|
+
fontFamily: "inherit",
|
|
1869
|
+
borderRadius: "6px",
|
|
1870
|
+
border: `1.5px solid ${isSelected ? tokens.accent : tokens.border}`,
|
|
1871
|
+
background: isSelected ? tokens.accent + "18" : "transparent",
|
|
1872
|
+
color: isSelected ? tokens.accent : tokens.text,
|
|
1873
|
+
cursor: "pointer",
|
|
1874
|
+
outline: "none",
|
|
1875
|
+
transition: "all 0.12s ease"
|
|
1876
|
+
},
|
|
1877
|
+
children: chain.name
|
|
1878
|
+
},
|
|
1879
|
+
chain.id
|
|
1880
|
+
);
|
|
1881
|
+
}) })
|
|
1882
|
+
] }),
|
|
1883
|
+
/* @__PURE__ */ jsx("div", { children: !showProviders ? /* @__PURE__ */ jsxs(
|
|
1884
|
+
"button",
|
|
1885
|
+
{
|
|
1886
|
+
onClick: () => setShowProviders(true),
|
|
1887
|
+
disabled: connectingNewAccount,
|
|
1888
|
+
style: {
|
|
1889
|
+
display: "flex",
|
|
1890
|
+
alignItems: "center",
|
|
1891
|
+
gap: "6px",
|
|
1892
|
+
background: "transparent",
|
|
1893
|
+
border: `1px dashed ${tokens.border}`,
|
|
1894
|
+
borderRadius: tokens.radius,
|
|
1895
|
+
padding: "10px 14px",
|
|
1896
|
+
width: "100%",
|
|
1897
|
+
cursor: connectingNewAccount ? "not-allowed" : "pointer",
|
|
1898
|
+
color: tokens.textSecondary,
|
|
1899
|
+
fontFamily: "inherit",
|
|
1900
|
+
fontSize: "0.825rem",
|
|
1901
|
+
fontWeight: 500,
|
|
1902
|
+
outline: "none",
|
|
1903
|
+
opacity: connectingNewAccount ? 0.5 : 1,
|
|
1904
|
+
transition: "opacity 0.1s ease"
|
|
1905
|
+
},
|
|
1906
|
+
children: [
|
|
1907
|
+
/* @__PURE__ */ jsx(
|
|
1908
|
+
"svg",
|
|
1909
|
+
{
|
|
1910
|
+
width: "14",
|
|
1911
|
+
height: "14",
|
|
1912
|
+
viewBox: "0 0 24 24",
|
|
1913
|
+
fill: "none",
|
|
1914
|
+
children: /* @__PURE__ */ jsx(
|
|
1915
|
+
"path",
|
|
1916
|
+
{
|
|
1917
|
+
d: "M12 5v14M5 12h14",
|
|
1918
|
+
stroke: tokens.textMuted,
|
|
1919
|
+
strokeWidth: "2",
|
|
1920
|
+
strokeLinecap: "round"
|
|
1921
|
+
}
|
|
1922
|
+
)
|
|
1923
|
+
}
|
|
1924
|
+
),
|
|
1925
|
+
"Connect new account"
|
|
1926
|
+
]
|
|
1069
1927
|
}
|
|
1070
|
-
)
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1928
|
+
) : /* @__PURE__ */ jsxs("div", { children: [
|
|
1929
|
+
/* @__PURE__ */ jsxs(
|
|
1930
|
+
"div",
|
|
1931
|
+
{
|
|
1932
|
+
style: {
|
|
1933
|
+
display: "flex",
|
|
1934
|
+
alignItems: "center",
|
|
1935
|
+
justifyContent: "space-between",
|
|
1936
|
+
marginBottom: "8px"
|
|
1937
|
+
},
|
|
1938
|
+
children: [
|
|
1939
|
+
/* @__PURE__ */ jsx(
|
|
1940
|
+
"label",
|
|
1941
|
+
{
|
|
1942
|
+
style: {
|
|
1943
|
+
fontSize: "0.7rem",
|
|
1944
|
+
fontWeight: 600,
|
|
1945
|
+
color: tokens.textMuted,
|
|
1946
|
+
textTransform: "uppercase",
|
|
1947
|
+
letterSpacing: "0.05em"
|
|
1948
|
+
},
|
|
1949
|
+
children: "Select provider"
|
|
1950
|
+
}
|
|
1951
|
+
),
|
|
1952
|
+
/* @__PURE__ */ jsx(
|
|
1953
|
+
"button",
|
|
1954
|
+
{
|
|
1955
|
+
onClick: () => setShowProviders(false),
|
|
1956
|
+
style: {
|
|
1957
|
+
background: "transparent",
|
|
1958
|
+
border: "none",
|
|
1959
|
+
cursor: "pointer",
|
|
1960
|
+
color: tokens.textMuted,
|
|
1961
|
+
fontSize: "0.75rem",
|
|
1962
|
+
fontFamily: "inherit",
|
|
1963
|
+
outline: "none",
|
|
1964
|
+
padding: "2px 4px"
|
|
1965
|
+
},
|
|
1966
|
+
children: "Cancel"
|
|
1967
|
+
}
|
|
1968
|
+
)
|
|
1969
|
+
]
|
|
1970
|
+
}
|
|
1971
|
+
),
|
|
1972
|
+
/* @__PURE__ */ jsx(
|
|
1973
|
+
"div",
|
|
1974
|
+
{
|
|
1975
|
+
style: {
|
|
1976
|
+
display: "flex",
|
|
1977
|
+
flexDirection: "column",
|
|
1978
|
+
gap: "6px"
|
|
1979
|
+
},
|
|
1980
|
+
children: providers.map((p) => /* @__PURE__ */ jsx(
|
|
1981
|
+
ProviderCard,
|
|
1982
|
+
{
|
|
1983
|
+
provider: p,
|
|
1984
|
+
selected: false,
|
|
1985
|
+
onClick: () => {
|
|
1986
|
+
onConnectNewAccount(p.id);
|
|
1987
|
+
setShowProviders(false);
|
|
1988
|
+
}
|
|
1989
|
+
},
|
|
1990
|
+
p.id
|
|
1991
|
+
))
|
|
1992
|
+
}
|
|
1993
|
+
)
|
|
1994
|
+
] }) })
|
|
1075
1995
|
]
|
|
1076
1996
|
}
|
|
1077
1997
|
)
|
|
@@ -1083,69 +2003,135 @@ function isMobile() {
|
|
|
1083
2003
|
navigator.userAgent
|
|
1084
2004
|
);
|
|
1085
2005
|
}
|
|
2006
|
+
function computeSmartDefaults(accts, transferAmount) {
|
|
2007
|
+
if (accts.length === 0) return null;
|
|
2008
|
+
for (const acct of accts) {
|
|
2009
|
+
for (const wallet of acct.wallets) {
|
|
2010
|
+
if (wallet.status === "ACTIVE") {
|
|
2011
|
+
const bestSource = wallet.sources.find(
|
|
2012
|
+
(s) => s.balance.available.amount >= transferAmount
|
|
2013
|
+
);
|
|
2014
|
+
if (bestSource) {
|
|
2015
|
+
return { accountId: acct.id, walletId: wallet.id };
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
let bestAccount = null;
|
|
2021
|
+
let bestWallet = null;
|
|
2022
|
+
let bestBalance = -1;
|
|
2023
|
+
for (const acct of accts) {
|
|
2024
|
+
for (const wallet of acct.wallets) {
|
|
2025
|
+
const walletBal = wallet.balance.available.amount;
|
|
2026
|
+
if (walletBal > bestBalance) {
|
|
2027
|
+
bestBalance = walletBal;
|
|
2028
|
+
bestAccount = acct;
|
|
2029
|
+
bestWallet = wallet;
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
if (bestAccount) {
|
|
2034
|
+
return {
|
|
2035
|
+
accountId: bestAccount.id,
|
|
2036
|
+
walletId: bestWallet?.id ?? null
|
|
2037
|
+
};
|
|
2038
|
+
}
|
|
2039
|
+
return { accountId: accts[0].id, walletId: null };
|
|
2040
|
+
}
|
|
1086
2041
|
function SwypePayment({
|
|
1087
2042
|
destination,
|
|
1088
2043
|
onComplete,
|
|
1089
2044
|
onError
|
|
1090
2045
|
}) {
|
|
1091
|
-
const { apiBaseUrl, tokens } = useSwypeConfig();
|
|
2046
|
+
const { apiBaseUrl, tokens, depositAmount } = useSwypeConfig();
|
|
1092
2047
|
const { ready, authenticated, login, getAccessToken } = usePrivy();
|
|
1093
2048
|
const [step, setStep] = useState("login");
|
|
1094
2049
|
const [error, setError] = useState(null);
|
|
1095
2050
|
const [providers, setProviders] = useState([]);
|
|
1096
2051
|
const [accounts, setAccounts] = useState([]);
|
|
2052
|
+
const [chains, setChains] = useState([]);
|
|
1097
2053
|
const [loadingData, setLoadingData] = useState(false);
|
|
1098
|
-
const [
|
|
1099
|
-
|
|
2054
|
+
const [selectedAccountId, setSelectedAccountId] = useState(null);
|
|
2055
|
+
const [selectedWalletId, setSelectedWalletId] = useState(null);
|
|
2056
|
+
const [selectedProviderId, setSelectedProviderId] = useState(null);
|
|
2057
|
+
const [connectingNewAccount, setConnectingNewAccount] = useState(false);
|
|
2058
|
+
const [amount, setAmount] = useState(
|
|
2059
|
+
depositAmount != null ? depositAmount.toString() : ""
|
|
1100
2060
|
);
|
|
1101
|
-
const [
|
|
1102
|
-
|
|
1103
|
-
|
|
2061
|
+
const [advancedSettings, setAdvancedSettings] = useState({
|
|
2062
|
+
asset: null,
|
|
2063
|
+
chain: null
|
|
2064
|
+
});
|
|
1104
2065
|
const [transfer, setTransfer] = useState(null);
|
|
1105
2066
|
const [creatingTransfer, setCreatingTransfer] = useState(false);
|
|
1106
2067
|
const [mobileFlow, setMobileFlow] = useState(false);
|
|
1107
2068
|
const pollingTransferIdRef = useRef(null);
|
|
1108
2069
|
const authExecutor = useAuthorizationExecutor();
|
|
1109
2070
|
const polling = useTransferPolling();
|
|
1110
|
-
const
|
|
1111
|
-
const
|
|
2071
|
+
const transferSigning = useTransferSigning();
|
|
2072
|
+
const sourceType = connectingNewAccount ? "providerId" : selectedWalletId ? "walletId" : selectedAccountId ? "accountId" : "providerId";
|
|
2073
|
+
const sourceId = connectingNewAccount ? selectedProviderId ?? "" : selectedWalletId ? selectedWalletId : selectedAccountId ? selectedAccountId : selectedProviderId ?? "";
|
|
2074
|
+
useEffect(() => {
|
|
2075
|
+
if (depositAmount != null) {
|
|
2076
|
+
setAmount(depositAmount.toString());
|
|
2077
|
+
}
|
|
2078
|
+
}, [depositAmount]);
|
|
1112
2079
|
useEffect(() => {
|
|
1113
2080
|
if (ready && authenticated && step === "login") {
|
|
1114
|
-
|
|
2081
|
+
if (depositAmount != null && depositAmount > 0) {
|
|
2082
|
+
setStep("ready");
|
|
2083
|
+
} else {
|
|
2084
|
+
setStep("enter-amount");
|
|
2085
|
+
}
|
|
1115
2086
|
}
|
|
1116
|
-
}, [ready, authenticated, step]);
|
|
2087
|
+
}, [ready, authenticated, step, depositAmount]);
|
|
2088
|
+
const loadingDataRef = useRef(false);
|
|
1117
2089
|
useEffect(() => {
|
|
1118
|
-
if (
|
|
1119
|
-
if (
|
|
2090
|
+
if (!authenticated) return;
|
|
2091
|
+
if (accounts.length > 0 || loadingDataRef.current) return;
|
|
1120
2092
|
let cancelled = false;
|
|
2093
|
+
loadingDataRef.current = true;
|
|
1121
2094
|
const load = async () => {
|
|
1122
2095
|
setLoadingData(true);
|
|
1123
2096
|
setError(null);
|
|
1124
2097
|
try {
|
|
1125
2098
|
const token = await getAccessToken();
|
|
1126
2099
|
if (!token) throw new Error("Not authenticated");
|
|
1127
|
-
const [prov, accts] = await Promise.all([
|
|
2100
|
+
const [prov, accts, chn] = await Promise.all([
|
|
1128
2101
|
fetchProviders(apiBaseUrl, token),
|
|
1129
|
-
fetchAccounts(apiBaseUrl, token)
|
|
2102
|
+
fetchAccounts(apiBaseUrl, token),
|
|
2103
|
+
fetchChains(apiBaseUrl, token)
|
|
1130
2104
|
]);
|
|
1131
2105
|
if (cancelled) return;
|
|
1132
2106
|
setProviders(prov);
|
|
1133
2107
|
setAccounts(accts);
|
|
1134
|
-
|
|
2108
|
+
setChains(chn);
|
|
2109
|
+
const parsedAmt = depositAmount != null ? depositAmount : 0;
|
|
2110
|
+
const defaults = computeSmartDefaults(accts, parsedAmt);
|
|
2111
|
+
if (defaults) {
|
|
2112
|
+
setSelectedAccountId(defaults.accountId);
|
|
2113
|
+
setSelectedWalletId(defaults.walletId);
|
|
2114
|
+
} else if (prov.length > 0) {
|
|
2115
|
+
setSelectedProviderId(prov[0].id);
|
|
2116
|
+
}
|
|
1135
2117
|
} catch (err) {
|
|
1136
2118
|
if (!cancelled) {
|
|
1137
2119
|
const msg = err instanceof Error ? err.message : "Failed to load data";
|
|
1138
2120
|
setError(msg);
|
|
1139
2121
|
}
|
|
1140
2122
|
} finally {
|
|
1141
|
-
if (!cancelled)
|
|
2123
|
+
if (!cancelled) {
|
|
2124
|
+
setLoadingData(false);
|
|
2125
|
+
loadingDataRef.current = false;
|
|
2126
|
+
}
|
|
1142
2127
|
}
|
|
1143
2128
|
};
|
|
1144
2129
|
load();
|
|
1145
2130
|
return () => {
|
|
1146
2131
|
cancelled = true;
|
|
2132
|
+
loadingDataRef.current = false;
|
|
1147
2133
|
};
|
|
1148
|
-
}, [
|
|
2134
|
+
}, [authenticated, accounts.length, apiBaseUrl, getAccessToken]);
|
|
1149
2135
|
useEffect(() => {
|
|
1150
2136
|
if (!polling.transfer) return;
|
|
1151
2137
|
if (polling.transfer.status === "COMPLETED") {
|
|
@@ -1172,6 +2158,61 @@ function SwypePayment({
|
|
|
1172
2158
|
document.removeEventListener("visibilitychange", handleVisibility);
|
|
1173
2159
|
};
|
|
1174
2160
|
}, [mobileFlow, polling]);
|
|
2161
|
+
useEffect(() => {
|
|
2162
|
+
if (!authExecutor.pendingSelectSource) return;
|
|
2163
|
+
const action = authExecutor.pendingSelectSource;
|
|
2164
|
+
const hasAdvancedOverride = advancedSettings.asset !== null || advancedSettings.chain !== null;
|
|
2165
|
+
if (hasAdvancedOverride) {
|
|
2166
|
+
const options = action.metadata?.options ?? [];
|
|
2167
|
+
const recommended = action.metadata?.recommended;
|
|
2168
|
+
const match = options.find(
|
|
2169
|
+
(opt) => (advancedSettings.chain === null || opt.chainName === advancedSettings.chain) && (advancedSettings.asset === null || opt.tokenSymbol === advancedSettings.asset)
|
|
2170
|
+
);
|
|
2171
|
+
if (match) {
|
|
2172
|
+
authExecutor.resolveSelectSource({
|
|
2173
|
+
chainName: match.chainName,
|
|
2174
|
+
tokenSymbol: match.tokenSymbol
|
|
2175
|
+
});
|
|
2176
|
+
} else if (recommended) {
|
|
2177
|
+
authExecutor.resolveSelectSource({
|
|
2178
|
+
chainName: recommended.chainName,
|
|
2179
|
+
tokenSymbol: recommended.tokenSymbol
|
|
2180
|
+
});
|
|
2181
|
+
}
|
|
2182
|
+
} else {
|
|
2183
|
+
const options = action.metadata?.options ?? [];
|
|
2184
|
+
const recommended = action.metadata?.recommended;
|
|
2185
|
+
const selWallet = selectedWalletId ? accounts.find((a) => a.id === selectedAccountId)?.wallets.find((w) => w.id === selectedWalletId) : null;
|
|
2186
|
+
if (selWallet) {
|
|
2187
|
+
const walletMatch = options.find(
|
|
2188
|
+
(opt) => opt.chainName === selWallet.chain.name
|
|
2189
|
+
);
|
|
2190
|
+
if (walletMatch) {
|
|
2191
|
+
authExecutor.resolveSelectSource({
|
|
2192
|
+
chainName: walletMatch.chainName,
|
|
2193
|
+
tokenSymbol: walletMatch.tokenSymbol
|
|
2194
|
+
});
|
|
2195
|
+
return;
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
if (recommended) {
|
|
2199
|
+
authExecutor.resolveSelectSource({
|
|
2200
|
+
chainName: recommended.chainName,
|
|
2201
|
+
tokenSymbol: recommended.tokenSymbol
|
|
2202
|
+
});
|
|
2203
|
+
} else if (options.length > 0) {
|
|
2204
|
+
authExecutor.resolveSelectSource({
|
|
2205
|
+
chainName: options[0].chainName,
|
|
2206
|
+
tokenSymbol: options[0].tokenSymbol
|
|
2207
|
+
});
|
|
2208
|
+
} else {
|
|
2209
|
+
authExecutor.resolveSelectSource({
|
|
2210
|
+
chainName: "Base",
|
|
2211
|
+
tokenSymbol: "USDC"
|
|
2212
|
+
});
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
}, [authExecutor, authExecutor.pendingSelectSource, advancedSettings, selectedWalletId, selectedAccountId, accounts]);
|
|
1175
2216
|
const handlePay = useCallback(async () => {
|
|
1176
2217
|
const parsedAmount = parseFloat(amount);
|
|
1177
2218
|
if (isNaN(parsedAmount) || parsedAmount <= 0) {
|
|
@@ -1179,7 +2220,7 @@ function SwypePayment({
|
|
|
1179
2220
|
return;
|
|
1180
2221
|
}
|
|
1181
2222
|
if (!sourceId) {
|
|
1182
|
-
setError("
|
|
2223
|
+
setError("No account or provider selected.");
|
|
1183
2224
|
return;
|
|
1184
2225
|
}
|
|
1185
2226
|
setStep("processing");
|
|
@@ -1189,12 +2230,6 @@ function SwypePayment({
|
|
|
1189
2230
|
try {
|
|
1190
2231
|
const token = await getAccessToken();
|
|
1191
2232
|
if (!token) throw new Error("Not authenticated");
|
|
1192
|
-
const parsedTopUp = parseFloat(topUpBalance);
|
|
1193
|
-
if (!isNaN(parsedTopUp) && parsedTopUp > 0) {
|
|
1194
|
-
await updateUserConfig(apiBaseUrl, token, {
|
|
1195
|
-
defaultAllowance: parsedTopUp
|
|
1196
|
-
});
|
|
1197
|
-
}
|
|
1198
2233
|
const t = await createTransfer(apiBaseUrl, token, {
|
|
1199
2234
|
sourceType,
|
|
1200
2235
|
sourceId,
|
|
@@ -1213,12 +2248,14 @@ function SwypePayment({
|
|
|
1213
2248
|
await authExecutor.executeSession(t);
|
|
1214
2249
|
}
|
|
1215
2250
|
}
|
|
2251
|
+
const signedTransfer = await transferSigning.signTransfer(t.id);
|
|
2252
|
+
setTransfer(signedTransfer);
|
|
1216
2253
|
polling.startPolling(t.id);
|
|
1217
2254
|
} catch (err) {
|
|
1218
|
-
const msg = err instanceof Error ? err.message : "Transfer
|
|
2255
|
+
const msg = err instanceof Error ? err.message : "Transfer failed";
|
|
1219
2256
|
setError(msg);
|
|
1220
2257
|
onError?.(msg);
|
|
1221
|
-
setStep("
|
|
2258
|
+
setStep("ready");
|
|
1222
2259
|
} finally {
|
|
1223
2260
|
setCreatingTransfer(false);
|
|
1224
2261
|
}
|
|
@@ -1230,20 +2267,26 @@ function SwypePayment({
|
|
|
1230
2267
|
apiBaseUrl,
|
|
1231
2268
|
getAccessToken,
|
|
1232
2269
|
authExecutor,
|
|
2270
|
+
transferSigning,
|
|
1233
2271
|
polling,
|
|
1234
|
-
onError
|
|
1235
|
-
topUpBalance
|
|
2272
|
+
onError
|
|
1236
2273
|
]);
|
|
1237
2274
|
const handleNewPayment = () => {
|
|
1238
|
-
setStep("
|
|
2275
|
+
setStep("ready");
|
|
1239
2276
|
setTransfer(null);
|
|
1240
2277
|
setError(null);
|
|
1241
|
-
setAmount(
|
|
1242
|
-
setTopUpBalance("");
|
|
2278
|
+
setAmount(depositAmount != null ? depositAmount.toString() : "");
|
|
1243
2279
|
setMobileFlow(false);
|
|
1244
2280
|
pollingTransferIdRef.current = null;
|
|
1245
|
-
|
|
1246
|
-
|
|
2281
|
+
setConnectingNewAccount(false);
|
|
2282
|
+
setSelectedWalletId(null);
|
|
2283
|
+
setAdvancedSettings({ asset: null, chain: null });
|
|
2284
|
+
if (accounts.length > 0) setSelectedAccountId(accounts[0].id);
|
|
2285
|
+
};
|
|
2286
|
+
const handleConnectNewAccount = (providerId) => {
|
|
2287
|
+
setSelectedProviderId(providerId);
|
|
2288
|
+
setSelectedAccountId(null);
|
|
2289
|
+
setConnectingNewAccount(true);
|
|
1247
2290
|
};
|
|
1248
2291
|
const cardStyle = {
|
|
1249
2292
|
background: tokens.bgCard,
|
|
@@ -1281,15 +2324,10 @@ function SwypePayment({
|
|
|
1281
2324
|
opacity: 0.5,
|
|
1282
2325
|
cursor: "not-allowed"
|
|
1283
2326
|
};
|
|
1284
|
-
|
|
2327
|
+
({
|
|
1285
2328
|
...btnPrimary,
|
|
1286
|
-
background: "transparent",
|
|
1287
2329
|
color: tokens.textSecondary,
|
|
1288
|
-
border: `1px solid ${tokens.border}
|
|
1289
|
-
width: "auto",
|
|
1290
|
-
flex: "0 0 auto",
|
|
1291
|
-
padding: "14px 20px"
|
|
1292
|
-
};
|
|
2330
|
+
border: `1px solid ${tokens.border}`});
|
|
1293
2331
|
const errorStyle = {
|
|
1294
2332
|
background: tokens.errorBg,
|
|
1295
2333
|
border: `1px solid ${tokens.error}`,
|
|
@@ -1380,62 +2418,20 @@ function SwypePayment({
|
|
|
1380
2418
|
/* @__PURE__ */ jsx("button", { style: btnPrimary, onClick: login, children: "Connect to Swype" })
|
|
1381
2419
|
] }) });
|
|
1382
2420
|
}
|
|
1383
|
-
if (step === "select-source") {
|
|
1384
|
-
return /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
|
|
1385
|
-
stepBadge("Select payment source"),
|
|
1386
|
-
/* @__PURE__ */ jsx("h2", { style: headingStyle, children: "Choose a provider" }),
|
|
1387
|
-
error && /* @__PURE__ */ jsx("div", { style: errorStyle, children: error }),
|
|
1388
|
-
loadingData ? /* @__PURE__ */ jsx("div", { style: { padding: "24px 0", textAlign: "center" }, children: /* @__PURE__ */ jsx(Spinner, { label: "Loading providers..." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1389
|
-
accounts.length > 0 && /* @__PURE__ */ jsx("div", { style: { marginBottom: "16px" }, children: /* @__PURE__ */ jsx(
|
|
1390
|
-
AccountWalletSelector,
|
|
1391
|
-
{
|
|
1392
|
-
accounts,
|
|
1393
|
-
selection: walletSelection,
|
|
1394
|
-
onSelect: (sel) => {
|
|
1395
|
-
setWalletSelection(sel);
|
|
1396
|
-
if (sel) setSelectedProviderId(null);
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
) }),
|
|
1400
|
-
!walletSelection && /* @__PURE__ */ jsx(
|
|
1401
|
-
"div",
|
|
1402
|
-
{
|
|
1403
|
-
style: {
|
|
1404
|
-
display: "flex",
|
|
1405
|
-
flexDirection: "column",
|
|
1406
|
-
gap: "8px",
|
|
1407
|
-
marginBottom: "20px"
|
|
1408
|
-
},
|
|
1409
|
-
children: providers.map((p) => /* @__PURE__ */ jsx(
|
|
1410
|
-
ProviderCard,
|
|
1411
|
-
{
|
|
1412
|
-
provider: p,
|
|
1413
|
-
selected: selectedProviderId === p.id,
|
|
1414
|
-
onClick: () => {
|
|
1415
|
-
setSelectedProviderId(p.id);
|
|
1416
|
-
setWalletSelection(null);
|
|
1417
|
-
}
|
|
1418
|
-
},
|
|
1419
|
-
p.id
|
|
1420
|
-
))
|
|
1421
|
-
}
|
|
1422
|
-
),
|
|
1423
|
-
/* @__PURE__ */ jsx(
|
|
1424
|
-
"button",
|
|
1425
|
-
{
|
|
1426
|
-
style: sourceId ? btnPrimary : btnDisabled,
|
|
1427
|
-
disabled: !sourceId,
|
|
1428
|
-
onClick: () => {
|
|
1429
|
-
setError(null);
|
|
1430
|
-
setStep("enter-amount");
|
|
1431
|
-
},
|
|
1432
|
-
children: "Continue"
|
|
1433
|
-
}
|
|
1434
|
-
)
|
|
1435
|
-
] })
|
|
1436
|
-
] });
|
|
1437
|
-
}
|
|
1438
2421
|
if (step === "enter-amount") {
|
|
2422
|
+
const parsedAmount = parseFloat(amount);
|
|
2423
|
+
const canContinue = !isNaN(parsedAmount) && parsedAmount > 0;
|
|
2424
|
+
let maxSourceBalance = null;
|
|
2425
|
+
for (const acct of accounts) {
|
|
2426
|
+
for (const wallet of acct.wallets) {
|
|
2427
|
+
for (const source of wallet.sources) {
|
|
2428
|
+
const bal = source.balance.available.amount;
|
|
2429
|
+
if (maxSourceBalance === null || bal > maxSourceBalance) {
|
|
2430
|
+
maxSourceBalance = bal;
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
1439
2435
|
return /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
|
|
1440
2436
|
stepBadge("Enter amount"),
|
|
1441
2437
|
/* @__PURE__ */ jsx("h2", { style: headingStyle, children: "How much?" }),
|
|
@@ -1451,7 +2447,7 @@ function SwypePayment({
|
|
|
1451
2447
|
border: `1px solid ${tokens.border}`,
|
|
1452
2448
|
borderRadius: tokens.radius,
|
|
1453
2449
|
padding: "4px 14px 4px 4px",
|
|
1454
|
-
marginBottom: "
|
|
2450
|
+
marginBottom: "8px"
|
|
1455
2451
|
},
|
|
1456
2452
|
children: [
|
|
1457
2453
|
/* @__PURE__ */ jsx(
|
|
@@ -1475,6 +2471,7 @@ function SwypePayment({
|
|
|
1475
2471
|
step: "0.01",
|
|
1476
2472
|
value: amount,
|
|
1477
2473
|
onChange: (e) => setAmount(e.target.value),
|
|
2474
|
+
placeholder: "0.00",
|
|
1478
2475
|
style: {
|
|
1479
2476
|
flex: 1,
|
|
1480
2477
|
background: "transparent",
|
|
@@ -1506,156 +2503,301 @@ function SwypePayment({
|
|
|
1506
2503
|
]
|
|
1507
2504
|
}
|
|
1508
2505
|
),
|
|
1509
|
-
/* @__PURE__ */
|
|
2506
|
+
/* @__PURE__ */ jsx(
|
|
1510
2507
|
"div",
|
|
1511
2508
|
{
|
|
1512
2509
|
style: {
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
border: `1px solid ${tokens.border}`,
|
|
1518
|
-
borderRadius: tokens.radius,
|
|
1519
|
-
padding: "4px 14px 4px 4px",
|
|
1520
|
-
marginBottom: "20px"
|
|
2510
|
+
fontSize: "0.8rem",
|
|
2511
|
+
color: tokens.textMuted,
|
|
2512
|
+
marginBottom: "20px",
|
|
2513
|
+
paddingLeft: "2px"
|
|
1521
2514
|
},
|
|
1522
|
-
children: [
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
color: tokens.textMuted,
|
|
1530
|
-
paddingLeft: "10px",
|
|
1531
|
-
userSelect: "none"
|
|
1532
|
-
},
|
|
1533
|
-
children: "$"
|
|
1534
|
-
}
|
|
1535
|
-
),
|
|
1536
|
-
/* @__PURE__ */ jsx(
|
|
1537
|
-
"input",
|
|
1538
|
-
{
|
|
1539
|
-
type: "number",
|
|
1540
|
-
min: "0",
|
|
1541
|
-
step: "1",
|
|
1542
|
-
placeholder: "Top up balance (optional)",
|
|
1543
|
-
value: topUpBalance,
|
|
1544
|
-
onChange: (e) => setTopUpBalance(e.target.value),
|
|
1545
|
-
style: {
|
|
1546
|
-
flex: 1,
|
|
1547
|
-
background: "transparent",
|
|
1548
|
-
border: "none",
|
|
1549
|
-
outline: "none",
|
|
1550
|
-
color: tokens.text,
|
|
1551
|
-
fontSize: "1rem",
|
|
1552
|
-
fontWeight: 600,
|
|
1553
|
-
fontFamily: "inherit",
|
|
1554
|
-
padding: "10px 0"
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
),
|
|
1558
|
-
/* @__PURE__ */ jsx(
|
|
1559
|
-
"span",
|
|
1560
|
-
{
|
|
1561
|
-
style: {
|
|
1562
|
-
fontSize: "0.75rem",
|
|
1563
|
-
fontWeight: 600,
|
|
1564
|
-
color: tokens.textMuted,
|
|
1565
|
-
background: tokens.bgHover,
|
|
1566
|
-
padding: "4px 10px",
|
|
1567
|
-
borderRadius: "6px",
|
|
1568
|
-
whiteSpace: "nowrap"
|
|
1569
|
-
},
|
|
1570
|
-
children: "USD"
|
|
1571
|
-
}
|
|
1572
|
-
)
|
|
1573
|
-
]
|
|
2515
|
+
children: loadingData ? /* @__PURE__ */ jsx("span", { children: "Loading balance..." }) : maxSourceBalance !== null && maxSourceBalance > 0 ? /* @__PURE__ */ jsxs("span", { children: [
|
|
2516
|
+
"Available: ",
|
|
2517
|
+
/* @__PURE__ */ jsxs("span", { style: { fontWeight: 600, color: tokens.textSecondary }, children: [
|
|
2518
|
+
"$",
|
|
2519
|
+
maxSourceBalance.toFixed(2)
|
|
2520
|
+
] })
|
|
2521
|
+
] }) : null
|
|
1574
2522
|
}
|
|
1575
2523
|
),
|
|
1576
2524
|
/* @__PURE__ */ jsx(
|
|
1577
|
-
"
|
|
2525
|
+
"button",
|
|
1578
2526
|
{
|
|
1579
|
-
style:
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
2527
|
+
style: canContinue ? btnPrimary : btnDisabled,
|
|
2528
|
+
disabled: !canContinue,
|
|
2529
|
+
onClick: () => {
|
|
2530
|
+
setError(null);
|
|
2531
|
+
setStep("ready");
|
|
1584
2532
|
},
|
|
1585
|
-
children: "
|
|
2533
|
+
children: "Continue"
|
|
1586
2534
|
}
|
|
1587
|
-
)
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
2535
|
+
)
|
|
2536
|
+
] });
|
|
2537
|
+
}
|
|
2538
|
+
if (step === "ready") {
|
|
2539
|
+
const parsedAmount = parseFloat(amount);
|
|
2540
|
+
const canPay = !isNaN(parsedAmount) && parsedAmount > 0 && !!sourceId && !loadingData;
|
|
2541
|
+
const noAccounts = !loadingData && accounts.length === 0;
|
|
2542
|
+
return /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
|
|
2543
|
+
stepBadge("Review & pay"),
|
|
2544
|
+
error && /* @__PURE__ */ jsx("div", { style: errorStyle, children: error }),
|
|
2545
|
+
loadingData ? /* @__PURE__ */ jsx("div", { style: { padding: "24px 0", textAlign: "center" }, children: /* @__PURE__ */ jsx(Spinner, { label: "Loading..." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2546
|
+
/* @__PURE__ */ jsxs(
|
|
2547
|
+
"div",
|
|
2548
|
+
{
|
|
2549
|
+
style: {
|
|
2550
|
+
textAlign: "center",
|
|
2551
|
+
marginBottom: "20px"
|
|
2552
|
+
},
|
|
2553
|
+
children: [
|
|
1603
2554
|
/* @__PURE__ */ jsxs(
|
|
1604
|
-
"
|
|
2555
|
+
"div",
|
|
1605
2556
|
{
|
|
1606
2557
|
style: {
|
|
1607
|
-
|
|
1608
|
-
|
|
2558
|
+
fontSize: "2rem",
|
|
2559
|
+
fontWeight: 700,
|
|
2560
|
+
color: tokens.text,
|
|
2561
|
+
lineHeight: 1.2
|
|
1609
2562
|
},
|
|
1610
2563
|
children: [
|
|
1611
|
-
|
|
1612
|
-
"
|
|
1613
|
-
destination.address.slice(-4)
|
|
2564
|
+
"$",
|
|
2565
|
+
parsedAmount > 0 ? parsedAmount.toFixed(2) : "0.00"
|
|
1614
2566
|
]
|
|
1615
2567
|
}
|
|
2568
|
+
),
|
|
2569
|
+
/* @__PURE__ */ jsx(
|
|
2570
|
+
"button",
|
|
2571
|
+
{
|
|
2572
|
+
onClick: () => setStep("enter-amount"),
|
|
2573
|
+
style: {
|
|
2574
|
+
background: "transparent",
|
|
2575
|
+
border: "none",
|
|
2576
|
+
cursor: "pointer",
|
|
2577
|
+
color: tokens.textMuted,
|
|
2578
|
+
fontSize: "0.75rem",
|
|
2579
|
+
fontFamily: "inherit",
|
|
2580
|
+
outline: "none",
|
|
2581
|
+
padding: "4px 8px",
|
|
2582
|
+
marginTop: "4px"
|
|
2583
|
+
},
|
|
2584
|
+
children: "Change amount"
|
|
2585
|
+
}
|
|
1616
2586
|
)
|
|
1617
|
-
]
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
|
|
1623
|
-
/* @__PURE__ */ jsx("span", { children: "Source" }),
|
|
1624
|
-
/* @__PURE__ */ jsx("span", { style: { fontWeight: 600 }, children: walletSelection ? `${walletSelection.walletName} (${walletSelection.chainName})` : providers.find((p) => p.id === selectedProviderId)?.name ?? "Provider" })
|
|
1625
|
-
] })
|
|
1626
|
-
]
|
|
1627
|
-
}
|
|
1628
|
-
),
|
|
1629
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
1630
|
-
/* @__PURE__ */ jsx(
|
|
1631
|
-
"button",
|
|
2587
|
+
]
|
|
2588
|
+
}
|
|
2589
|
+
),
|
|
2590
|
+
/* @__PURE__ */ jsxs(
|
|
2591
|
+
"div",
|
|
1632
2592
|
{
|
|
1633
|
-
style:
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
2593
|
+
style: {
|
|
2594
|
+
fontSize: "0.825rem",
|
|
2595
|
+
color: tokens.textSecondary,
|
|
2596
|
+
marginBottom: "16px",
|
|
2597
|
+
padding: "12px 14px",
|
|
2598
|
+
background: tokens.bgInput,
|
|
2599
|
+
borderRadius: tokens.radius,
|
|
2600
|
+
lineHeight: 1.7
|
|
1637
2601
|
},
|
|
1638
|
-
children:
|
|
2602
|
+
children: [
|
|
2603
|
+
/* @__PURE__ */ jsxs(
|
|
2604
|
+
"div",
|
|
2605
|
+
{
|
|
2606
|
+
style: { display: "flex", justifyContent: "space-between" },
|
|
2607
|
+
children: [
|
|
2608
|
+
/* @__PURE__ */ jsx("span", { children: "To" }),
|
|
2609
|
+
/* @__PURE__ */ jsxs(
|
|
2610
|
+
"span",
|
|
2611
|
+
{
|
|
2612
|
+
style: {
|
|
2613
|
+
fontFamily: '"SF Mono", "Fira Code", monospace',
|
|
2614
|
+
fontSize: "0.8rem"
|
|
2615
|
+
},
|
|
2616
|
+
children: [
|
|
2617
|
+
destination.address.slice(0, 6),
|
|
2618
|
+
"...",
|
|
2619
|
+
destination.address.slice(-4)
|
|
2620
|
+
]
|
|
2621
|
+
}
|
|
2622
|
+
)
|
|
2623
|
+
]
|
|
2624
|
+
}
|
|
2625
|
+
),
|
|
2626
|
+
/* @__PURE__ */ jsxs(
|
|
2627
|
+
"div",
|
|
2628
|
+
{
|
|
2629
|
+
style: { display: "flex", justifyContent: "space-between" },
|
|
2630
|
+
children: [
|
|
2631
|
+
/* @__PURE__ */ jsx("span", { children: "Token" }),
|
|
2632
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 600 }, children: destination.token.symbol })
|
|
2633
|
+
]
|
|
2634
|
+
}
|
|
2635
|
+
),
|
|
2636
|
+
/* @__PURE__ */ jsxs(
|
|
2637
|
+
"div",
|
|
2638
|
+
{
|
|
2639
|
+
style: {
|
|
2640
|
+
display: "flex",
|
|
2641
|
+
justifyContent: "space-between",
|
|
2642
|
+
alignItems: "center"
|
|
2643
|
+
},
|
|
2644
|
+
children: [
|
|
2645
|
+
/* @__PURE__ */ jsx("span", { children: "From" }),
|
|
2646
|
+
noAccounts ? /* @__PURE__ */ jsx("span", { style: { fontWeight: 500, color: tokens.textMuted }, children: "New account" }) : /* @__PURE__ */ jsx(
|
|
2647
|
+
AccountDropdown,
|
|
2648
|
+
{
|
|
2649
|
+
accounts,
|
|
2650
|
+
selectedAccountId,
|
|
2651
|
+
selectedWalletId,
|
|
2652
|
+
onSelect: (id) => {
|
|
2653
|
+
setSelectedAccountId(id);
|
|
2654
|
+
setSelectedWalletId(null);
|
|
2655
|
+
setConnectingNewAccount(false);
|
|
2656
|
+
setSelectedProviderId(null);
|
|
2657
|
+
},
|
|
2658
|
+
onWalletSelect: (accountId, walletId) => {
|
|
2659
|
+
setSelectedAccountId(accountId);
|
|
2660
|
+
setSelectedWalletId(walletId);
|
|
2661
|
+
setConnectingNewAccount(false);
|
|
2662
|
+
setSelectedProviderId(null);
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
)
|
|
2666
|
+
]
|
|
2667
|
+
}
|
|
2668
|
+
)
|
|
2669
|
+
]
|
|
1639
2670
|
}
|
|
1640
2671
|
),
|
|
2672
|
+
noAccounts && /* @__PURE__ */ jsxs("div", { style: { marginBottom: "16px" }, children: [
|
|
2673
|
+
/* @__PURE__ */ jsx(
|
|
2674
|
+
"label",
|
|
2675
|
+
{
|
|
2676
|
+
style: {
|
|
2677
|
+
display: "block",
|
|
2678
|
+
fontSize: "0.8rem",
|
|
2679
|
+
color: tokens.textMuted,
|
|
2680
|
+
marginBottom: "8px",
|
|
2681
|
+
fontWeight: 500,
|
|
2682
|
+
textTransform: "uppercase",
|
|
2683
|
+
letterSpacing: "0.05em"
|
|
2684
|
+
},
|
|
2685
|
+
children: "Connect a wallet"
|
|
2686
|
+
}
|
|
2687
|
+
),
|
|
2688
|
+
/* @__PURE__ */ jsx(
|
|
2689
|
+
"div",
|
|
2690
|
+
{
|
|
2691
|
+
style: {
|
|
2692
|
+
display: "flex",
|
|
2693
|
+
flexDirection: "column",
|
|
2694
|
+
gap: "8px"
|
|
2695
|
+
},
|
|
2696
|
+
children: providers.map((p) => /* @__PURE__ */ jsx(
|
|
2697
|
+
ProviderCard,
|
|
2698
|
+
{
|
|
2699
|
+
provider: p,
|
|
2700
|
+
selected: selectedProviderId === p.id,
|
|
2701
|
+
onClick: () => {
|
|
2702
|
+
setSelectedProviderId(p.id);
|
|
2703
|
+
setSelectedAccountId(null);
|
|
2704
|
+
setConnectingNewAccount(false);
|
|
2705
|
+
}
|
|
2706
|
+
},
|
|
2707
|
+
p.id
|
|
2708
|
+
))
|
|
2709
|
+
}
|
|
2710
|
+
)
|
|
2711
|
+
] }),
|
|
1641
2712
|
/* @__PURE__ */ jsxs(
|
|
1642
2713
|
"button",
|
|
1643
2714
|
{
|
|
1644
|
-
style:
|
|
1645
|
-
disabled: !
|
|
2715
|
+
style: canPay ? btnPrimary : btnDisabled,
|
|
2716
|
+
disabled: !canPay,
|
|
1646
2717
|
onClick: handlePay,
|
|
1647
2718
|
children: [
|
|
1648
2719
|
"Pay $",
|
|
1649
|
-
|
|
2720
|
+
parsedAmount > 0 ? parsedAmount.toFixed(2) : "0.00"
|
|
1650
2721
|
]
|
|
1651
2722
|
}
|
|
2723
|
+
),
|
|
2724
|
+
!noAccounts && /* @__PURE__ */ jsx(
|
|
2725
|
+
AdvancedSettings,
|
|
2726
|
+
{
|
|
2727
|
+
settings: advancedSettings,
|
|
2728
|
+
onChange: setAdvancedSettings,
|
|
2729
|
+
chains,
|
|
2730
|
+
providers,
|
|
2731
|
+
onConnectNewAccount: handleConnectNewAccount,
|
|
2732
|
+
connectingNewAccount
|
|
2733
|
+
}
|
|
1652
2734
|
)
|
|
1653
2735
|
] })
|
|
1654
2736
|
] });
|
|
1655
2737
|
}
|
|
1656
2738
|
if (step === "processing") {
|
|
1657
|
-
|
|
1658
|
-
|
|
2739
|
+
if (transferSigning.signing && transferSigning.signPayload) {
|
|
2740
|
+
const payload = transferSigning.signPayload;
|
|
2741
|
+
return /* @__PURE__ */ jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "16px 0" }, children: [
|
|
2742
|
+
/* @__PURE__ */ jsxs("svg", { width: "48", height: "48", viewBox: "0 0 48 48", fill: "none", style: { margin: "0 auto 16px" }, children: [
|
|
2743
|
+
/* @__PURE__ */ jsx("rect", { width: "48", height: "48", rx: "12", fill: tokens.accent + "20" }),
|
|
2744
|
+
/* @__PURE__ */ jsx("path", { d: "M24 14v8M20 18h8M24 26v2M24 32v2", stroke: tokens.accent, strokeWidth: "2", strokeLinecap: "round" })
|
|
2745
|
+
] }),
|
|
2746
|
+
/* @__PURE__ */ jsx("h2", { style: { ...headingStyle, marginBottom: "8px" }, children: "Authorize Transfer" }),
|
|
2747
|
+
/* @__PURE__ */ jsx("p", { style: { fontSize: "0.85rem", color: tokens.textSecondary, margin: "0 0 16px 0", lineHeight: 1.5 }, children: "Use your passkey to confirm this payment." }),
|
|
2748
|
+
/* @__PURE__ */ jsxs("div", { style: { fontSize: "0.825rem", color: tokens.textSecondary, padding: "12px 14px", background: tokens.bgInput, borderRadius: tokens.radius, textAlign: "left", lineHeight: 1.7, marginBottom: "16px" }, children: [
|
|
2749
|
+
payload.amount && payload.tokenSymbol && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
|
|
2750
|
+
/* @__PURE__ */ jsx("span", { children: "Amount" }),
|
|
2751
|
+
/* @__PURE__ */ jsxs("span", { style: { fontWeight: 600, color: tokens.text }, children: [
|
|
2752
|
+
payload.amount,
|
|
2753
|
+
" ",
|
|
2754
|
+
payload.tokenSymbol
|
|
2755
|
+
] })
|
|
2756
|
+
] }),
|
|
2757
|
+
payload.bridgeRelayAddress && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
|
|
2758
|
+
/* @__PURE__ */ jsx("span", { children: "Bridge relay" }),
|
|
2759
|
+
/* @__PURE__ */ jsxs("span", { style: { fontFamily: '"SF Mono", "Fira Code", monospace', fontSize: "0.75rem" }, children: [
|
|
2760
|
+
payload.bridgeRelayAddress.slice(0, 6),
|
|
2761
|
+
"...",
|
|
2762
|
+
payload.bridgeRelayAddress.slice(-4)
|
|
2763
|
+
] })
|
|
2764
|
+
] }),
|
|
2765
|
+
payload.estimatedFeeUsd && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
|
|
2766
|
+
/* @__PURE__ */ jsx("span", { children: "Est. fee" }),
|
|
2767
|
+
/* @__PURE__ */ jsxs("span", { style: { fontWeight: 600 }, children: [
|
|
2768
|
+
"$",
|
|
2769
|
+
payload.estimatedFeeUsd
|
|
2770
|
+
] })
|
|
2771
|
+
] })
|
|
2772
|
+
] }),
|
|
2773
|
+
/* @__PURE__ */ jsx(Spinner, { label: "Waiting for passkey..." })
|
|
2774
|
+
] }) });
|
|
2775
|
+
}
|
|
2776
|
+
const currentActionType = authExecutor.currentAction?.type;
|
|
2777
|
+
const getRegistrationMessage = () => {
|
|
2778
|
+
switch (currentActionType) {
|
|
2779
|
+
case "REGISTER_PASSKEY":
|
|
2780
|
+
return {
|
|
2781
|
+
label: "Creating your passkey...",
|
|
2782
|
+
description: "Set up a passkey for secure, one-touch payments."
|
|
2783
|
+
};
|
|
2784
|
+
case "UPGRADE_SMART_ACCOUNT":
|
|
2785
|
+
return {
|
|
2786
|
+
label: "Upgrading your account...",
|
|
2787
|
+
description: "Approve the prompts in MetaMask to upgrade your account to a smart account and register your passkey. You may see two prompts."
|
|
2788
|
+
};
|
|
2789
|
+
case "GRANT_PERMISSIONS":
|
|
2790
|
+
return {
|
|
2791
|
+
label: "Setting up permissions...",
|
|
2792
|
+
description: "Signing delegation permissions. Transfer routing and gas sponsorship are handled by Swype backend."
|
|
2793
|
+
};
|
|
2794
|
+
default:
|
|
2795
|
+
return { label: "", description: "" };
|
|
2796
|
+
}
|
|
2797
|
+
};
|
|
2798
|
+
const regMsg = getRegistrationMessage();
|
|
2799
|
+
const statusLabel = creatingTransfer ? "Creating transfer..." : mobileFlow ? "Waiting for authorization..." : authExecutor.executing && regMsg.label ? regMsg.label : authExecutor.executing ? "Authorizing..." : transferSigning.signing ? "Preparing transfer..." : polling.isPolling ? "Processing payment..." : "Please wait...";
|
|
2800
|
+
const statusDescription = creatingTransfer ? "Setting up your transfer..." : mobileFlow ? "Complete the authorization in your wallet app, then return here." : authExecutor.executing && regMsg.description ? regMsg.description : authExecutor.executing ? "Complete the wallet prompts to authorize this payment." : transferSigning.signing ? "Waiting for backend to prepare your transfer payload..." : polling.isPolling ? "Your payment is being processed. This usually takes a few moments." : "Hang tight...";
|
|
1659
2801
|
return /* @__PURE__ */ jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "16px 0" }, children: [
|
|
1660
2802
|
/* @__PURE__ */ jsx(Spinner, { size: 48 }),
|
|
1661
2803
|
/* @__PURE__ */ jsx(
|
|
@@ -1699,11 +2841,11 @@ function SwypePayment({
|
|
|
1699
2841
|
},
|
|
1700
2842
|
r.actionId
|
|
1701
2843
|
)) }),
|
|
1702
|
-
(error || authExecutor.error || polling.error) && /* @__PURE__ */ jsx(
|
|
2844
|
+
(error || authExecutor.error || transferSigning.error || polling.error) && /* @__PURE__ */ jsx(
|
|
1703
2845
|
"div",
|
|
1704
2846
|
{
|
|
1705
2847
|
style: { ...errorStyle, marginTop: "16px", textAlign: "left" },
|
|
1706
|
-
children: error || authExecutor.error || polling.error
|
|
2848
|
+
children: error || authExecutor.error || transferSigning.error || polling.error
|
|
1707
2849
|
}
|
|
1708
2850
|
)
|
|
1709
2851
|
] }) });
|
|
@@ -1830,6 +2972,6 @@ function SwypePayment({
|
|
|
1830
2972
|
return null;
|
|
1831
2973
|
}
|
|
1832
2974
|
|
|
1833
|
-
export { SwypePayment, SwypeProvider, darkTheme, getTheme, lightTheme, api_exports as swypeApi, useAuthorizationExecutor, useSwypeConfig, useTransferPolling };
|
|
2975
|
+
export { SwypePayment, SwypeProvider, darkTheme, getTheme, lightTheme, api_exports as swypeApi, useAuthorizationExecutor, useSwypeConfig, useSwypeDepositAmount, useTransferPolling };
|
|
1834
2976
|
//# sourceMappingURL=index.js.map
|
|
1835
2977
|
//# sourceMappingURL=index.js.map
|