@swype-org/react-sdk 0.1.0 → 0.1.2
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 +1357 -491
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -5
- package/dist/index.d.ts +77 -5
- package/dist/index.js +1359 -494
- package/dist/index.js.map +1 -1
- package/package.json +1 -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, useAccount, useConnect, useSwitchChain, useSignTypedData,
|
|
3
|
+
import { createConfig, http, WagmiProvider, useAccount, useConnect, useSwitchChain, useSignTypedData, useWalletClient } 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 { createPublicClient, http as http$1 } from 'viem';
|
|
8
|
+
import { arbitrum as arbitrum$1, base as base$1, mainnet as mainnet$1 } from 'viem/chains';
|
|
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,8 @@ __export(api_exports, {
|
|
|
121
143
|
fetchProviders: () => fetchProviders,
|
|
122
144
|
fetchTransfer: () => fetchTransfer,
|
|
123
145
|
reportActionCompletion: () => reportActionCompletion,
|
|
124
|
-
updateUserConfig: () => updateUserConfig
|
|
146
|
+
updateUserConfig: () => updateUserConfig,
|
|
147
|
+
updateUserConfigBySession: () => updateUserConfigBySession
|
|
125
148
|
});
|
|
126
149
|
async function throwApiError(res) {
|
|
127
150
|
const body = await res.json().catch(() => null);
|
|
@@ -206,6 +229,17 @@ async function updateUserConfig(apiBaseUrl, token, config) {
|
|
|
206
229
|
});
|
|
207
230
|
if (!res.ok) await throwApiError(res);
|
|
208
231
|
}
|
|
232
|
+
async function updateUserConfigBySession(apiBaseUrl, sessionId, config) {
|
|
233
|
+
const res = await fetch(
|
|
234
|
+
`${apiBaseUrl}/v1/authorization-sessions/${sessionId}/user-config`,
|
|
235
|
+
{
|
|
236
|
+
method: "PATCH",
|
|
237
|
+
headers: { "Content-Type": "application/json" },
|
|
238
|
+
body: JSON.stringify({ config })
|
|
239
|
+
}
|
|
240
|
+
);
|
|
241
|
+
if (!res.ok) await throwApiError(res);
|
|
242
|
+
}
|
|
209
243
|
async function reportActionCompletion(apiBaseUrl, actionId, result) {
|
|
210
244
|
const res = await fetch(
|
|
211
245
|
`${apiBaseUrl}/v1/authorization-actions/${actionId}`,
|
|
@@ -218,6 +252,26 @@ async function reportActionCompletion(apiBaseUrl, actionId, result) {
|
|
|
218
252
|
if (!res.ok) await throwApiError(res);
|
|
219
253
|
return await res.json();
|
|
220
254
|
}
|
|
255
|
+
var VIEM_CHAINS = {
|
|
256
|
+
1: mainnet$1,
|
|
257
|
+
8453: base$1,
|
|
258
|
+
42161: arbitrum$1
|
|
259
|
+
};
|
|
260
|
+
var chainClientCache = /* @__PURE__ */ new Map();
|
|
261
|
+
function getPublicClientForChain(numericChainId) {
|
|
262
|
+
const existing = chainClientCache.get(numericChainId);
|
|
263
|
+
if (existing) return existing;
|
|
264
|
+
const viemChain = VIEM_CHAINS[numericChainId];
|
|
265
|
+
if (!viemChain) {
|
|
266
|
+
throw new Error(`Unsupported chain ID: ${numericChainId}`);
|
|
267
|
+
}
|
|
268
|
+
const client = createPublicClient({
|
|
269
|
+
chain: viemChain,
|
|
270
|
+
transport: http$1()
|
|
271
|
+
});
|
|
272
|
+
chainClientCache.set(numericChainId, client);
|
|
273
|
+
return client;
|
|
274
|
+
}
|
|
221
275
|
function useTransferPolling(intervalMs = 3e3) {
|
|
222
276
|
const { apiBaseUrl } = useSwypeConfig();
|
|
223
277
|
const { getAccessToken } = usePrivy();
|
|
@@ -272,12 +326,30 @@ function useAuthorizationExecutor() {
|
|
|
272
326
|
const { connectAsync, connectors } = useConnect();
|
|
273
327
|
const { switchChainAsync } = useSwitchChain();
|
|
274
328
|
const { signTypedDataAsync } = useSignTypedData();
|
|
275
|
-
const publicClient = usePublicClient();
|
|
276
329
|
const { data: walletClient } = useWalletClient();
|
|
277
330
|
const [executing, setExecuting] = useState(false);
|
|
278
331
|
const [results, setResults] = useState([]);
|
|
279
332
|
const [error, setError] = useState(null);
|
|
280
333
|
const executingRef = useRef(false);
|
|
334
|
+
const [pendingSelectSource, setPendingSelectSource] = useState(null);
|
|
335
|
+
const selectSourceResolverRef = useRef(null);
|
|
336
|
+
const resolveSelectSource = useCallback((selection) => {
|
|
337
|
+
if (selectSourceResolverRef.current) {
|
|
338
|
+
selectSourceResolverRef.current(selection);
|
|
339
|
+
selectSourceResolverRef.current = null;
|
|
340
|
+
setPendingSelectSource(null);
|
|
341
|
+
}
|
|
342
|
+
}, []);
|
|
343
|
+
const [pendingAllowanceSelection, setPendingAllowanceSelection] = useState(null);
|
|
344
|
+
const allowanceSelectionResolverRef = useRef(null);
|
|
345
|
+
const sessionIdRef = useRef(null);
|
|
346
|
+
const resolveAllowanceSelection = useCallback((selection) => {
|
|
347
|
+
if (allowanceSelectionResolverRef.current) {
|
|
348
|
+
allowanceSelectionResolverRef.current(selection);
|
|
349
|
+
allowanceSelectionResolverRef.current = null;
|
|
350
|
+
setPendingAllowanceSelection(null);
|
|
351
|
+
}
|
|
352
|
+
}, []);
|
|
281
353
|
const executeOpenProvider = useCallback(
|
|
282
354
|
async (action) => {
|
|
283
355
|
try {
|
|
@@ -321,6 +393,49 @@ function useAuthorizationExecutor() {
|
|
|
321
393
|
},
|
|
322
394
|
[isConnected, address, currentChainId, connectors, connectAsync]
|
|
323
395
|
);
|
|
396
|
+
const executeSelectSource = useCallback(
|
|
397
|
+
async (action) => {
|
|
398
|
+
try {
|
|
399
|
+
const options = action.metadata?.options;
|
|
400
|
+
const recommended = action.metadata?.recommended;
|
|
401
|
+
if (!options || options.length <= 1) {
|
|
402
|
+
const selection2 = recommended ?? { chainName: "Base", tokenSymbol: "USDC" };
|
|
403
|
+
return {
|
|
404
|
+
actionId: action.id,
|
|
405
|
+
type: action.type,
|
|
406
|
+
status: "success",
|
|
407
|
+
message: `Auto-selected ${selection2.tokenSymbol} on ${selection2.chainName}.`,
|
|
408
|
+
data: {
|
|
409
|
+
selectedChainName: selection2.chainName,
|
|
410
|
+
selectedTokenSymbol: selection2.tokenSymbol
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
const selection = await new Promise((resolve) => {
|
|
415
|
+
selectSourceResolverRef.current = resolve;
|
|
416
|
+
setPendingSelectSource(action);
|
|
417
|
+
});
|
|
418
|
+
return {
|
|
419
|
+
actionId: action.id,
|
|
420
|
+
type: action.type,
|
|
421
|
+
status: "success",
|
|
422
|
+
message: `Selected ${selection.tokenSymbol} on ${selection.chainName}.`,
|
|
423
|
+
data: {
|
|
424
|
+
selectedChainName: selection.chainName,
|
|
425
|
+
selectedTokenSymbol: selection.tokenSymbol
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
} catch (err) {
|
|
429
|
+
return {
|
|
430
|
+
actionId: action.id,
|
|
431
|
+
type: action.type,
|
|
432
|
+
status: "error",
|
|
433
|
+
message: err instanceof Error ? err.message : "Failed to select source"
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
[]
|
|
438
|
+
);
|
|
324
439
|
const executeSwitchChain = useCallback(
|
|
325
440
|
async (action) => {
|
|
326
441
|
try {
|
|
@@ -334,8 +449,17 @@ function useAuthorizationExecutor() {
|
|
|
334
449
|
};
|
|
335
450
|
}
|
|
336
451
|
const targetChainIdNum = parseInt(targetChainIdHex, 16);
|
|
337
|
-
await switchChainAsync({ chainId: targetChainIdNum });
|
|
338
452
|
const hexChainId = `0x${targetChainIdNum.toString(16)}`;
|
|
453
|
+
if (currentChainId === targetChainIdNum) {
|
|
454
|
+
return {
|
|
455
|
+
actionId: action.id,
|
|
456
|
+
type: action.type,
|
|
457
|
+
status: "success",
|
|
458
|
+
message: `Already on chain ${hexChainId}. Skipped.`,
|
|
459
|
+
data: { chainId: hexChainId, switched: false }
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
await switchChainAsync({ chainId: targetChainIdNum });
|
|
339
463
|
return {
|
|
340
464
|
actionId: action.id,
|
|
341
465
|
type: action.type,
|
|
@@ -352,13 +476,14 @@ function useAuthorizationExecutor() {
|
|
|
352
476
|
};
|
|
353
477
|
}
|
|
354
478
|
},
|
|
355
|
-
[switchChainAsync]
|
|
479
|
+
[currentChainId, switchChainAsync]
|
|
356
480
|
);
|
|
357
481
|
const executeApprovePermit2 = useCallback(
|
|
358
482
|
async (action) => {
|
|
359
483
|
try {
|
|
360
484
|
const tokenAddress = action.metadata?.tokenAddress;
|
|
361
485
|
const permit2Address = action.metadata?.permit2Address;
|
|
486
|
+
const metadataChainId = action.metadata?.chainId;
|
|
362
487
|
if (!tokenAddress || !permit2Address) {
|
|
363
488
|
return {
|
|
364
489
|
actionId: action.id,
|
|
@@ -397,21 +522,26 @@ function useAuthorizationExecutor() {
|
|
|
397
522
|
outputs: [{ name: "", type: "bool" }]
|
|
398
523
|
}
|
|
399
524
|
];
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
525
|
+
const targetChainIdNum = metadataChainId ? parseInt(metadataChainId, 16) : currentChainId;
|
|
526
|
+
const chainClient = targetChainIdNum ? getPublicClientForChain(targetChainIdNum) : void 0;
|
|
527
|
+
if (chainClient) {
|
|
528
|
+
try {
|
|
529
|
+
const currentAllowance = await chainClient.readContract({
|
|
530
|
+
address: tokenAddress,
|
|
531
|
+
abi: ERC20_ABI,
|
|
532
|
+
functionName: "allowance",
|
|
533
|
+
args: [address, permit2Address]
|
|
534
|
+
});
|
|
535
|
+
if (currentAllowance > 0n) {
|
|
536
|
+
return {
|
|
537
|
+
actionId: action.id,
|
|
538
|
+
type: action.type,
|
|
539
|
+
status: "success",
|
|
540
|
+
message: `Permit2 already approved (allowance: ${currentAllowance.toString()}). Skipped.`,
|
|
541
|
+
data: { skipped: true, existingAllowance: currentAllowance.toString() }
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
} catch {
|
|
415
545
|
}
|
|
416
546
|
}
|
|
417
547
|
if (!walletClient) {
|
|
@@ -429,8 +559,8 @@ function useAuthorizationExecutor() {
|
|
|
429
559
|
functionName: "approve",
|
|
430
560
|
args: [permit2Address, MAX_UINT256]
|
|
431
561
|
});
|
|
432
|
-
if (
|
|
433
|
-
await
|
|
562
|
+
if (chainClient) {
|
|
563
|
+
await chainClient.waitForTransactionReceipt({ hash: txHash });
|
|
434
564
|
}
|
|
435
565
|
return {
|
|
436
566
|
actionId: action.id,
|
|
@@ -448,7 +578,7 @@ function useAuthorizationExecutor() {
|
|
|
448
578
|
};
|
|
449
579
|
}
|
|
450
580
|
},
|
|
451
|
-
[address,
|
|
581
|
+
[address, currentChainId, walletClient]
|
|
452
582
|
);
|
|
453
583
|
const executeSignPermit2 = useCallback(
|
|
454
584
|
async (action) => {
|
|
@@ -483,34 +613,55 @@ function useAuthorizationExecutor() {
|
|
|
483
613
|
message: "Missing spenderAddress or tokenAddress in action metadata."
|
|
484
614
|
};
|
|
485
615
|
}
|
|
486
|
-
|
|
616
|
+
const permit2ChainId = metadataChainId ? parseInt(metadataChainId, 16) : currentChainId;
|
|
617
|
+
const chainClient = permit2ChainId ? getPublicClientForChain(permit2ChainId) : void 0;
|
|
618
|
+
let onChainNonce;
|
|
619
|
+
if (chainClient && address) {
|
|
487
620
|
try {
|
|
488
|
-
const [existingAmount, existingExpiration] = await
|
|
621
|
+
const [existingAmount, existingExpiration, chainNonce] = await chainClient.readContract({
|
|
489
622
|
address: PERMIT2_ADDRESS,
|
|
490
623
|
abi: PERMIT2_ALLOWANCE_ABI,
|
|
491
624
|
functionName: "allowance",
|
|
492
625
|
args: [address, tokenAddress, spenderAddress]
|
|
493
626
|
});
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
627
|
+
onChainNonce = chainNonce;
|
|
628
|
+
if (metadataAmount) {
|
|
629
|
+
const requiredSmallestUnit = BigInt(metadataAmount);
|
|
630
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
631
|
+
if (existingAmount >= requiredSmallestUnit && existingExpiration > now) {
|
|
632
|
+
return {
|
|
633
|
+
actionId: action.id,
|
|
634
|
+
type: action.type,
|
|
635
|
+
status: "success",
|
|
636
|
+
message: `Permit2 allowance already sufficient (${existingAmount.toString()}). Skipped.`,
|
|
637
|
+
data: { skipped: true, existingAllowance: existingAmount.toString() }
|
|
638
|
+
};
|
|
639
|
+
}
|
|
506
640
|
}
|
|
507
641
|
} catch {
|
|
508
642
|
}
|
|
509
643
|
}
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
644
|
+
const allowanceSelection = await new Promise((resolve) => {
|
|
645
|
+
allowanceSelectionResolverRef.current = resolve;
|
|
646
|
+
setPendingAllowanceSelection(action);
|
|
647
|
+
});
|
|
648
|
+
if (allowanceSelection.topUpAmount > 0 && sessionIdRef.current) {
|
|
649
|
+
try {
|
|
650
|
+
await updateUserConfigBySession(
|
|
651
|
+
apiBaseUrl,
|
|
652
|
+
sessionIdRef.current,
|
|
653
|
+
{ defaultAllowance: allowanceSelection.topUpAmount }
|
|
654
|
+
);
|
|
655
|
+
} catch {
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
const tokenDecimals = Number(action.metadata?.tokenDecimals ?? 6);
|
|
659
|
+
const topUpSmallestUnit = BigInt(
|
|
660
|
+
Math.round(allowanceSelection.topUpAmount * 10 ** tokenDecimals)
|
|
661
|
+
);
|
|
662
|
+
const baseAmount = metadataAmount ? BigInt(metadataAmount) : BigInt(0);
|
|
663
|
+
const permitAmount = baseAmount + topUpSmallestUnit;
|
|
664
|
+
const nonce = onChainNonce ?? Number(action.metadata?.nonce ?? 0);
|
|
514
665
|
const sigDeadline = BigInt(Math.floor(Date.now() / 1e3) + 3600);
|
|
515
666
|
const expiration = Math.floor(Date.now() / 1e3) + 30 * 24 * 60 * 60;
|
|
516
667
|
const signature = await signTypedDataAsync({
|
|
@@ -567,13 +718,15 @@ function useAuthorizationExecutor() {
|
|
|
567
718
|
};
|
|
568
719
|
}
|
|
569
720
|
},
|
|
570
|
-
[address, currentChainId,
|
|
721
|
+
[address, currentChainId, signTypedDataAsync, apiBaseUrl]
|
|
571
722
|
);
|
|
572
723
|
const executeAction = useCallback(
|
|
573
724
|
async (action) => {
|
|
574
725
|
switch (action.type) {
|
|
575
726
|
case "OPEN_PROVIDER":
|
|
576
727
|
return executeOpenProvider(action);
|
|
728
|
+
case "SELECT_SOURCE":
|
|
729
|
+
return executeSelectSource(action);
|
|
577
730
|
case "SWITCH_CHAIN":
|
|
578
731
|
return executeSwitchChain(action);
|
|
579
732
|
case "APPROVE_PERMIT_2":
|
|
@@ -589,7 +742,7 @@ function useAuthorizationExecutor() {
|
|
|
589
742
|
};
|
|
590
743
|
}
|
|
591
744
|
},
|
|
592
|
-
[executeOpenProvider, executeSwitchChain, executeApprovePermit2, executeSignPermit2]
|
|
745
|
+
[executeOpenProvider, executeSelectSource, executeSwitchChain, executeApprovePermit2, executeSignPermit2]
|
|
593
746
|
);
|
|
594
747
|
const executeSession = useCallback(
|
|
595
748
|
async (transfer) => {
|
|
@@ -601,6 +754,7 @@ function useAuthorizationExecutor() {
|
|
|
601
754
|
return;
|
|
602
755
|
}
|
|
603
756
|
const sessionId = transfer.authorizationSessions[0].id;
|
|
757
|
+
sessionIdRef.current = sessionId;
|
|
604
758
|
setExecuting(true);
|
|
605
759
|
setError(null);
|
|
606
760
|
setResults([]);
|
|
@@ -609,6 +763,19 @@ function useAuthorizationExecutor() {
|
|
|
609
763
|
const allResults = [];
|
|
610
764
|
const completedActionIds = /* @__PURE__ */ new Set();
|
|
611
765
|
let pendingActions = currentSession.actions.filter((a) => a.status === "PENDING").sort((a, b) => a.orderIndex - b.orderIndex);
|
|
766
|
+
const ACTION_POLL_INTERVAL_MS = 500;
|
|
767
|
+
const ACTION_POLL_MAX_RETRIES = 20;
|
|
768
|
+
let actionPollRetries = 0;
|
|
769
|
+
while (pendingActions.length === 0 && currentSession.status !== "AUTHORIZED" && actionPollRetries < ACTION_POLL_MAX_RETRIES) {
|
|
770
|
+
await new Promise((r) => setTimeout(r, ACTION_POLL_INTERVAL_MS));
|
|
771
|
+
currentSession = await fetchAuthorizationSession(apiBaseUrl, sessionId);
|
|
772
|
+
pendingActions = currentSession.actions.filter((a) => a.status === "PENDING").sort((a, b) => a.orderIndex - b.orderIndex);
|
|
773
|
+
actionPollRetries++;
|
|
774
|
+
}
|
|
775
|
+
if (pendingActions.length === 0 && currentSession.status !== "AUTHORIZED") {
|
|
776
|
+
setError("Authorization actions were not created in time. Please try again.");
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
612
779
|
while (pendingActions.length > 0) {
|
|
613
780
|
const action = pendingActions[0];
|
|
614
781
|
if (completedActionIds.has(action.id)) break;
|
|
@@ -668,7 +835,16 @@ function useAuthorizationExecutor() {
|
|
|
668
835
|
},
|
|
669
836
|
[apiBaseUrl, executeAction]
|
|
670
837
|
);
|
|
671
|
-
return {
|
|
838
|
+
return {
|
|
839
|
+
executing,
|
|
840
|
+
results,
|
|
841
|
+
error,
|
|
842
|
+
pendingSelectSource,
|
|
843
|
+
resolveSelectSource,
|
|
844
|
+
pendingAllowanceSelection,
|
|
845
|
+
resolveAllowanceSelection,
|
|
846
|
+
executeSession
|
|
847
|
+
};
|
|
672
848
|
}
|
|
673
849
|
function Spinner({ size = 40, label }) {
|
|
674
850
|
const { tokens } = useSwypeConfig();
|
|
@@ -786,163 +962,232 @@ function ProviderCard({ provider, selected, onClick }) {
|
|
|
786
962
|
}
|
|
787
963
|
);
|
|
788
964
|
}
|
|
789
|
-
function
|
|
965
|
+
function AccountDropdown({
|
|
790
966
|
accounts,
|
|
791
|
-
|
|
792
|
-
onSelect
|
|
967
|
+
selectedAccountId,
|
|
968
|
+
onSelect,
|
|
969
|
+
selectedWalletId,
|
|
970
|
+
onWalletSelect
|
|
793
971
|
}) {
|
|
794
972
|
const { tokens } = useSwypeConfig();
|
|
795
|
-
const [
|
|
796
|
-
const
|
|
797
|
-
|
|
973
|
+
const [open, setOpen] = useState(false);
|
|
974
|
+
const containerRef = useRef(null);
|
|
975
|
+
const selected = accounts.find((a) => a.id === selectedAccountId);
|
|
976
|
+
const selectedWallet = selected?.wallets.find(
|
|
977
|
+
(w) => w.id === selectedWalletId
|
|
798
978
|
);
|
|
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
|
-
);
|
|
979
|
+
useEffect(() => {
|
|
980
|
+
if (!open) return;
|
|
981
|
+
const handleClick = (e) => {
|
|
982
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
983
|
+
setOpen(false);
|
|
828
984
|
}
|
|
985
|
+
};
|
|
986
|
+
document.addEventListener("mousedown", handleClick);
|
|
987
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
988
|
+
}, [open]);
|
|
989
|
+
if (accounts.length === 0) return null;
|
|
990
|
+
const hasMultipleChoices = accounts.length > 1 || accounts.length === 1 && onWalletSelect && accounts[0].wallets.filter((w) => w.balance.available.amount > 0).length > 1;
|
|
991
|
+
if (!hasMultipleChoices) {
|
|
992
|
+
return /* @__PURE__ */ jsxs(
|
|
993
|
+
"div",
|
|
994
|
+
{
|
|
995
|
+
style: {
|
|
996
|
+
display: "flex",
|
|
997
|
+
alignItems: "center",
|
|
998
|
+
gap: "6px",
|
|
999
|
+
fontSize: "0.85rem",
|
|
1000
|
+
color: tokens.textSecondary
|
|
1001
|
+
},
|
|
1002
|
+
children: [
|
|
1003
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: accounts[0].name }),
|
|
1004
|
+
(selectedWallet ?? accounts[0].wallets[0]) && /* @__PURE__ */ jsx(
|
|
1005
|
+
"span",
|
|
1006
|
+
{
|
|
1007
|
+
style: {
|
|
1008
|
+
fontSize: "0.75rem",
|
|
1009
|
+
color: tokens.textMuted,
|
|
1010
|
+
fontFamily: '"SF Mono", "Fira Code", monospace'
|
|
1011
|
+
},
|
|
1012
|
+
children: selectedWallet ? `${selectedWallet.chain.name} \xB7 ${selectedWallet.name}` : accounts[0].wallets[0]?.name
|
|
1013
|
+
}
|
|
1014
|
+
)
|
|
1015
|
+
]
|
|
1016
|
+
}
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
const getAccountBalance = (account) => {
|
|
1020
|
+
let total = 0;
|
|
1021
|
+
for (const w of account.wallets) {
|
|
1022
|
+
total += w.balance.available.amount;
|
|
829
1023
|
}
|
|
830
|
-
|
|
831
|
-
return `${wallet.balance.available.amount.toFixed(2)} ${wallet.balance.available.currency}`;
|
|
832
|
-
}
|
|
833
|
-
return parts.join(", ") || "No balance";
|
|
1024
|
+
return total > 0 ? `$${total.toFixed(2)}` : "";
|
|
834
1025
|
};
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
1026
|
+
const hasActiveWallet = (account) => account.wallets.some((w) => w.status === "ACTIVE");
|
|
1027
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, style: { position: "relative" }, children: [
|
|
1028
|
+
/* @__PURE__ */ jsxs(
|
|
1029
|
+
"button",
|
|
838
1030
|
{
|
|
1031
|
+
onClick: () => setOpen(!open),
|
|
839
1032
|
style: {
|
|
840
|
-
display: "
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
1033
|
+
display: "flex",
|
|
1034
|
+
alignItems: "center",
|
|
1035
|
+
gap: "6px",
|
|
1036
|
+
background: "transparent",
|
|
1037
|
+
border: "none",
|
|
1038
|
+
cursor: "pointer",
|
|
1039
|
+
padding: "4px 0",
|
|
1040
|
+
color: tokens.textSecondary,
|
|
1041
|
+
fontFamily: "inherit",
|
|
1042
|
+
fontSize: "0.85rem",
|
|
1043
|
+
outline: "none"
|
|
847
1044
|
},
|
|
848
|
-
children:
|
|
1045
|
+
children: [
|
|
1046
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500, color: tokens.text }, children: selected?.name ?? "Select account" }),
|
|
1047
|
+
(selectedWallet ?? selected?.wallets?.[0]) && /* @__PURE__ */ jsx(
|
|
1048
|
+
"span",
|
|
1049
|
+
{
|
|
1050
|
+
style: {
|
|
1051
|
+
fontSize: "0.75rem",
|
|
1052
|
+
color: tokens.textMuted,
|
|
1053
|
+
fontFamily: '"SF Mono", "Fira Code", monospace'
|
|
1054
|
+
},
|
|
1055
|
+
children: selectedWallet ? `${selectedWallet.chain.name} \xB7 ${selectedWallet.name}` : selected.wallets[0].name
|
|
1056
|
+
}
|
|
1057
|
+
),
|
|
1058
|
+
/* @__PURE__ */ jsx(
|
|
1059
|
+
"svg",
|
|
1060
|
+
{
|
|
1061
|
+
width: "12",
|
|
1062
|
+
height: "12",
|
|
1063
|
+
viewBox: "0 0 24 24",
|
|
1064
|
+
fill: "none",
|
|
1065
|
+
style: {
|
|
1066
|
+
transform: open ? "rotate(180deg)" : "rotate(0deg)",
|
|
1067
|
+
transition: "transform 0.15s ease",
|
|
1068
|
+
flexShrink: 0
|
|
1069
|
+
},
|
|
1070
|
+
children: /* @__PURE__ */ jsx(
|
|
1071
|
+
"path",
|
|
1072
|
+
{
|
|
1073
|
+
d: "M7 10l5 5 5-5",
|
|
1074
|
+
stroke: tokens.textMuted,
|
|
1075
|
+
strokeWidth: "2",
|
|
1076
|
+
strokeLinecap: "round",
|
|
1077
|
+
strokeLinejoin: "round"
|
|
1078
|
+
}
|
|
1079
|
+
)
|
|
1080
|
+
}
|
|
1081
|
+
)
|
|
1082
|
+
]
|
|
849
1083
|
}
|
|
850
1084
|
),
|
|
851
|
-
/* @__PURE__ */ jsx(
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
1085
|
+
open && /* @__PURE__ */ jsx(
|
|
1086
|
+
"div",
|
|
1087
|
+
{
|
|
1088
|
+
style: {
|
|
1089
|
+
position: "absolute",
|
|
1090
|
+
top: "100%",
|
|
1091
|
+
left: 0,
|
|
1092
|
+
right: 0,
|
|
1093
|
+
marginTop: "4px",
|
|
1094
|
+
background: tokens.bgCard,
|
|
1095
|
+
border: `1px solid ${tokens.border}`,
|
|
1096
|
+
borderRadius: tokens.radius,
|
|
1097
|
+
boxShadow: tokens.shadowLg,
|
|
1098
|
+
zIndex: 50,
|
|
1099
|
+
overflow: "hidden",
|
|
1100
|
+
minWidth: "220px"
|
|
1101
|
+
},
|
|
1102
|
+
children: accounts.map((account) => {
|
|
1103
|
+
const isAcctSelected = account.id === selectedAccountId;
|
|
1104
|
+
const balance = getAccountBalance(account);
|
|
1105
|
+
const active = hasActiveWallet(account);
|
|
1106
|
+
const walletsWithBalance = account.wallets.filter(
|
|
1107
|
+
(w) => w.balance.available.amount > 0
|
|
1108
|
+
);
|
|
1109
|
+
const showWallets = onWalletSelect && walletsWithBalance.length > 0;
|
|
1110
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
865
1111
|
/* @__PURE__ */ jsxs(
|
|
866
1112
|
"button",
|
|
867
1113
|
{
|
|
868
|
-
onClick: () =>
|
|
1114
|
+
onClick: () => {
|
|
1115
|
+
onSelect(account.id);
|
|
1116
|
+
if (!showWallets) setOpen(false);
|
|
1117
|
+
},
|
|
869
1118
|
style: {
|
|
870
|
-
width: "100%",
|
|
871
1119
|
display: "flex",
|
|
872
1120
|
alignItems: "center",
|
|
873
1121
|
justifyContent: "space-between",
|
|
874
|
-
|
|
875
|
-
|
|
1122
|
+
width: "100%",
|
|
1123
|
+
padding: "10px 14px",
|
|
1124
|
+
background: isAcctSelected && !selectedWalletId ? tokens.accent + "12" : "transparent",
|
|
876
1125
|
border: "none",
|
|
1126
|
+
borderBottom: showWallets ? "none" : `1px solid ${tokens.border}`,
|
|
877
1127
|
cursor: "pointer",
|
|
878
1128
|
color: tokens.text,
|
|
879
1129
|
fontFamily: "inherit",
|
|
880
|
-
fontSize: "0.
|
|
881
|
-
fontWeight: 500,
|
|
1130
|
+
fontSize: "0.85rem",
|
|
882
1131
|
textAlign: "left",
|
|
883
1132
|
outline: "none",
|
|
884
|
-
transition: "background 0.
|
|
1133
|
+
transition: "background 0.1s ease"
|
|
885
1134
|
},
|
|
886
1135
|
children: [
|
|
887
|
-
/* @__PURE__ */ jsxs("div", { style: {
|
|
888
|
-
/* @__PURE__ */
|
|
1136
|
+
/* @__PURE__ */ jsxs("div", { style: { minWidth: 0, flex: 1 }, children: [
|
|
1137
|
+
/* @__PURE__ */ jsxs(
|
|
889
1138
|
"div",
|
|
890
1139
|
{
|
|
891
1140
|
style: {
|
|
892
|
-
width: 28,
|
|
893
|
-
height: 28,
|
|
894
|
-
borderRadius: "6px",
|
|
895
|
-
background: tokens.accent + "25",
|
|
896
1141
|
display: "flex",
|
|
897
1142
|
alignItems: "center",
|
|
898
|
-
|
|
899
|
-
fontSize: "0.75rem",
|
|
900
|
-
fontWeight: 700,
|
|
901
|
-
color: tokens.accent,
|
|
902
|
-
flexShrink: 0
|
|
1143
|
+
gap: "6px"
|
|
903
1144
|
},
|
|
904
|
-
children:
|
|
1145
|
+
children: [
|
|
1146
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: account.name }),
|
|
1147
|
+
active && /* @__PURE__ */ jsx(
|
|
1148
|
+
"span",
|
|
1149
|
+
{
|
|
1150
|
+
style: {
|
|
1151
|
+
fontSize: "0.6rem",
|
|
1152
|
+
fontWeight: 600,
|
|
1153
|
+
color: tokens.success,
|
|
1154
|
+
background: tokens.successBg,
|
|
1155
|
+
padding: "1px 5px",
|
|
1156
|
+
borderRadius: "3px",
|
|
1157
|
+
textTransform: "uppercase",
|
|
1158
|
+
letterSpacing: "0.03em"
|
|
1159
|
+
},
|
|
1160
|
+
children: "Active"
|
|
1161
|
+
}
|
|
1162
|
+
)
|
|
1163
|
+
]
|
|
905
1164
|
}
|
|
906
1165
|
),
|
|
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
|
-
] })
|
|
1166
|
+
balance && /* @__PURE__ */ jsx(
|
|
1167
|
+
"div",
|
|
1168
|
+
{
|
|
1169
|
+
style: {
|
|
1170
|
+
fontSize: "0.75rem",
|
|
1171
|
+
color: tokens.textMuted,
|
|
1172
|
+
marginTop: "2px"
|
|
1173
|
+
},
|
|
1174
|
+
children: balance
|
|
1175
|
+
}
|
|
1176
|
+
)
|
|
925
1177
|
] }),
|
|
926
|
-
/* @__PURE__ */ jsx(
|
|
1178
|
+
isAcctSelected && !selectedWalletId && /* @__PURE__ */ jsx(
|
|
927
1179
|
"svg",
|
|
928
1180
|
{
|
|
929
1181
|
width: "14",
|
|
930
1182
|
height: "14",
|
|
931
1183
|
viewBox: "0 0 24 24",
|
|
932
1184
|
fill: "none",
|
|
933
|
-
style: {
|
|
934
|
-
transform: isExpanded ? "rotate(180deg)" : "rotate(0deg)",
|
|
935
|
-
transition: "transform 0.2s ease",
|
|
936
|
-
flexShrink: 0
|
|
937
|
-
},
|
|
1185
|
+
style: { flexShrink: 0, marginLeft: "8px" },
|
|
938
1186
|
children: /* @__PURE__ */ jsx(
|
|
939
1187
|
"path",
|
|
940
1188
|
{
|
|
941
|
-
d: "
|
|
942
|
-
|
|
943
|
-
strokeWidth: "2",
|
|
944
|
-
strokeLinecap: "round",
|
|
945
|
-
strokeLinejoin: "round"
|
|
1189
|
+
d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
|
|
1190
|
+
fill: tokens.accent
|
|
946
1191
|
}
|
|
947
1192
|
)
|
|
948
1193
|
}
|
|
@@ -950,202 +1195,720 @@ function AccountWalletSelector({
|
|
|
950
1195
|
]
|
|
951
1196
|
}
|
|
952
1197
|
),
|
|
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
|
-
|
|
1198
|
+
showWallets && walletsWithBalance.map((wallet, wIdx) => {
|
|
1199
|
+
const isWalletSelected = isAcctSelected && wallet.id === selectedWalletId;
|
|
1200
|
+
const walletBal = wallet.balance.available.amount > 0 ? `$${wallet.balance.available.amount.toFixed(2)}` : "";
|
|
1201
|
+
const isLastWallet = wIdx === walletsWithBalance.length - 1;
|
|
1202
|
+
return /* @__PURE__ */ jsxs(
|
|
1203
|
+
"button",
|
|
1204
|
+
{
|
|
1205
|
+
onClick: () => {
|
|
1206
|
+
onWalletSelect(account.id, wallet.id);
|
|
1207
|
+
setOpen(false);
|
|
1208
|
+
},
|
|
1209
|
+
style: {
|
|
1210
|
+
display: "flex",
|
|
1211
|
+
alignItems: "center",
|
|
1212
|
+
justifyContent: "space-between",
|
|
1213
|
+
width: "100%",
|
|
1214
|
+
padding: "8px 14px 8px 28px",
|
|
1215
|
+
background: isWalletSelected ? tokens.accent + "12" : "transparent",
|
|
1216
|
+
border: "none",
|
|
1217
|
+
borderBottom: isLastWallet ? `1px solid ${tokens.border}` : "none",
|
|
1218
|
+
cursor: "pointer",
|
|
1219
|
+
color: tokens.text,
|
|
1220
|
+
fontFamily: "inherit",
|
|
1221
|
+
fontSize: "0.8rem",
|
|
1222
|
+
textAlign: "left",
|
|
1223
|
+
outline: "none",
|
|
1224
|
+
transition: "background 0.1s ease"
|
|
1225
|
+
},
|
|
1226
|
+
children: [
|
|
1227
|
+
/* @__PURE__ */ jsxs(
|
|
1228
|
+
"div",
|
|
1229
|
+
{
|
|
1230
|
+
style: {
|
|
1231
|
+
display: "flex",
|
|
1232
|
+
alignItems: "center",
|
|
1233
|
+
gap: "6px",
|
|
1234
|
+
minWidth: 0,
|
|
1235
|
+
flex: 1
|
|
1236
|
+
},
|
|
1237
|
+
children: [
|
|
1238
|
+
/* @__PURE__ */ jsx(
|
|
1239
|
+
"span",
|
|
987
1240
|
{
|
|
988
1241
|
style: {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
gap: "6px"
|
|
1242
|
+
fontWeight: 500,
|
|
1243
|
+
fontSize: "0.8rem"
|
|
992
1244
|
},
|
|
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
|
-
]
|
|
1245
|
+
children: wallet.chain.name
|
|
1009
1246
|
}
|
|
1010
1247
|
),
|
|
1011
1248
|
/* @__PURE__ */ jsx(
|
|
1012
|
-
"
|
|
1249
|
+
"span",
|
|
1013
1250
|
{
|
|
1014
1251
|
style: {
|
|
1015
|
-
fontSize: "0.
|
|
1016
|
-
color: tokens.
|
|
1017
|
-
|
|
1252
|
+
fontSize: "0.7rem",
|
|
1253
|
+
color: tokens.textMuted,
|
|
1254
|
+
fontFamily: '"SF Mono", "Fira Code", monospace'
|
|
1018
1255
|
},
|
|
1019
|
-
children:
|
|
1256
|
+
children: wallet.name
|
|
1257
|
+
}
|
|
1258
|
+
),
|
|
1259
|
+
walletBal && /* @__PURE__ */ jsx(
|
|
1260
|
+
"span",
|
|
1261
|
+
{
|
|
1262
|
+
style: {
|
|
1263
|
+
fontSize: "0.7rem",
|
|
1264
|
+
color: tokens.textMuted,
|
|
1265
|
+
marginLeft: "auto"
|
|
1266
|
+
},
|
|
1267
|
+
children: walletBal
|
|
1020
1268
|
}
|
|
1021
1269
|
)
|
|
1022
|
-
]
|
|
1023
|
-
|
|
1024
|
-
|
|
1270
|
+
]
|
|
1271
|
+
}
|
|
1272
|
+
),
|
|
1273
|
+
isWalletSelected && /* @__PURE__ */ jsx(
|
|
1274
|
+
"svg",
|
|
1275
|
+
{
|
|
1276
|
+
width: "12",
|
|
1277
|
+
height: "12",
|
|
1278
|
+
viewBox: "0 0 24 24",
|
|
1279
|
+
fill: "none",
|
|
1280
|
+
style: {
|
|
1281
|
+
flexShrink: 0,
|
|
1282
|
+
marginLeft: "8px"
|
|
1283
|
+
},
|
|
1284
|
+
children: /* @__PURE__ */ jsx(
|
|
1285
|
+
"path",
|
|
1025
1286
|
{
|
|
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
|
-
)
|
|
1287
|
+
d: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z",
|
|
1288
|
+
fill: tokens.accent
|
|
1038
1289
|
}
|
|
1039
1290
|
)
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
)
|
|
1047
|
-
]
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1291
|
+
}
|
|
1292
|
+
)
|
|
1293
|
+
]
|
|
1294
|
+
},
|
|
1295
|
+
wallet.id
|
|
1296
|
+
);
|
|
1297
|
+
})
|
|
1298
|
+
] }, account.id);
|
|
1299
|
+
})
|
|
1300
|
+
}
|
|
1301
|
+
)
|
|
1302
|
+
] });
|
|
1303
|
+
}
|
|
1304
|
+
var ASSETS = ["USDC", "USDT"];
|
|
1305
|
+
function AdvancedSettings({
|
|
1306
|
+
settings,
|
|
1307
|
+
onChange,
|
|
1308
|
+
chains,
|
|
1309
|
+
providers,
|
|
1310
|
+
onConnectNewAccount,
|
|
1311
|
+
connectingNewAccount
|
|
1312
|
+
}) {
|
|
1313
|
+
const { tokens } = useSwypeConfig();
|
|
1314
|
+
const [open, setOpen] = useState(false);
|
|
1315
|
+
const [showProviders, setShowProviders] = useState(false);
|
|
1316
|
+
return /* @__PURE__ */ jsxs("div", { style: { marginTop: "12px" }, children: [
|
|
1317
|
+
/* @__PURE__ */ jsxs(
|
|
1318
|
+
"button",
|
|
1054
1319
|
{
|
|
1320
|
+
onClick: () => setOpen(!open),
|
|
1055
1321
|
style: {
|
|
1056
|
-
marginTop: "8px",
|
|
1057
|
-
fontSize: "0.8rem",
|
|
1058
|
-
color: tokens.accent,
|
|
1059
1322
|
display: "flex",
|
|
1060
1323
|
alignItems: "center",
|
|
1061
|
-
gap: "6px"
|
|
1324
|
+
gap: "6px",
|
|
1325
|
+
background: "transparent",
|
|
1326
|
+
border: "none",
|
|
1327
|
+
cursor: "pointer",
|
|
1328
|
+
padding: "4px 0",
|
|
1329
|
+
color: tokens.textMuted,
|
|
1330
|
+
fontFamily: "inherit",
|
|
1331
|
+
fontSize: "0.8rem",
|
|
1332
|
+
fontWeight: 500,
|
|
1333
|
+
outline: "none",
|
|
1334
|
+
letterSpacing: "0.02em"
|
|
1062
1335
|
},
|
|
1063
1336
|
children: [
|
|
1064
|
-
/* @__PURE__ */ jsx(
|
|
1065
|
-
"
|
|
1337
|
+
/* @__PURE__ */ jsx(
|
|
1338
|
+
"svg",
|
|
1066
1339
|
{
|
|
1067
|
-
|
|
1068
|
-
|
|
1340
|
+
width: "10",
|
|
1341
|
+
height: "10",
|
|
1342
|
+
viewBox: "0 0 24 24",
|
|
1343
|
+
fill: "none",
|
|
1344
|
+
style: {
|
|
1345
|
+
transform: open ? "rotate(180deg)" : "rotate(0deg)",
|
|
1346
|
+
transition: "transform 0.15s ease"
|
|
1347
|
+
},
|
|
1348
|
+
children: /* @__PURE__ */ jsx(
|
|
1349
|
+
"path",
|
|
1350
|
+
{
|
|
1351
|
+
d: "M7 10l5 5 5-5",
|
|
1352
|
+
stroke: tokens.textMuted,
|
|
1353
|
+
strokeWidth: "2.5",
|
|
1354
|
+
strokeLinecap: "round",
|
|
1355
|
+
strokeLinejoin: "round"
|
|
1356
|
+
}
|
|
1357
|
+
)
|
|
1069
1358
|
}
|
|
1070
|
-
)
|
|
1071
|
-
"
|
|
1072
|
-
selection.walletName,
|
|
1073
|
-
" on ",
|
|
1074
|
-
selection.chainName
|
|
1359
|
+
),
|
|
1360
|
+
"Advanced options"
|
|
1075
1361
|
]
|
|
1076
1362
|
}
|
|
1077
|
-
)
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1363
|
+
),
|
|
1364
|
+
open && /* @__PURE__ */ jsxs(
|
|
1365
|
+
"div",
|
|
1366
|
+
{
|
|
1367
|
+
style: {
|
|
1368
|
+
marginTop: "10px",
|
|
1369
|
+
padding: "14px",
|
|
1370
|
+
background: tokens.bgInput,
|
|
1371
|
+
borderRadius: tokens.radius,
|
|
1372
|
+
border: `1px solid ${tokens.border}`
|
|
1373
|
+
},
|
|
1374
|
+
children: [
|
|
1375
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "14px" }, children: [
|
|
1376
|
+
/* @__PURE__ */ jsx(
|
|
1377
|
+
"label",
|
|
1378
|
+
{
|
|
1379
|
+
style: {
|
|
1380
|
+
display: "block",
|
|
1381
|
+
fontSize: "0.7rem",
|
|
1382
|
+
fontWeight: 600,
|
|
1383
|
+
color: tokens.textMuted,
|
|
1384
|
+
textTransform: "uppercase",
|
|
1385
|
+
letterSpacing: "0.05em",
|
|
1386
|
+
marginBottom: "6px"
|
|
1387
|
+
},
|
|
1388
|
+
children: "Asset"
|
|
1389
|
+
}
|
|
1390
|
+
),
|
|
1391
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px" }, children: ASSETS.map((asset) => {
|
|
1392
|
+
const isSelected = settings.asset === asset;
|
|
1393
|
+
return /* @__PURE__ */ jsx(
|
|
1394
|
+
"button",
|
|
1395
|
+
{
|
|
1396
|
+
onClick: () => onChange({
|
|
1397
|
+
...settings,
|
|
1398
|
+
asset: isSelected ? null : asset
|
|
1399
|
+
}),
|
|
1400
|
+
style: {
|
|
1401
|
+
padding: "6px 14px",
|
|
1402
|
+
fontSize: "0.8rem",
|
|
1403
|
+
fontWeight: 600,
|
|
1404
|
+
fontFamily: "inherit",
|
|
1405
|
+
borderRadius: "6px",
|
|
1406
|
+
border: `1.5px solid ${isSelected ? tokens.accent : tokens.border}`,
|
|
1407
|
+
background: isSelected ? tokens.accent + "18" : "transparent",
|
|
1408
|
+
color: isSelected ? tokens.accent : tokens.text,
|
|
1409
|
+
cursor: "pointer",
|
|
1410
|
+
outline: "none",
|
|
1411
|
+
transition: "all 0.12s ease"
|
|
1412
|
+
},
|
|
1413
|
+
children: asset
|
|
1414
|
+
},
|
|
1415
|
+
asset
|
|
1416
|
+
);
|
|
1417
|
+
}) })
|
|
1418
|
+
] }),
|
|
1419
|
+
chains.length > 0 && /* @__PURE__ */ jsxs("div", { style: { marginBottom: "14px" }, children: [
|
|
1420
|
+
/* @__PURE__ */ jsx(
|
|
1421
|
+
"label",
|
|
1422
|
+
{
|
|
1423
|
+
style: {
|
|
1424
|
+
display: "block",
|
|
1425
|
+
fontSize: "0.7rem",
|
|
1426
|
+
fontWeight: 600,
|
|
1427
|
+
color: tokens.textMuted,
|
|
1428
|
+
textTransform: "uppercase",
|
|
1429
|
+
letterSpacing: "0.05em",
|
|
1430
|
+
marginBottom: "6px"
|
|
1431
|
+
},
|
|
1432
|
+
children: "Chain"
|
|
1433
|
+
}
|
|
1434
|
+
),
|
|
1435
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: chains.map((chain) => {
|
|
1436
|
+
const isSelected = settings.chain === chain.name;
|
|
1437
|
+
return /* @__PURE__ */ jsx(
|
|
1438
|
+
"button",
|
|
1439
|
+
{
|
|
1440
|
+
onClick: () => onChange({
|
|
1441
|
+
...settings,
|
|
1442
|
+
chain: isSelected ? null : chain.name
|
|
1443
|
+
}),
|
|
1444
|
+
style: {
|
|
1445
|
+
padding: "6px 14px",
|
|
1446
|
+
fontSize: "0.8rem",
|
|
1447
|
+
fontWeight: 600,
|
|
1448
|
+
fontFamily: "inherit",
|
|
1449
|
+
borderRadius: "6px",
|
|
1450
|
+
border: `1.5px solid ${isSelected ? tokens.accent : tokens.border}`,
|
|
1451
|
+
background: isSelected ? tokens.accent + "18" : "transparent",
|
|
1452
|
+
color: isSelected ? tokens.accent : tokens.text,
|
|
1453
|
+
cursor: "pointer",
|
|
1454
|
+
outline: "none",
|
|
1455
|
+
transition: "all 0.12s ease"
|
|
1456
|
+
},
|
|
1457
|
+
children: chain.name
|
|
1458
|
+
},
|
|
1459
|
+
chain.id
|
|
1460
|
+
);
|
|
1461
|
+
}) })
|
|
1462
|
+
] }),
|
|
1463
|
+
/* @__PURE__ */ jsx("div", { children: !showProviders ? /* @__PURE__ */ jsxs(
|
|
1464
|
+
"button",
|
|
1465
|
+
{
|
|
1466
|
+
onClick: () => setShowProviders(true),
|
|
1467
|
+
disabled: connectingNewAccount,
|
|
1468
|
+
style: {
|
|
1469
|
+
display: "flex",
|
|
1470
|
+
alignItems: "center",
|
|
1471
|
+
gap: "6px",
|
|
1472
|
+
background: "transparent",
|
|
1473
|
+
border: `1px dashed ${tokens.border}`,
|
|
1474
|
+
borderRadius: tokens.radius,
|
|
1475
|
+
padding: "10px 14px",
|
|
1476
|
+
width: "100%",
|
|
1477
|
+
cursor: connectingNewAccount ? "not-allowed" : "pointer",
|
|
1478
|
+
color: tokens.textSecondary,
|
|
1479
|
+
fontFamily: "inherit",
|
|
1480
|
+
fontSize: "0.825rem",
|
|
1481
|
+
fontWeight: 500,
|
|
1482
|
+
outline: "none",
|
|
1483
|
+
opacity: connectingNewAccount ? 0.5 : 1,
|
|
1484
|
+
transition: "opacity 0.1s ease"
|
|
1485
|
+
},
|
|
1486
|
+
children: [
|
|
1487
|
+
/* @__PURE__ */ jsx(
|
|
1488
|
+
"svg",
|
|
1489
|
+
{
|
|
1490
|
+
width: "14",
|
|
1491
|
+
height: "14",
|
|
1492
|
+
viewBox: "0 0 24 24",
|
|
1493
|
+
fill: "none",
|
|
1494
|
+
children: /* @__PURE__ */ jsx(
|
|
1495
|
+
"path",
|
|
1496
|
+
{
|
|
1497
|
+
d: "M12 5v14M5 12h14",
|
|
1498
|
+
stroke: tokens.textMuted,
|
|
1499
|
+
strokeWidth: "2",
|
|
1500
|
+
strokeLinecap: "round"
|
|
1501
|
+
}
|
|
1502
|
+
)
|
|
1503
|
+
}
|
|
1504
|
+
),
|
|
1505
|
+
"Connect new account"
|
|
1506
|
+
]
|
|
1507
|
+
}
|
|
1508
|
+
) : /* @__PURE__ */ jsxs("div", { children: [
|
|
1509
|
+
/* @__PURE__ */ jsxs(
|
|
1510
|
+
"div",
|
|
1511
|
+
{
|
|
1512
|
+
style: {
|
|
1513
|
+
display: "flex",
|
|
1514
|
+
alignItems: "center",
|
|
1515
|
+
justifyContent: "space-between",
|
|
1516
|
+
marginBottom: "8px"
|
|
1517
|
+
},
|
|
1518
|
+
children: [
|
|
1519
|
+
/* @__PURE__ */ jsx(
|
|
1520
|
+
"label",
|
|
1521
|
+
{
|
|
1522
|
+
style: {
|
|
1523
|
+
fontSize: "0.7rem",
|
|
1524
|
+
fontWeight: 600,
|
|
1525
|
+
color: tokens.textMuted,
|
|
1526
|
+
textTransform: "uppercase",
|
|
1527
|
+
letterSpacing: "0.05em"
|
|
1528
|
+
},
|
|
1529
|
+
children: "Select provider"
|
|
1530
|
+
}
|
|
1531
|
+
),
|
|
1532
|
+
/* @__PURE__ */ jsx(
|
|
1533
|
+
"button",
|
|
1534
|
+
{
|
|
1535
|
+
onClick: () => setShowProviders(false),
|
|
1536
|
+
style: {
|
|
1537
|
+
background: "transparent",
|
|
1538
|
+
border: "none",
|
|
1539
|
+
cursor: "pointer",
|
|
1540
|
+
color: tokens.textMuted,
|
|
1541
|
+
fontSize: "0.75rem",
|
|
1542
|
+
fontFamily: "inherit",
|
|
1543
|
+
outline: "none",
|
|
1544
|
+
padding: "2px 4px"
|
|
1545
|
+
},
|
|
1546
|
+
children: "Cancel"
|
|
1547
|
+
}
|
|
1548
|
+
)
|
|
1549
|
+
]
|
|
1550
|
+
}
|
|
1551
|
+
),
|
|
1552
|
+
/* @__PURE__ */ jsx(
|
|
1553
|
+
"div",
|
|
1554
|
+
{
|
|
1555
|
+
style: {
|
|
1556
|
+
display: "flex",
|
|
1557
|
+
flexDirection: "column",
|
|
1558
|
+
gap: "6px"
|
|
1559
|
+
},
|
|
1560
|
+
children: providers.map((p) => /* @__PURE__ */ jsx(
|
|
1561
|
+
ProviderCard,
|
|
1562
|
+
{
|
|
1563
|
+
provider: p,
|
|
1564
|
+
selected: false,
|
|
1565
|
+
onClick: () => {
|
|
1566
|
+
onConnectNewAccount(p.id);
|
|
1567
|
+
setShowProviders(false);
|
|
1568
|
+
}
|
|
1569
|
+
},
|
|
1570
|
+
p.id
|
|
1571
|
+
))
|
|
1572
|
+
}
|
|
1573
|
+
)
|
|
1574
|
+
] }) })
|
|
1575
|
+
]
|
|
1576
|
+
}
|
|
1577
|
+
)
|
|
1578
|
+
] });
|
|
1579
|
+
}
|
|
1580
|
+
var TOP_UP_OPTIONS = [0, 25, 50, 100, 500];
|
|
1581
|
+
function AllowanceSelector({ action, onSelect }) {
|
|
1582
|
+
const { tokens } = useSwypeConfig();
|
|
1583
|
+
const metadataAmount = action.metadata?.amount;
|
|
1584
|
+
const tokenDecimals = Number(action.metadata?.tokenDecimals ?? 6);
|
|
1585
|
+
const currency = action.metadata?.currency ?? "USD";
|
|
1586
|
+
const transferAmountRaw = metadataAmount ? Number(BigInt(metadataAmount)) / 10 ** tokenDecimals : 0;
|
|
1587
|
+
const [selectedTopUp, setSelectedTopUp] = useState(0);
|
|
1588
|
+
const totalAllowance = transferAmountRaw + selectedTopUp;
|
|
1589
|
+
const formatAmount = (amount) => `$${amount.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
1590
|
+
return /* @__PURE__ */ jsxs(
|
|
1591
|
+
"div",
|
|
1592
|
+
{
|
|
1593
|
+
style: {
|
|
1594
|
+
padding: "4px 0",
|
|
1595
|
+
textAlign: "left"
|
|
1596
|
+
},
|
|
1597
|
+
children: [
|
|
1598
|
+
/* @__PURE__ */ jsx(
|
|
1599
|
+
"h3",
|
|
1600
|
+
{
|
|
1601
|
+
style: {
|
|
1602
|
+
fontSize: "1rem",
|
|
1603
|
+
fontWeight: 600,
|
|
1604
|
+
color: tokens.text,
|
|
1605
|
+
margin: "0 0 6px 0",
|
|
1606
|
+
textAlign: "center"
|
|
1607
|
+
},
|
|
1608
|
+
children: "Set spending limit"
|
|
1609
|
+
}
|
|
1610
|
+
),
|
|
1611
|
+
/* @__PURE__ */ jsx(
|
|
1612
|
+
"p",
|
|
1613
|
+
{
|
|
1614
|
+
style: {
|
|
1615
|
+
fontSize: "0.8rem",
|
|
1616
|
+
color: tokens.textMuted,
|
|
1617
|
+
margin: "0 0 16px 0",
|
|
1618
|
+
lineHeight: 1.5,
|
|
1619
|
+
textAlign: "center"
|
|
1620
|
+
},
|
|
1621
|
+
children: "Pre-authorize a higher amount so future payments go through instantly without wallet prompts."
|
|
1622
|
+
}
|
|
1623
|
+
),
|
|
1624
|
+
/* @__PURE__ */ jsxs(
|
|
1625
|
+
"div",
|
|
1626
|
+
{
|
|
1627
|
+
style: {
|
|
1628
|
+
display: "flex",
|
|
1629
|
+
justifyContent: "space-between",
|
|
1630
|
+
alignItems: "center",
|
|
1631
|
+
padding: "10px 14px",
|
|
1632
|
+
background: tokens.bgInput,
|
|
1633
|
+
borderRadius: tokens.radius,
|
|
1634
|
+
marginBottom: "12px",
|
|
1635
|
+
fontSize: "0.825rem"
|
|
1636
|
+
},
|
|
1637
|
+
children: [
|
|
1638
|
+
/* @__PURE__ */ jsx("span", { style: { color: tokens.textSecondary }, children: "This payment" }),
|
|
1639
|
+
/* @__PURE__ */ jsxs("span", { style: { fontWeight: 600, color: tokens.text }, children: [
|
|
1640
|
+
formatAmount(transferAmountRaw),
|
|
1641
|
+
" ",
|
|
1642
|
+
currency
|
|
1643
|
+
] })
|
|
1644
|
+
]
|
|
1645
|
+
}
|
|
1646
|
+
),
|
|
1647
|
+
/* @__PURE__ */ jsx(
|
|
1648
|
+
"div",
|
|
1649
|
+
{
|
|
1650
|
+
style: {
|
|
1651
|
+
display: "flex",
|
|
1652
|
+
flexDirection: "column",
|
|
1653
|
+
gap: "6px",
|
|
1654
|
+
marginBottom: "16px"
|
|
1655
|
+
},
|
|
1656
|
+
children: TOP_UP_OPTIONS.map((topUp) => {
|
|
1657
|
+
const isSelected = selectedTopUp === topUp;
|
|
1658
|
+
const total = transferAmountRaw + topUp;
|
|
1659
|
+
const label = topUp === 0 ? "Just this payment" : `+${formatAmount(topUp)} for future payments`;
|
|
1660
|
+
return /* @__PURE__ */ jsxs(
|
|
1661
|
+
"button",
|
|
1662
|
+
{
|
|
1663
|
+
onClick: () => setSelectedTopUp(topUp),
|
|
1664
|
+
style: {
|
|
1665
|
+
display: "flex",
|
|
1666
|
+
alignItems: "center",
|
|
1667
|
+
justifyContent: "space-between",
|
|
1668
|
+
width: "100%",
|
|
1669
|
+
padding: "12px 14px",
|
|
1670
|
+
background: isSelected ? tokens.accent + "14" : "transparent",
|
|
1671
|
+
border: `1.5px solid ${isSelected ? tokens.accent : tokens.border}`,
|
|
1672
|
+
borderRadius: tokens.radius,
|
|
1673
|
+
cursor: "pointer",
|
|
1674
|
+
color: tokens.text,
|
|
1675
|
+
fontFamily: "inherit",
|
|
1676
|
+
fontSize: "0.825rem",
|
|
1677
|
+
textAlign: "left",
|
|
1678
|
+
outline: "none",
|
|
1679
|
+
transition: "all 0.12s ease"
|
|
1680
|
+
},
|
|
1681
|
+
children: [
|
|
1682
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
1683
|
+
/* @__PURE__ */ jsx(
|
|
1684
|
+
"div",
|
|
1685
|
+
{
|
|
1686
|
+
style: {
|
|
1687
|
+
width: 16,
|
|
1688
|
+
height: 16,
|
|
1689
|
+
borderRadius: "50%",
|
|
1690
|
+
border: `2px solid ${isSelected ? tokens.accent : tokens.border}`,
|
|
1691
|
+
display: "flex",
|
|
1692
|
+
alignItems: "center",
|
|
1693
|
+
justifyContent: "center",
|
|
1694
|
+
flexShrink: 0
|
|
1695
|
+
},
|
|
1696
|
+
children: isSelected && /* @__PURE__ */ jsx(
|
|
1697
|
+
"div",
|
|
1698
|
+
{
|
|
1699
|
+
style: {
|
|
1700
|
+
width: 8,
|
|
1701
|
+
height: 8,
|
|
1702
|
+
borderRadius: "50%",
|
|
1703
|
+
background: tokens.accent
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
)
|
|
1707
|
+
}
|
|
1708
|
+
),
|
|
1709
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: isSelected ? 600 : 400 }, children: label })
|
|
1710
|
+
] }),
|
|
1711
|
+
/* @__PURE__ */ jsx(
|
|
1712
|
+
"span",
|
|
1713
|
+
{
|
|
1714
|
+
style: {
|
|
1715
|
+
fontWeight: 600,
|
|
1716
|
+
color: isSelected ? tokens.accent : tokens.textMuted,
|
|
1717
|
+
fontSize: "0.8rem",
|
|
1718
|
+
flexShrink: 0,
|
|
1719
|
+
marginLeft: "8px"
|
|
1720
|
+
},
|
|
1721
|
+
children: formatAmount(total)
|
|
1722
|
+
}
|
|
1723
|
+
)
|
|
1724
|
+
]
|
|
1725
|
+
},
|
|
1726
|
+
topUp
|
|
1727
|
+
);
|
|
1728
|
+
})
|
|
1729
|
+
}
|
|
1730
|
+
),
|
|
1731
|
+
/* @__PURE__ */ jsxs(
|
|
1732
|
+
"div",
|
|
1733
|
+
{
|
|
1734
|
+
style: {
|
|
1735
|
+
display: "flex",
|
|
1736
|
+
justifyContent: "space-between",
|
|
1737
|
+
alignItems: "center",
|
|
1738
|
+
padding: "10px 14px",
|
|
1739
|
+
background: tokens.bgInput,
|
|
1740
|
+
borderRadius: tokens.radius,
|
|
1741
|
+
marginBottom: "14px",
|
|
1742
|
+
fontSize: "0.825rem"
|
|
1743
|
+
},
|
|
1744
|
+
children: [
|
|
1745
|
+
/* @__PURE__ */ jsx("span", { style: { color: tokens.textSecondary }, children: "Total authorization" }),
|
|
1746
|
+
/* @__PURE__ */ jsxs("span", { style: { fontWeight: 700, color: tokens.text, fontSize: "0.9rem" }, children: [
|
|
1747
|
+
formatAmount(totalAllowance),
|
|
1748
|
+
" ",
|
|
1749
|
+
currency
|
|
1750
|
+
] })
|
|
1751
|
+
]
|
|
1752
|
+
}
|
|
1753
|
+
),
|
|
1754
|
+
/* @__PURE__ */ jsx(
|
|
1755
|
+
"button",
|
|
1756
|
+
{
|
|
1757
|
+
onClick: () => onSelect({ topUpAmount: selectedTopUp }),
|
|
1758
|
+
style: {
|
|
1759
|
+
width: "100%",
|
|
1760
|
+
padding: "14px",
|
|
1761
|
+
background: tokens.accent,
|
|
1762
|
+
color: tokens.accentText,
|
|
1763
|
+
border: "none",
|
|
1764
|
+
borderRadius: tokens.radius,
|
|
1765
|
+
fontSize: "1rem",
|
|
1766
|
+
fontWeight: 600,
|
|
1767
|
+
cursor: "pointer",
|
|
1768
|
+
transition: "background 0.15s ease",
|
|
1769
|
+
fontFamily: "inherit"
|
|
1770
|
+
},
|
|
1771
|
+
children: "Authorize & Sign"
|
|
1772
|
+
}
|
|
1773
|
+
)
|
|
1774
|
+
]
|
|
1775
|
+
}
|
|
1776
|
+
);
|
|
1777
|
+
}
|
|
1778
|
+
function isMobile() {
|
|
1779
|
+
if (typeof navigator === "undefined") return false;
|
|
1780
|
+
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
1781
|
+
navigator.userAgent
|
|
1782
|
+
);
|
|
1783
|
+
}
|
|
1784
|
+
function computeSmartDefaults(accts, transferAmount) {
|
|
1785
|
+
if (accts.length === 0) return null;
|
|
1786
|
+
for (const acct of accts) {
|
|
1787
|
+
for (const wallet of acct.wallets) {
|
|
1788
|
+
if (wallet.status === "ACTIVE" && wallet.lastAuthorizedToken) {
|
|
1789
|
+
const matchingSource = wallet.sources.find(
|
|
1790
|
+
(s) => s.token.symbol === wallet.lastAuthorizedToken.symbol
|
|
1791
|
+
);
|
|
1792
|
+
if (matchingSource && matchingSource.balance.available.amount >= transferAmount) {
|
|
1793
|
+
return { accountId: acct.id, walletId: wallet.id };
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
let bestAccount = null;
|
|
1799
|
+
let bestWallet = null;
|
|
1800
|
+
let bestBalance = -1;
|
|
1801
|
+
for (const acct of accts) {
|
|
1802
|
+
for (const wallet of acct.wallets) {
|
|
1803
|
+
const walletBal = wallet.balance.available.amount;
|
|
1804
|
+
if (walletBal > bestBalance) {
|
|
1805
|
+
bestBalance = walletBal;
|
|
1806
|
+
bestAccount = acct;
|
|
1807
|
+
bestWallet = wallet;
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
if (bestAccount) {
|
|
1812
|
+
return {
|
|
1813
|
+
accountId: bestAccount.id,
|
|
1814
|
+
walletId: bestWallet?.id ?? null
|
|
1815
|
+
};
|
|
1816
|
+
}
|
|
1817
|
+
return { accountId: accts[0].id, walletId: null };
|
|
1818
|
+
}
|
|
1819
|
+
function SwypePayment({
|
|
1820
|
+
destination,
|
|
1821
|
+
onComplete,
|
|
1822
|
+
onError
|
|
1823
|
+
}) {
|
|
1824
|
+
const { apiBaseUrl, tokens, depositAmount } = useSwypeConfig();
|
|
1825
|
+
const { ready, authenticated, login, getAccessToken } = usePrivy();
|
|
1826
|
+
const [step, setStep] = useState("login");
|
|
1827
|
+
const [error, setError] = useState(null);
|
|
1828
|
+
const [providers, setProviders] = useState([]);
|
|
1829
|
+
const [accounts, setAccounts] = useState([]);
|
|
1830
|
+
const [chains, setChains] = useState([]);
|
|
1831
|
+
const [loadingData, setLoadingData] = useState(false);
|
|
1832
|
+
const [selectedAccountId, setSelectedAccountId] = useState(null);
|
|
1833
|
+
const [selectedWalletId, setSelectedWalletId] = useState(null);
|
|
1834
|
+
const [selectedProviderId, setSelectedProviderId] = useState(null);
|
|
1835
|
+
const [connectingNewAccount, setConnectingNewAccount] = useState(false);
|
|
1836
|
+
const [amount, setAmount] = useState(
|
|
1837
|
+
depositAmount != null ? depositAmount.toString() : ""
|
|
1838
|
+
);
|
|
1839
|
+
const [advancedSettings, setAdvancedSettings] = useState({
|
|
1840
|
+
asset: null,
|
|
1841
|
+
chain: null
|
|
1842
|
+
});
|
|
1843
|
+
const [transfer, setTransfer] = useState(null);
|
|
1844
|
+
const [creatingTransfer, setCreatingTransfer] = useState(false);
|
|
1845
|
+
const [mobileFlow, setMobileFlow] = useState(false);
|
|
1846
|
+
const pollingTransferIdRef = useRef(null);
|
|
1847
|
+
const authExecutor = useAuthorizationExecutor();
|
|
1109
1848
|
const polling = useTransferPolling();
|
|
1110
|
-
const sourceType =
|
|
1111
|
-
const sourceId =
|
|
1849
|
+
const sourceType = connectingNewAccount ? "providerId" : selectedWalletId ? "walletId" : selectedAccountId ? "accountId" : "providerId";
|
|
1850
|
+
const sourceId = connectingNewAccount ? selectedProviderId ?? "" : selectedWalletId ? selectedWalletId : selectedAccountId ? selectedAccountId : selectedProviderId ?? "";
|
|
1851
|
+
useEffect(() => {
|
|
1852
|
+
if (depositAmount != null) {
|
|
1853
|
+
setAmount(depositAmount.toString());
|
|
1854
|
+
}
|
|
1855
|
+
}, [depositAmount]);
|
|
1112
1856
|
useEffect(() => {
|
|
1113
1857
|
if (ready && authenticated && step === "login") {
|
|
1114
|
-
|
|
1858
|
+
if (depositAmount != null && depositAmount > 0) {
|
|
1859
|
+
setStep("ready");
|
|
1860
|
+
} else {
|
|
1861
|
+
setStep("enter-amount");
|
|
1862
|
+
}
|
|
1115
1863
|
}
|
|
1116
|
-
}, [ready, authenticated, step]);
|
|
1864
|
+
}, [ready, authenticated, step, depositAmount]);
|
|
1865
|
+
const loadingDataRef = useRef(false);
|
|
1117
1866
|
useEffect(() => {
|
|
1118
|
-
if (
|
|
1119
|
-
if (
|
|
1867
|
+
if (!authenticated) return;
|
|
1868
|
+
if (accounts.length > 0 || loadingDataRef.current) return;
|
|
1120
1869
|
let cancelled = false;
|
|
1870
|
+
loadingDataRef.current = true;
|
|
1121
1871
|
const load = async () => {
|
|
1122
1872
|
setLoadingData(true);
|
|
1123
1873
|
setError(null);
|
|
1124
1874
|
try {
|
|
1125
1875
|
const token = await getAccessToken();
|
|
1126
1876
|
if (!token) throw new Error("Not authenticated");
|
|
1127
|
-
const [prov, accts] = await Promise.all([
|
|
1877
|
+
const [prov, accts, chn] = await Promise.all([
|
|
1128
1878
|
fetchProviders(apiBaseUrl, token),
|
|
1129
|
-
fetchAccounts(apiBaseUrl, token)
|
|
1879
|
+
fetchAccounts(apiBaseUrl, token),
|
|
1880
|
+
fetchChains(apiBaseUrl, token)
|
|
1130
1881
|
]);
|
|
1131
1882
|
if (cancelled) return;
|
|
1132
1883
|
setProviders(prov);
|
|
1133
1884
|
setAccounts(accts);
|
|
1134
|
-
|
|
1885
|
+
setChains(chn);
|
|
1886
|
+
const parsedAmt = depositAmount != null ? depositAmount : 0;
|
|
1887
|
+
const defaults = computeSmartDefaults(accts, parsedAmt);
|
|
1888
|
+
if (defaults) {
|
|
1889
|
+
setSelectedAccountId(defaults.accountId);
|
|
1890
|
+
setSelectedWalletId(defaults.walletId);
|
|
1891
|
+
} else if (prov.length > 0) {
|
|
1892
|
+
setSelectedProviderId(prov[0].id);
|
|
1893
|
+
}
|
|
1135
1894
|
} catch (err) {
|
|
1136
1895
|
if (!cancelled) {
|
|
1137
1896
|
const msg = err instanceof Error ? err.message : "Failed to load data";
|
|
1138
1897
|
setError(msg);
|
|
1139
1898
|
}
|
|
1140
1899
|
} finally {
|
|
1141
|
-
if (!cancelled)
|
|
1900
|
+
if (!cancelled) {
|
|
1901
|
+
setLoadingData(false);
|
|
1902
|
+
loadingDataRef.current = false;
|
|
1903
|
+
}
|
|
1142
1904
|
}
|
|
1143
1905
|
};
|
|
1144
1906
|
load();
|
|
1145
1907
|
return () => {
|
|
1146
1908
|
cancelled = true;
|
|
1909
|
+
loadingDataRef.current = false;
|
|
1147
1910
|
};
|
|
1148
|
-
}, [
|
|
1911
|
+
}, [authenticated, accounts.length, apiBaseUrl, getAccessToken]);
|
|
1149
1912
|
useEffect(() => {
|
|
1150
1913
|
if (!polling.transfer) return;
|
|
1151
1914
|
if (polling.transfer.status === "COMPLETED") {
|
|
@@ -1172,6 +1935,61 @@ function SwypePayment({
|
|
|
1172
1935
|
document.removeEventListener("visibilitychange", handleVisibility);
|
|
1173
1936
|
};
|
|
1174
1937
|
}, [mobileFlow, polling]);
|
|
1938
|
+
useEffect(() => {
|
|
1939
|
+
if (!authExecutor.pendingSelectSource) return;
|
|
1940
|
+
const action = authExecutor.pendingSelectSource;
|
|
1941
|
+
const hasAdvancedOverride = advancedSettings.asset !== null || advancedSettings.chain !== null;
|
|
1942
|
+
if (hasAdvancedOverride) {
|
|
1943
|
+
const options = action.metadata?.options ?? [];
|
|
1944
|
+
const recommended = action.metadata?.recommended;
|
|
1945
|
+
const match = options.find(
|
|
1946
|
+
(opt) => (advancedSettings.chain === null || opt.chainName === advancedSettings.chain) && (advancedSettings.asset === null || opt.tokenSymbol === advancedSettings.asset)
|
|
1947
|
+
);
|
|
1948
|
+
if (match) {
|
|
1949
|
+
authExecutor.resolveSelectSource({
|
|
1950
|
+
chainName: match.chainName,
|
|
1951
|
+
tokenSymbol: match.tokenSymbol
|
|
1952
|
+
});
|
|
1953
|
+
} else if (recommended) {
|
|
1954
|
+
authExecutor.resolveSelectSource({
|
|
1955
|
+
chainName: recommended.chainName,
|
|
1956
|
+
tokenSymbol: recommended.tokenSymbol
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
} else {
|
|
1960
|
+
const options = action.metadata?.options ?? [];
|
|
1961
|
+
const recommended = action.metadata?.recommended;
|
|
1962
|
+
const selWallet = selectedWalletId ? accounts.find((a) => a.id === selectedAccountId)?.wallets.find((w) => w.id === selectedWalletId) : null;
|
|
1963
|
+
if (selWallet) {
|
|
1964
|
+
const walletMatch = options.find(
|
|
1965
|
+
(opt) => opt.chainName === selWallet.chain.name
|
|
1966
|
+
);
|
|
1967
|
+
if (walletMatch) {
|
|
1968
|
+
authExecutor.resolveSelectSource({
|
|
1969
|
+
chainName: walletMatch.chainName,
|
|
1970
|
+
tokenSymbol: walletMatch.tokenSymbol
|
|
1971
|
+
});
|
|
1972
|
+
return;
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
if (recommended) {
|
|
1976
|
+
authExecutor.resolveSelectSource({
|
|
1977
|
+
chainName: recommended.chainName,
|
|
1978
|
+
tokenSymbol: recommended.tokenSymbol
|
|
1979
|
+
});
|
|
1980
|
+
} else if (options.length > 0) {
|
|
1981
|
+
authExecutor.resolveSelectSource({
|
|
1982
|
+
chainName: options[0].chainName,
|
|
1983
|
+
tokenSymbol: options[0].tokenSymbol
|
|
1984
|
+
});
|
|
1985
|
+
} else {
|
|
1986
|
+
authExecutor.resolveSelectSource({
|
|
1987
|
+
chainName: "Base",
|
|
1988
|
+
tokenSymbol: "USDC"
|
|
1989
|
+
});
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
}, [authExecutor, authExecutor.pendingSelectSource, advancedSettings, selectedWalletId, selectedAccountId, accounts]);
|
|
1175
1993
|
const handlePay = useCallback(async () => {
|
|
1176
1994
|
const parsedAmount = parseFloat(amount);
|
|
1177
1995
|
if (isNaN(parsedAmount) || parsedAmount <= 0) {
|
|
@@ -1179,7 +1997,7 @@ function SwypePayment({
|
|
|
1179
1997
|
return;
|
|
1180
1998
|
}
|
|
1181
1999
|
if (!sourceId) {
|
|
1182
|
-
setError("
|
|
2000
|
+
setError("No account or provider selected.");
|
|
1183
2001
|
return;
|
|
1184
2002
|
}
|
|
1185
2003
|
setStep("processing");
|
|
@@ -1189,12 +2007,6 @@ function SwypePayment({
|
|
|
1189
2007
|
try {
|
|
1190
2008
|
const token = await getAccessToken();
|
|
1191
2009
|
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
2010
|
const t = await createTransfer(apiBaseUrl, token, {
|
|
1199
2011
|
sourceType,
|
|
1200
2012
|
sourceId,
|
|
@@ -1218,7 +2030,7 @@ function SwypePayment({
|
|
|
1218
2030
|
const msg = err instanceof Error ? err.message : "Transfer creation failed";
|
|
1219
2031
|
setError(msg);
|
|
1220
2032
|
onError?.(msg);
|
|
1221
|
-
setStep("
|
|
2033
|
+
setStep("ready");
|
|
1222
2034
|
} finally {
|
|
1223
2035
|
setCreatingTransfer(false);
|
|
1224
2036
|
}
|
|
@@ -1231,19 +2043,24 @@ function SwypePayment({
|
|
|
1231
2043
|
getAccessToken,
|
|
1232
2044
|
authExecutor,
|
|
1233
2045
|
polling,
|
|
1234
|
-
onError
|
|
1235
|
-
topUpBalance
|
|
2046
|
+
onError
|
|
1236
2047
|
]);
|
|
1237
2048
|
const handleNewPayment = () => {
|
|
1238
|
-
setStep("
|
|
2049
|
+
setStep("ready");
|
|
1239
2050
|
setTransfer(null);
|
|
1240
2051
|
setError(null);
|
|
1241
|
-
setAmount(
|
|
1242
|
-
setTopUpBalance("");
|
|
2052
|
+
setAmount(depositAmount != null ? depositAmount.toString() : "");
|
|
1243
2053
|
setMobileFlow(false);
|
|
1244
2054
|
pollingTransferIdRef.current = null;
|
|
1245
|
-
|
|
1246
|
-
|
|
2055
|
+
setConnectingNewAccount(false);
|
|
2056
|
+
setSelectedWalletId(null);
|
|
2057
|
+
setAdvancedSettings({ asset: null, chain: null });
|
|
2058
|
+
if (accounts.length > 0) setSelectedAccountId(accounts[0].id);
|
|
2059
|
+
};
|
|
2060
|
+
const handleConnectNewAccount = (providerId) => {
|
|
2061
|
+
setSelectedProviderId(providerId);
|
|
2062
|
+
setSelectedAccountId(null);
|
|
2063
|
+
setConnectingNewAccount(true);
|
|
1247
2064
|
};
|
|
1248
2065
|
const cardStyle = {
|
|
1249
2066
|
background: tokens.bgCard,
|
|
@@ -1281,15 +2098,10 @@ function SwypePayment({
|
|
|
1281
2098
|
opacity: 0.5,
|
|
1282
2099
|
cursor: "not-allowed"
|
|
1283
2100
|
};
|
|
1284
|
-
|
|
2101
|
+
({
|
|
1285
2102
|
...btnPrimary,
|
|
1286
|
-
background: "transparent",
|
|
1287
2103
|
color: tokens.textSecondary,
|
|
1288
|
-
border: `1px solid ${tokens.border}
|
|
1289
|
-
width: "auto",
|
|
1290
|
-
flex: "0 0 auto",
|
|
1291
|
-
padding: "14px 20px"
|
|
1292
|
-
};
|
|
2104
|
+
border: `1px solid ${tokens.border}`});
|
|
1293
2105
|
const errorStyle = {
|
|
1294
2106
|
background: tokens.errorBg,
|
|
1295
2107
|
border: `1px solid ${tokens.error}`,
|
|
@@ -1380,62 +2192,20 @@ function SwypePayment({
|
|
|
1380
2192
|
/* @__PURE__ */ jsx("button", { style: btnPrimary, onClick: login, children: "Connect to Swype" })
|
|
1381
2193
|
] }) });
|
|
1382
2194
|
}
|
|
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
2195
|
if (step === "enter-amount") {
|
|
2196
|
+
const parsedAmount = parseFloat(amount);
|
|
2197
|
+
const canContinue = !isNaN(parsedAmount) && parsedAmount > 0;
|
|
2198
|
+
let maxSourceBalance = null;
|
|
2199
|
+
for (const acct of accounts) {
|
|
2200
|
+
for (const wallet of acct.wallets) {
|
|
2201
|
+
for (const source of wallet.sources) {
|
|
2202
|
+
const bal = source.balance.available.amount;
|
|
2203
|
+
if (maxSourceBalance === null || bal > maxSourceBalance) {
|
|
2204
|
+
maxSourceBalance = bal;
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
1439
2209
|
return /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
|
|
1440
2210
|
stepBadge("Enter amount"),
|
|
1441
2211
|
/* @__PURE__ */ jsx("h2", { style: headingStyle, children: "How much?" }),
|
|
@@ -1451,7 +2221,7 @@ function SwypePayment({
|
|
|
1451
2221
|
border: `1px solid ${tokens.border}`,
|
|
1452
2222
|
borderRadius: tokens.radius,
|
|
1453
2223
|
padding: "4px 14px 4px 4px",
|
|
1454
|
-
marginBottom: "
|
|
2224
|
+
marginBottom: "8px"
|
|
1455
2225
|
},
|
|
1456
2226
|
children: [
|
|
1457
2227
|
/* @__PURE__ */ jsx(
|
|
@@ -1475,6 +2245,7 @@ function SwypePayment({
|
|
|
1475
2245
|
step: "0.01",
|
|
1476
2246
|
value: amount,
|
|
1477
2247
|
onChange: (e) => setAmount(e.target.value),
|
|
2248
|
+
placeholder: "0.00",
|
|
1478
2249
|
style: {
|
|
1479
2250
|
flex: 1,
|
|
1480
2251
|
background: "transparent",
|
|
@@ -1506,154 +2277,248 @@ function SwypePayment({
|
|
|
1506
2277
|
]
|
|
1507
2278
|
}
|
|
1508
2279
|
),
|
|
1509
|
-
/* @__PURE__ */
|
|
2280
|
+
/* @__PURE__ */ jsx(
|
|
1510
2281
|
"div",
|
|
1511
2282
|
{
|
|
1512
2283
|
style: {
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
border: `1px solid ${tokens.border}`,
|
|
1518
|
-
borderRadius: tokens.radius,
|
|
1519
|
-
padding: "4px 14px 4px 4px",
|
|
1520
|
-
marginBottom: "20px"
|
|
2284
|
+
fontSize: "0.8rem",
|
|
2285
|
+
color: tokens.textMuted,
|
|
2286
|
+
marginBottom: "20px",
|
|
2287
|
+
paddingLeft: "2px"
|
|
1521
2288
|
},
|
|
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
|
-
]
|
|
2289
|
+
children: loadingData ? /* @__PURE__ */ jsx("span", { children: "Loading balance..." }) : maxSourceBalance !== null && maxSourceBalance > 0 ? /* @__PURE__ */ jsxs("span", { children: [
|
|
2290
|
+
"Available: ",
|
|
2291
|
+
/* @__PURE__ */ jsxs("span", { style: { fontWeight: 600, color: tokens.textSecondary }, children: [
|
|
2292
|
+
"$",
|
|
2293
|
+
maxSourceBalance.toFixed(2)
|
|
2294
|
+
] })
|
|
2295
|
+
] }) : null
|
|
1574
2296
|
}
|
|
1575
2297
|
),
|
|
1576
2298
|
/* @__PURE__ */ jsx(
|
|
1577
|
-
"
|
|
2299
|
+
"button",
|
|
1578
2300
|
{
|
|
1579
|
-
style:
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
2301
|
+
style: canContinue ? btnPrimary : btnDisabled,
|
|
2302
|
+
disabled: !canContinue,
|
|
2303
|
+
onClick: () => {
|
|
2304
|
+
setError(null);
|
|
2305
|
+
setStep("ready");
|
|
1584
2306
|
},
|
|
1585
|
-
children: "
|
|
2307
|
+
children: "Continue"
|
|
1586
2308
|
}
|
|
1587
|
-
)
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
2309
|
+
)
|
|
2310
|
+
] });
|
|
2311
|
+
}
|
|
2312
|
+
if (step === "ready") {
|
|
2313
|
+
const parsedAmount = parseFloat(amount);
|
|
2314
|
+
const canPay = !isNaN(parsedAmount) && parsedAmount > 0 && !!sourceId && !loadingData;
|
|
2315
|
+
const noAccounts = !loadingData && accounts.length === 0;
|
|
2316
|
+
return /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
|
|
2317
|
+
stepBadge("Review & pay"),
|
|
2318
|
+
error && /* @__PURE__ */ jsx("div", { style: errorStyle, children: error }),
|
|
2319
|
+
loadingData ? /* @__PURE__ */ jsx("div", { style: { padding: "24px 0", textAlign: "center" }, children: /* @__PURE__ */ jsx(Spinner, { label: "Loading..." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2320
|
+
/* @__PURE__ */ jsxs(
|
|
2321
|
+
"div",
|
|
2322
|
+
{
|
|
2323
|
+
style: {
|
|
2324
|
+
textAlign: "center",
|
|
2325
|
+
marginBottom: "20px"
|
|
2326
|
+
},
|
|
2327
|
+
children: [
|
|
1603
2328
|
/* @__PURE__ */ jsxs(
|
|
1604
|
-
"
|
|
2329
|
+
"div",
|
|
1605
2330
|
{
|
|
1606
2331
|
style: {
|
|
1607
|
-
|
|
1608
|
-
|
|
2332
|
+
fontSize: "2rem",
|
|
2333
|
+
fontWeight: 700,
|
|
2334
|
+
color: tokens.text,
|
|
2335
|
+
lineHeight: 1.2
|
|
1609
2336
|
},
|
|
1610
2337
|
children: [
|
|
1611
|
-
|
|
1612
|
-
"
|
|
1613
|
-
destination.address.slice(-4)
|
|
2338
|
+
"$",
|
|
2339
|
+
parsedAmount > 0 ? parsedAmount.toFixed(2) : "0.00"
|
|
1614
2340
|
]
|
|
1615
2341
|
}
|
|
2342
|
+
),
|
|
2343
|
+
/* @__PURE__ */ jsx(
|
|
2344
|
+
"button",
|
|
2345
|
+
{
|
|
2346
|
+
onClick: () => setStep("enter-amount"),
|
|
2347
|
+
style: {
|
|
2348
|
+
background: "transparent",
|
|
2349
|
+
border: "none",
|
|
2350
|
+
cursor: "pointer",
|
|
2351
|
+
color: tokens.textMuted,
|
|
2352
|
+
fontSize: "0.75rem",
|
|
2353
|
+
fontFamily: "inherit",
|
|
2354
|
+
outline: "none",
|
|
2355
|
+
padding: "4px 8px",
|
|
2356
|
+
marginTop: "4px"
|
|
2357
|
+
},
|
|
2358
|
+
children: "Change amount"
|
|
2359
|
+
}
|
|
1616
2360
|
)
|
|
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",
|
|
2361
|
+
]
|
|
2362
|
+
}
|
|
2363
|
+
),
|
|
2364
|
+
/* @__PURE__ */ jsxs(
|
|
2365
|
+
"div",
|
|
1632
2366
|
{
|
|
1633
|
-
style:
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
2367
|
+
style: {
|
|
2368
|
+
fontSize: "0.825rem",
|
|
2369
|
+
color: tokens.textSecondary,
|
|
2370
|
+
marginBottom: "16px",
|
|
2371
|
+
padding: "12px 14px",
|
|
2372
|
+
background: tokens.bgInput,
|
|
2373
|
+
borderRadius: tokens.radius,
|
|
2374
|
+
lineHeight: 1.7
|
|
1637
2375
|
},
|
|
1638
|
-
children:
|
|
2376
|
+
children: [
|
|
2377
|
+
/* @__PURE__ */ jsxs(
|
|
2378
|
+
"div",
|
|
2379
|
+
{
|
|
2380
|
+
style: { display: "flex", justifyContent: "space-between" },
|
|
2381
|
+
children: [
|
|
2382
|
+
/* @__PURE__ */ jsx("span", { children: "To" }),
|
|
2383
|
+
/* @__PURE__ */ jsxs(
|
|
2384
|
+
"span",
|
|
2385
|
+
{
|
|
2386
|
+
style: {
|
|
2387
|
+
fontFamily: '"SF Mono", "Fira Code", monospace',
|
|
2388
|
+
fontSize: "0.8rem"
|
|
2389
|
+
},
|
|
2390
|
+
children: [
|
|
2391
|
+
destination.address.slice(0, 6),
|
|
2392
|
+
"...",
|
|
2393
|
+
destination.address.slice(-4)
|
|
2394
|
+
]
|
|
2395
|
+
}
|
|
2396
|
+
)
|
|
2397
|
+
]
|
|
2398
|
+
}
|
|
2399
|
+
),
|
|
2400
|
+
/* @__PURE__ */ jsxs(
|
|
2401
|
+
"div",
|
|
2402
|
+
{
|
|
2403
|
+
style: { display: "flex", justifyContent: "space-between" },
|
|
2404
|
+
children: [
|
|
2405
|
+
/* @__PURE__ */ jsx("span", { children: "Token" }),
|
|
2406
|
+
/* @__PURE__ */ jsx("span", { style: { fontWeight: 600 }, children: destination.token.symbol })
|
|
2407
|
+
]
|
|
2408
|
+
}
|
|
2409
|
+
),
|
|
2410
|
+
/* @__PURE__ */ jsxs(
|
|
2411
|
+
"div",
|
|
2412
|
+
{
|
|
2413
|
+
style: {
|
|
2414
|
+
display: "flex",
|
|
2415
|
+
justifyContent: "space-between",
|
|
2416
|
+
alignItems: "center"
|
|
2417
|
+
},
|
|
2418
|
+
children: [
|
|
2419
|
+
/* @__PURE__ */ jsx("span", { children: "From" }),
|
|
2420
|
+
noAccounts ? /* @__PURE__ */ jsx("span", { style: { fontWeight: 500, color: tokens.textMuted }, children: "New account" }) : /* @__PURE__ */ jsx(
|
|
2421
|
+
AccountDropdown,
|
|
2422
|
+
{
|
|
2423
|
+
accounts,
|
|
2424
|
+
selectedAccountId,
|
|
2425
|
+
selectedWalletId,
|
|
2426
|
+
onSelect: (id) => {
|
|
2427
|
+
setSelectedAccountId(id);
|
|
2428
|
+
setSelectedWalletId(null);
|
|
2429
|
+
setConnectingNewAccount(false);
|
|
2430
|
+
setSelectedProviderId(null);
|
|
2431
|
+
},
|
|
2432
|
+
onWalletSelect: (accountId, walletId) => {
|
|
2433
|
+
setSelectedAccountId(accountId);
|
|
2434
|
+
setSelectedWalletId(walletId);
|
|
2435
|
+
setConnectingNewAccount(false);
|
|
2436
|
+
setSelectedProviderId(null);
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
)
|
|
2440
|
+
]
|
|
2441
|
+
}
|
|
2442
|
+
)
|
|
2443
|
+
]
|
|
1639
2444
|
}
|
|
1640
2445
|
),
|
|
2446
|
+
noAccounts && /* @__PURE__ */ jsxs("div", { style: { marginBottom: "16px" }, children: [
|
|
2447
|
+
/* @__PURE__ */ jsx(
|
|
2448
|
+
"label",
|
|
2449
|
+
{
|
|
2450
|
+
style: {
|
|
2451
|
+
display: "block",
|
|
2452
|
+
fontSize: "0.8rem",
|
|
2453
|
+
color: tokens.textMuted,
|
|
2454
|
+
marginBottom: "8px",
|
|
2455
|
+
fontWeight: 500,
|
|
2456
|
+
textTransform: "uppercase",
|
|
2457
|
+
letterSpacing: "0.05em"
|
|
2458
|
+
},
|
|
2459
|
+
children: "Connect a wallet"
|
|
2460
|
+
}
|
|
2461
|
+
),
|
|
2462
|
+
/* @__PURE__ */ jsx(
|
|
2463
|
+
"div",
|
|
2464
|
+
{
|
|
2465
|
+
style: {
|
|
2466
|
+
display: "flex",
|
|
2467
|
+
flexDirection: "column",
|
|
2468
|
+
gap: "8px"
|
|
2469
|
+
},
|
|
2470
|
+
children: providers.map((p) => /* @__PURE__ */ jsx(
|
|
2471
|
+
ProviderCard,
|
|
2472
|
+
{
|
|
2473
|
+
provider: p,
|
|
2474
|
+
selected: selectedProviderId === p.id,
|
|
2475
|
+
onClick: () => {
|
|
2476
|
+
setSelectedProviderId(p.id);
|
|
2477
|
+
setSelectedAccountId(null);
|
|
2478
|
+
setConnectingNewAccount(false);
|
|
2479
|
+
}
|
|
2480
|
+
},
|
|
2481
|
+
p.id
|
|
2482
|
+
))
|
|
2483
|
+
}
|
|
2484
|
+
)
|
|
2485
|
+
] }),
|
|
1641
2486
|
/* @__PURE__ */ jsxs(
|
|
1642
2487
|
"button",
|
|
1643
2488
|
{
|
|
1644
|
-
style:
|
|
1645
|
-
disabled: !
|
|
2489
|
+
style: canPay ? btnPrimary : btnDisabled,
|
|
2490
|
+
disabled: !canPay,
|
|
1646
2491
|
onClick: handlePay,
|
|
1647
2492
|
children: [
|
|
1648
2493
|
"Pay $",
|
|
1649
|
-
|
|
2494
|
+
parsedAmount > 0 ? parsedAmount.toFixed(2) : "0.00"
|
|
1650
2495
|
]
|
|
1651
2496
|
}
|
|
2497
|
+
),
|
|
2498
|
+
!noAccounts && /* @__PURE__ */ jsx(
|
|
2499
|
+
AdvancedSettings,
|
|
2500
|
+
{
|
|
2501
|
+
settings: advancedSettings,
|
|
2502
|
+
onChange: setAdvancedSettings,
|
|
2503
|
+
chains,
|
|
2504
|
+
providers,
|
|
2505
|
+
onConnectNewAccount: handleConnectNewAccount,
|
|
2506
|
+
connectingNewAccount
|
|
2507
|
+
}
|
|
1652
2508
|
)
|
|
1653
2509
|
] })
|
|
1654
2510
|
] });
|
|
1655
2511
|
}
|
|
1656
2512
|
if (step === "processing") {
|
|
2513
|
+
if (authExecutor.pendingAllowanceSelection) {
|
|
2514
|
+
return /* @__PURE__ */ jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsx(
|
|
2515
|
+
AllowanceSelector,
|
|
2516
|
+
{
|
|
2517
|
+
action: authExecutor.pendingAllowanceSelection,
|
|
2518
|
+
onSelect: authExecutor.resolveAllowanceSelection
|
|
2519
|
+
}
|
|
2520
|
+
) });
|
|
2521
|
+
}
|
|
1657
2522
|
const statusLabel = creatingTransfer ? "Creating transfer..." : mobileFlow ? "Waiting for authorization..." : authExecutor.executing ? "Authorizing..." : polling.isPolling ? "Processing payment..." : "Please wait...";
|
|
1658
2523
|
const statusDescription = creatingTransfer ? "Setting up your transfer..." : mobileFlow ? "Complete the authorization in your wallet app, then return here." : authExecutor.executing ? "Complete the wallet prompts to authorize this payment." : polling.isPolling ? "Your payment is being processed. This usually takes a few moments." : "Hang tight...";
|
|
1659
2524
|
return /* @__PURE__ */ jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "16px 0" }, children: [
|
|
@@ -1830,6 +2695,6 @@ function SwypePayment({
|
|
|
1830
2695
|
return null;
|
|
1831
2696
|
}
|
|
1832
2697
|
|
|
1833
|
-
export { SwypePayment, SwypeProvider, darkTheme, getTheme, lightTheme, api_exports as swypeApi, useAuthorizationExecutor, useSwypeConfig, useTransferPolling };
|
|
2698
|
+
export { SwypePayment, SwypeProvider, darkTheme, getTheme, lightTheme, api_exports as swypeApi, useAuthorizationExecutor, useSwypeConfig, useSwypeDepositAmount, useTransferPolling };
|
|
1834
2699
|
//# sourceMappingURL=index.js.map
|
|
1835
2700
|
//# sourceMappingURL=index.js.map
|