@swype-org/react-sdk 0.1.217 → 0.1.219
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 +765 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +73 -1
- package/dist/index.d.ts +73 -1
- package/dist/index.js +766 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,8 +5,9 @@ import { mainnet, arbitrum, base, polygon, bsc } from 'wagmi/chains';
|
|
|
5
5
|
import { injected } from 'wagmi/connectors';
|
|
6
6
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
7
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
|
-
import { recoverTypedDataAddress, decodeAbiParameters, walletActions, createClient, custom } from 'viem';
|
|
8
|
+
import { recoverTypedDataAddress, decodeAbiParameters, walletActions, hexToString, createClient, custom } from 'viem';
|
|
9
9
|
import { parseErc6492Signature, parseAccount, getAddress } from 'viem/utils';
|
|
10
|
+
import { waitForTransactionReceipt as waitForTransactionReceipt$1, getTransaction, call } from 'viem/actions';
|
|
10
11
|
|
|
11
12
|
var __defProp = Object.defineProperty;
|
|
12
13
|
var __export = (target, all) => {
|
|
@@ -154,6 +155,17 @@ function useBlinkDepositAmount() {
|
|
|
154
155
|
};
|
|
155
156
|
}
|
|
156
157
|
|
|
158
|
+
// node_modules/@wagmi/core/dist/esm/utils/getAction.js
|
|
159
|
+
function getAction(client, actionFn, name) {
|
|
160
|
+
const action_implicit = client[actionFn.name];
|
|
161
|
+
if (typeof action_implicit === "function")
|
|
162
|
+
return action_implicit;
|
|
163
|
+
const action_explicit = client[name];
|
|
164
|
+
if (typeof action_explicit === "function")
|
|
165
|
+
return action_explicit;
|
|
166
|
+
return (params) => actionFn(client, params);
|
|
167
|
+
}
|
|
168
|
+
|
|
157
169
|
// node_modules/@wagmi/core/dist/esm/version.js
|
|
158
170
|
var version = "2.22.1";
|
|
159
171
|
|
|
@@ -413,24 +425,57 @@ async function getWalletClient(config, parameters = {}) {
|
|
|
413
425
|
const client = await getConnectorClient(config, parameters);
|
|
414
426
|
return client.extend(walletActions);
|
|
415
427
|
}
|
|
428
|
+
async function waitForTransactionReceipt(config, parameters) {
|
|
429
|
+
const { chainId, timeout = 0, ...rest } = parameters;
|
|
430
|
+
const client = config.getClient({ chainId });
|
|
431
|
+
const action = getAction(client, waitForTransactionReceipt$1, "waitForTransactionReceipt");
|
|
432
|
+
const receipt = await action({ ...rest, timeout });
|
|
433
|
+
if (receipt.status === "reverted") {
|
|
434
|
+
const action_getTransaction = getAction(client, getTransaction, "getTransaction");
|
|
435
|
+
const { from: account, ...txn } = await action_getTransaction({
|
|
436
|
+
hash: receipt.transactionHash
|
|
437
|
+
});
|
|
438
|
+
const action_call = getAction(client, call, "call");
|
|
439
|
+
const code = await action_call({
|
|
440
|
+
...txn,
|
|
441
|
+
account,
|
|
442
|
+
data: txn.input,
|
|
443
|
+
gasPrice: txn.type !== "eip1559" ? txn.gasPrice : void 0,
|
|
444
|
+
maxFeePerGas: txn.type === "eip1559" ? txn.maxFeePerGas : void 0,
|
|
445
|
+
maxPriorityFeePerGas: txn.type === "eip1559" ? txn.maxPriorityFeePerGas : void 0
|
|
446
|
+
});
|
|
447
|
+
const reason = code?.data ? hexToString(`0x${code.data.substring(138)}`) : "unknown reason";
|
|
448
|
+
throw new Error(reason);
|
|
449
|
+
}
|
|
450
|
+
return {
|
|
451
|
+
...receipt,
|
|
452
|
+
chainId: client.chain.id
|
|
453
|
+
};
|
|
454
|
+
}
|
|
416
455
|
|
|
417
456
|
// src/api.ts
|
|
418
457
|
var api_exports = {};
|
|
419
458
|
__export(api_exports, {
|
|
420
459
|
createAccount: () => createAccount,
|
|
421
460
|
createAccountAuthorizationSession: () => createAccountAuthorizationSession,
|
|
461
|
+
createGuestTransfer: () => createGuestTransfer,
|
|
422
462
|
createTransfer: () => createTransfer,
|
|
423
463
|
fetchAccount: () => fetchAccount,
|
|
424
464
|
fetchAccounts: () => fetchAccounts,
|
|
425
465
|
fetchAuthorizationSession: () => fetchAuthorizationSession,
|
|
426
466
|
fetchChains: () => fetchChains,
|
|
467
|
+
fetchGuestTransferBalances: () => fetchGuestTransferBalances,
|
|
427
468
|
fetchMerchantPublicKey: () => fetchMerchantPublicKey,
|
|
428
469
|
fetchProviders: () => fetchProviders,
|
|
429
470
|
fetchTransfer: () => fetchTransfer,
|
|
430
471
|
fetchUserConfig: () => fetchUserConfig,
|
|
472
|
+
getGuestTransfer: () => getGuestTransfer,
|
|
473
|
+
getTransferByGuestToken: () => getTransferByGuestToken,
|
|
431
474
|
registerPasskey: () => registerPasskey,
|
|
432
475
|
reportActionCompletion: () => reportActionCompletion,
|
|
433
476
|
reportPasskeyActivity: () => reportPasskeyActivity,
|
|
477
|
+
setTransferSender: () => setTransferSender,
|
|
478
|
+
signGuestTransfer: () => signGuestTransfer,
|
|
434
479
|
signTransfer: () => signTransfer,
|
|
435
480
|
updateUserConfig: () => updateUserConfig,
|
|
436
481
|
updateUserConfigBySession: () => updateUserConfigBySession
|
|
@@ -643,6 +688,79 @@ async function updateUserConfigBySession(apiBaseUrl, sessionId, config) {
|
|
|
643
688
|
);
|
|
644
689
|
if (!res.ok) await throwApiError(res);
|
|
645
690
|
}
|
|
691
|
+
async function createGuestTransfer(apiBaseUrl, params) {
|
|
692
|
+
const body = {
|
|
693
|
+
id: params.id ?? crypto.randomUUID(),
|
|
694
|
+
type: "guest",
|
|
695
|
+
merchantAuthorization: params.merchantAuthorization,
|
|
696
|
+
destinations: params.destinations,
|
|
697
|
+
amount: {
|
|
698
|
+
amount: params.amount,
|
|
699
|
+
currency: params.currency ?? "USD"
|
|
700
|
+
},
|
|
701
|
+
providerId: params.providerId
|
|
702
|
+
};
|
|
703
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers`, {
|
|
704
|
+
method: "POST",
|
|
705
|
+
headers: { "Content-Type": "application/json" },
|
|
706
|
+
body: JSON.stringify(body)
|
|
707
|
+
});
|
|
708
|
+
if (!res.ok) await throwApiError(res);
|
|
709
|
+
return await res.json();
|
|
710
|
+
}
|
|
711
|
+
async function getTransferByGuestToken(apiBaseUrl, guestToken) {
|
|
712
|
+
const params = new URLSearchParams({ guestToken });
|
|
713
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers?${params.toString()}`);
|
|
714
|
+
if (!res.ok) await throwApiError(res);
|
|
715
|
+
return await res.json();
|
|
716
|
+
}
|
|
717
|
+
async function setTransferSender(apiBaseUrl, transferId, guestSessionToken, senderAddress, sourceChainId, sourceToken) {
|
|
718
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}/sender`, {
|
|
719
|
+
method: "PUT",
|
|
720
|
+
headers: {
|
|
721
|
+
"Content-Type": "application/json",
|
|
722
|
+
"x-guest-session-token": guestSessionToken
|
|
723
|
+
},
|
|
724
|
+
body: JSON.stringify({ senderAddress, sourceChainId, sourceToken })
|
|
725
|
+
});
|
|
726
|
+
if (!res.ok) await throwApiError(res);
|
|
727
|
+
return await res.json();
|
|
728
|
+
}
|
|
729
|
+
async function signGuestTransfer(apiBaseUrl, transferId, guestSessionToken, originTxHash) {
|
|
730
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
|
|
731
|
+
method: "PATCH",
|
|
732
|
+
headers: {
|
|
733
|
+
"Content-Type": "application/json",
|
|
734
|
+
"x-guest-session-token": guestSessionToken
|
|
735
|
+
},
|
|
736
|
+
body: JSON.stringify({ originTxHash })
|
|
737
|
+
});
|
|
738
|
+
if (!res.ok) await throwApiError(res);
|
|
739
|
+
return await res.json();
|
|
740
|
+
}
|
|
741
|
+
async function getGuestTransfer(apiBaseUrl, transferId, guestSessionToken) {
|
|
742
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
|
|
743
|
+
headers: {
|
|
744
|
+
"x-guest-session-token": guestSessionToken
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
if (!res.ok) await throwApiError(res);
|
|
748
|
+
return await res.json();
|
|
749
|
+
}
|
|
750
|
+
async function fetchGuestTransferBalances(apiBaseUrl, transferId, guestSessionToken, walletAddress) {
|
|
751
|
+
const params = new URLSearchParams({ walletAddress });
|
|
752
|
+
const res = await fetch(
|
|
753
|
+
`${apiBaseUrl}/v1/transfers/${transferId}/balances?${params.toString()}`,
|
|
754
|
+
{
|
|
755
|
+
headers: {
|
|
756
|
+
"x-guest-session-token": guestSessionToken
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
);
|
|
760
|
+
if (!res.ok) await throwApiError(res);
|
|
761
|
+
const data = await res.json();
|
|
762
|
+
return data.items;
|
|
763
|
+
}
|
|
646
764
|
async function reportActionCompletion(apiBaseUrl, actionId, result) {
|
|
647
765
|
const res = await fetch(
|
|
648
766
|
`${apiBaseUrl}/v1/authorization-actions/${actionId}`,
|
|
@@ -1789,8 +1907,9 @@ function deriveSourceTypeAndId(state) {
|
|
|
1789
1907
|
return { sourceType: "accountId", sourceId: "" };
|
|
1790
1908
|
}
|
|
1791
1909
|
function createInitialState(config) {
|
|
1910
|
+
const isReturningUser = config.activeCredentialId != null;
|
|
1792
1911
|
return {
|
|
1793
|
-
step: "login",
|
|
1912
|
+
step: isReturningUser ? "login" : "wallet-picker",
|
|
1794
1913
|
error: null,
|
|
1795
1914
|
providers: [],
|
|
1796
1915
|
accounts: [],
|
|
@@ -1813,7 +1932,10 @@ function createInitialState(config) {
|
|
|
1813
1932
|
mobileFlow: false,
|
|
1814
1933
|
deeplinkUri: null,
|
|
1815
1934
|
increasingLimit: false,
|
|
1816
|
-
previousStep: null
|
|
1935
|
+
previousStep: null,
|
|
1936
|
+
isGuestFlow: false,
|
|
1937
|
+
guestTransferId: null,
|
|
1938
|
+
guestSessionToken: null
|
|
1817
1939
|
};
|
|
1818
1940
|
}
|
|
1819
1941
|
function paymentReducer(state, action) {
|
|
@@ -2036,6 +2158,27 @@ function paymentReducer(state, action) {
|
|
|
2036
2158
|
mobileFlow: true,
|
|
2037
2159
|
deeplinkUri: action.deeplinkUri
|
|
2038
2160
|
};
|
|
2161
|
+
// ── Guest checkout ────────────────────────────────────────────
|
|
2162
|
+
case "GUEST_PROVIDER_SELECTED":
|
|
2163
|
+
return {
|
|
2164
|
+
...state,
|
|
2165
|
+
isGuestFlow: true,
|
|
2166
|
+
selectedProviderId: action.providerId,
|
|
2167
|
+
guestTransferId: action.transferId,
|
|
2168
|
+
guestSessionToken: action.guestSessionToken,
|
|
2169
|
+
selectedAccountId: null,
|
|
2170
|
+
selectedWalletId: null,
|
|
2171
|
+
selectedTokenSymbol: null,
|
|
2172
|
+
step: "token-picker"
|
|
2173
|
+
};
|
|
2174
|
+
case "GUEST_TRANSFER_COMPLETED":
|
|
2175
|
+
return {
|
|
2176
|
+
...state,
|
|
2177
|
+
transfer: action.transfer,
|
|
2178
|
+
step: "success",
|
|
2179
|
+
mobileFlow: false,
|
|
2180
|
+
deeplinkUri: null
|
|
2181
|
+
};
|
|
2039
2182
|
// ── Navigation & error ───────────────────────────────────────
|
|
2040
2183
|
case "NAVIGATE":
|
|
2041
2184
|
return { ...state, step: action.step, previousStep: state.step, error: null };
|
|
@@ -2045,7 +2188,7 @@ function paymentReducer(state, action) {
|
|
|
2045
2188
|
case "NEW_PAYMENT":
|
|
2046
2189
|
return {
|
|
2047
2190
|
...state,
|
|
2048
|
-
step: "deposit",
|
|
2191
|
+
step: state.isGuestFlow ? "wallet-picker" : "deposit",
|
|
2049
2192
|
transfer: null,
|
|
2050
2193
|
error: null,
|
|
2051
2194
|
amount: action.depositAmount != null ? action.depositAmount.toString() : "",
|
|
@@ -2053,7 +2196,10 @@ function paymentReducer(state, action) {
|
|
|
2053
2196
|
deeplinkUri: null,
|
|
2054
2197
|
selectedProviderId: null,
|
|
2055
2198
|
selectedWalletId: null,
|
|
2056
|
-
selectedAccountId: action.firstAccountId
|
|
2199
|
+
selectedAccountId: action.firstAccountId,
|
|
2200
|
+
isGuestFlow: false,
|
|
2201
|
+
guestTransferId: null,
|
|
2202
|
+
guestSessionToken: null
|
|
2057
2203
|
};
|
|
2058
2204
|
case "LOGOUT":
|
|
2059
2205
|
return {
|
|
@@ -3236,7 +3382,9 @@ function WalletPickerScreen({
|
|
|
3236
3382
|
onSelectProvider,
|
|
3237
3383
|
onContinueConnection,
|
|
3238
3384
|
onBack,
|
|
3239
|
-
onLogout
|
|
3385
|
+
onLogout,
|
|
3386
|
+
onLogin,
|
|
3387
|
+
showLoginOption
|
|
3240
3388
|
}) {
|
|
3241
3389
|
const { tokens } = useBlinkConfig();
|
|
3242
3390
|
const [hoveredId, setHoveredId] = useState(null);
|
|
@@ -3264,13 +3412,8 @@ function WalletPickerScreen({
|
|
|
3264
3412
|
}
|
|
3265
3413
|
}, [onPrepareProvider]);
|
|
3266
3414
|
const hasPending = pendingConnections != null && pendingConnections.length > 0;
|
|
3267
|
-
const
|
|
3268
|
-
|
|
3269
|
-
{ id: "rabby", name: "Rabby" },
|
|
3270
|
-
{ id: "ora", name: "Ora" },
|
|
3271
|
-
{ id: "phantom", name: "Phantom" }
|
|
3272
|
-
];
|
|
3273
|
-
const selectedProvider = displayProviders.find((p) => p.id === selectedProviderId);
|
|
3415
|
+
const providersLoading = providers.length === 0;
|
|
3416
|
+
const selectedProvider = providers.find((p) => p.id === selectedProviderId);
|
|
3274
3417
|
if (loading) {
|
|
3275
3418
|
return /* @__PURE__ */ jsxs(ScreenLayout, { children: [
|
|
3276
3419
|
/* @__PURE__ */ jsx(ScreenHeader, { title: "Set up Blink", onBack, onLogout }),
|
|
@@ -3365,7 +3508,8 @@ function WalletPickerScreen({
|
|
|
3365
3508
|
]
|
|
3366
3509
|
}
|
|
3367
3510
|
),
|
|
3368
|
-
cryptoExpanded && /* @__PURE__ */ jsx("div", { style:
|
|
3511
|
+
cryptoExpanded && providersLoading && /* @__PURE__ */ jsx("div", { style: { textAlign: "center", padding: "24px 0" }, children: /* @__PURE__ */ jsx(Spinner, { label: "Loading wallets..." }) }),
|
|
3512
|
+
cryptoExpanded && !providersLoading && /* @__PURE__ */ jsx("div", { style: gridStyle, children: providers.map((p) => {
|
|
3369
3513
|
const logoSrc = "logoURI" in p && p.logoURI || KNOWN_LOGOS[p.name.toLowerCase()];
|
|
3370
3514
|
const emoji = WALLET_EMOJIS[p.name.toLowerCase()] ?? p.name.charAt(0);
|
|
3371
3515
|
const isSelected = selectedProviderId === p.id;
|
|
@@ -3395,6 +3539,18 @@ function WalletPickerScreen({
|
|
|
3395
3539
|
/* @__PURE__ */ jsxs("div", { style: categoryRowStyle(tokens, false, true), children: [
|
|
3396
3540
|
/* @__PURE__ */ jsx("span", { style: categoryLabelStyle, children: "Bank Account" }),
|
|
3397
3541
|
/* @__PURE__ */ jsx("span", { style: comingSoonBadgeStyle(tokens), children: "Coming Soon" })
|
|
3542
|
+
] }),
|
|
3543
|
+
showLoginOption && onLogin && /* @__PURE__ */ jsxs("div", { style: loginOptionStyle, children: [
|
|
3544
|
+
/* @__PURE__ */ jsx("span", { style: loginTextStyle(tokens.textSecondary), children: "Already have an account?" }),
|
|
3545
|
+
/* @__PURE__ */ jsx(
|
|
3546
|
+
"button",
|
|
3547
|
+
{
|
|
3548
|
+
type: "button",
|
|
3549
|
+
onClick: onLogin,
|
|
3550
|
+
style: loginButtonStyle(tokens.accent),
|
|
3551
|
+
children: "Log in"
|
|
3552
|
+
}
|
|
3553
|
+
)
|
|
3398
3554
|
] })
|
|
3399
3555
|
]
|
|
3400
3556
|
}
|
|
@@ -3561,6 +3717,28 @@ var dividerTextStyle = (color) => ({
|
|
|
3561
3717
|
color,
|
|
3562
3718
|
whiteSpace: "nowrap"
|
|
3563
3719
|
});
|
|
3720
|
+
var loginOptionStyle = {
|
|
3721
|
+
display: "flex",
|
|
3722
|
+
alignItems: "center",
|
|
3723
|
+
justifyContent: "center",
|
|
3724
|
+
gap: 6,
|
|
3725
|
+
padding: "12px 0 4px"
|
|
3726
|
+
};
|
|
3727
|
+
var loginTextStyle = (color) => ({
|
|
3728
|
+
fontSize: "0.85rem",
|
|
3729
|
+
color
|
|
3730
|
+
});
|
|
3731
|
+
var loginButtonStyle = (accentColor) => ({
|
|
3732
|
+
fontSize: "0.85rem",
|
|
3733
|
+
fontWeight: 600,
|
|
3734
|
+
color: accentColor,
|
|
3735
|
+
background: "none",
|
|
3736
|
+
border: "none",
|
|
3737
|
+
cursor: "pointer",
|
|
3738
|
+
padding: 0,
|
|
3739
|
+
fontFamily: "inherit",
|
|
3740
|
+
textDecoration: "underline"
|
|
3741
|
+
});
|
|
3564
3742
|
var DEFAULT_MAX = 1e7;
|
|
3565
3743
|
var ABSOLUTE_MIN = 0.01;
|
|
3566
3744
|
var PRESETS = [100, 250, 1e3];
|
|
@@ -5398,6 +5576,179 @@ var selectCircleSelectedStyle = (color) => ({
|
|
|
5398
5576
|
justifyContent: "center",
|
|
5399
5577
|
flexShrink: 0
|
|
5400
5578
|
});
|
|
5579
|
+
function GuestTokenPickerScreen({
|
|
5580
|
+
entries,
|
|
5581
|
+
loading,
|
|
5582
|
+
setting,
|
|
5583
|
+
depositAmount,
|
|
5584
|
+
error,
|
|
5585
|
+
onSelect,
|
|
5586
|
+
onBack
|
|
5587
|
+
}) {
|
|
5588
|
+
const { tokens: t } = useBlinkConfig();
|
|
5589
|
+
if (loading) {
|
|
5590
|
+
return /* @__PURE__ */ jsxs(ScreenLayout, { children: [
|
|
5591
|
+
/* @__PURE__ */ jsx(ScreenHeader, { title: "Select Token", onBack }),
|
|
5592
|
+
/* @__PURE__ */ jsx("div", { style: loadingWrapStyle, children: /* @__PURE__ */ jsx(Spinner, { label: "Loading balances..." }) })
|
|
5593
|
+
] });
|
|
5594
|
+
}
|
|
5595
|
+
return /* @__PURE__ */ jsxs(ScreenLayout, { footer: /* @__PURE__ */ jsx(PoweredByFooter, {}), children: [
|
|
5596
|
+
/* @__PURE__ */ jsx(ScreenHeader, { title: "Select Token", onBack }),
|
|
5597
|
+
depositAmount != null && /* @__PURE__ */ jsxs("div", { style: depositHeaderStyle, children: [
|
|
5598
|
+
/* @__PURE__ */ jsx("div", { style: depositLabelStyle3(t.textMuted), children: "Depositing" }),
|
|
5599
|
+
/* @__PURE__ */ jsxs("div", { style: depositAmountStyle2(t.text), children: [
|
|
5600
|
+
"$",
|
|
5601
|
+
depositAmount.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
|
5602
|
+
] })
|
|
5603
|
+
] }),
|
|
5604
|
+
error && /* @__PURE__ */ jsx("p", { style: errorStyle3(t.error), children: error }),
|
|
5605
|
+
/* @__PURE__ */ jsx("div", { style: sectionLabelStyle2(t.textMuted), children: "Choose token to pay with" }),
|
|
5606
|
+
/* @__PURE__ */ jsx("div", { style: tokenListStyle3, children: entries.map((entry) => /* @__PURE__ */ jsxs(
|
|
5607
|
+
"button",
|
|
5608
|
+
{
|
|
5609
|
+
type: "button",
|
|
5610
|
+
onClick: () => onSelect(entry),
|
|
5611
|
+
disabled: setting,
|
|
5612
|
+
style: tokenRowStyle3(t, setting),
|
|
5613
|
+
children: [
|
|
5614
|
+
/* @__PURE__ */ jsx("div", { style: tokenIconCircleStyle3(t, !!TOKEN_LOGOS[entry.tokenSymbol]), children: TOKEN_LOGOS[entry.tokenSymbol] ? /* @__PURE__ */ jsx("img", { src: TOKEN_LOGOS[entry.tokenSymbol], alt: entry.tokenSymbol, style: tokenLogoImgStyle3 }) : /* @__PURE__ */ jsx("span", { style: tokenIconTextStyle3(t.textMuted), children: "$" }) }),
|
|
5615
|
+
/* @__PURE__ */ jsxs("div", { style: tokenInfoStyle3, children: [
|
|
5616
|
+
/* @__PURE__ */ jsxs("div", { style: tokenNameRowStyle2, children: [
|
|
5617
|
+
/* @__PURE__ */ jsx("span", { style: tokenSymbolTextStyle2(t.text), children: entry.tokenSymbol }),
|
|
5618
|
+
/* @__PURE__ */ jsx("span", { style: tokenChainDotStyle2(t.textMuted), children: "\xB7" }),
|
|
5619
|
+
/* @__PURE__ */ jsx("span", { style: tokenChainTextStyle2(t.textMuted), children: entry.chainName })
|
|
5620
|
+
] }),
|
|
5621
|
+
/* @__PURE__ */ jsxs("span", { style: tokenBalanceStyle2(t.textMuted), children: [
|
|
5622
|
+
"$",
|
|
5623
|
+
entry.balance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
|
5624
|
+
] })
|
|
5625
|
+
] }),
|
|
5626
|
+
/* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: chevronStyle, children: /* @__PURE__ */ jsx("path", { d: "M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z", fill: t.textMuted }) })
|
|
5627
|
+
]
|
|
5628
|
+
},
|
|
5629
|
+
`${entry.chainId}-${entry.tokenAddress}`
|
|
5630
|
+
)) }),
|
|
5631
|
+
entries.length === 0 && /* @__PURE__ */ jsx("p", { style: emptyStyle(t.textMuted), children: "No supported tokens found in your wallet. Please ensure you have USDC or USDT." })
|
|
5632
|
+
] });
|
|
5633
|
+
}
|
|
5634
|
+
var loadingWrapStyle = {
|
|
5635
|
+
textAlign: "center",
|
|
5636
|
+
padding: "48px 0",
|
|
5637
|
+
flex: 1,
|
|
5638
|
+
display: "flex",
|
|
5639
|
+
alignItems: "center",
|
|
5640
|
+
justifyContent: "center"
|
|
5641
|
+
};
|
|
5642
|
+
var depositHeaderStyle = {
|
|
5643
|
+
marginBottom: 20
|
|
5644
|
+
};
|
|
5645
|
+
var depositLabelStyle3 = (color) => ({
|
|
5646
|
+
fontSize: "0.75rem",
|
|
5647
|
+
fontWeight: 500,
|
|
5648
|
+
color,
|
|
5649
|
+
marginBottom: 4
|
|
5650
|
+
});
|
|
5651
|
+
var depositAmountStyle2 = (color) => ({
|
|
5652
|
+
fontSize: "2.4rem",
|
|
5653
|
+
fontWeight: 700,
|
|
5654
|
+
letterSpacing: "-0.02em",
|
|
5655
|
+
color
|
|
5656
|
+
});
|
|
5657
|
+
var errorStyle3 = (color) => ({
|
|
5658
|
+
fontSize: "0.84rem",
|
|
5659
|
+
color,
|
|
5660
|
+
margin: "0 0 12px",
|
|
5661
|
+
lineHeight: 1.5
|
|
5662
|
+
});
|
|
5663
|
+
var sectionLabelStyle2 = (color) => ({
|
|
5664
|
+
fontSize: "0.84rem",
|
|
5665
|
+
fontWeight: 500,
|
|
5666
|
+
color,
|
|
5667
|
+
marginBottom: 12
|
|
5668
|
+
});
|
|
5669
|
+
var tokenListStyle3 = {
|
|
5670
|
+
display: "flex",
|
|
5671
|
+
flexDirection: "column",
|
|
5672
|
+
gap: 10
|
|
5673
|
+
};
|
|
5674
|
+
var tokenRowStyle3 = (tokens, disabled) => ({
|
|
5675
|
+
display: "flex",
|
|
5676
|
+
alignItems: "center",
|
|
5677
|
+
gap: 14,
|
|
5678
|
+
padding: "14px 16px",
|
|
5679
|
+
background: tokens.bgInput,
|
|
5680
|
+
border: `1px solid ${tokens.border}`,
|
|
5681
|
+
borderRadius: 16,
|
|
5682
|
+
cursor: disabled ? "default" : "pointer",
|
|
5683
|
+
fontFamily: "inherit",
|
|
5684
|
+
textAlign: "left",
|
|
5685
|
+
width: "100%",
|
|
5686
|
+
opacity: disabled ? 0.6 : 1,
|
|
5687
|
+
transition: "opacity 0.15s ease"
|
|
5688
|
+
});
|
|
5689
|
+
var tokenIconCircleStyle3 = (tokens, hasLogo) => ({
|
|
5690
|
+
width: 36,
|
|
5691
|
+
height: 36,
|
|
5692
|
+
borderRadius: "50%",
|
|
5693
|
+
border: hasLogo ? "none" : `1.5px solid ${tokens.border}`,
|
|
5694
|
+
display: "flex",
|
|
5695
|
+
alignItems: "center",
|
|
5696
|
+
justifyContent: "center",
|
|
5697
|
+
flexShrink: 0,
|
|
5698
|
+
overflow: "hidden"
|
|
5699
|
+
});
|
|
5700
|
+
var tokenLogoImgStyle3 = {
|
|
5701
|
+
width: 36,
|
|
5702
|
+
height: 36,
|
|
5703
|
+
borderRadius: "50%",
|
|
5704
|
+
objectFit: "cover"
|
|
5705
|
+
};
|
|
5706
|
+
var tokenIconTextStyle3 = (color) => ({
|
|
5707
|
+
fontSize: "1rem",
|
|
5708
|
+
fontWeight: 700,
|
|
5709
|
+
color
|
|
5710
|
+
});
|
|
5711
|
+
var tokenInfoStyle3 = {
|
|
5712
|
+
display: "flex",
|
|
5713
|
+
flexDirection: "column",
|
|
5714
|
+
gap: 2,
|
|
5715
|
+
flex: 1,
|
|
5716
|
+
minWidth: 0
|
|
5717
|
+
};
|
|
5718
|
+
var tokenNameRowStyle2 = {
|
|
5719
|
+
display: "flex",
|
|
5720
|
+
alignItems: "center",
|
|
5721
|
+
gap: 4
|
|
5722
|
+
};
|
|
5723
|
+
var tokenSymbolTextStyle2 = (color) => ({
|
|
5724
|
+
fontSize: "0.92rem",
|
|
5725
|
+
fontWeight: 600,
|
|
5726
|
+
color
|
|
5727
|
+
});
|
|
5728
|
+
var tokenChainDotStyle2 = (color) => ({
|
|
5729
|
+
fontSize: "0.8rem",
|
|
5730
|
+
color
|
|
5731
|
+
});
|
|
5732
|
+
var tokenChainTextStyle2 = (color) => ({
|
|
5733
|
+
fontSize: "0.84rem",
|
|
5734
|
+
fontWeight: 400,
|
|
5735
|
+
color
|
|
5736
|
+
});
|
|
5737
|
+
var tokenBalanceStyle2 = (color) => ({
|
|
5738
|
+
fontSize: "0.78rem",
|
|
5739
|
+
color
|
|
5740
|
+
});
|
|
5741
|
+
var chevronStyle = {
|
|
5742
|
+
flexShrink: 0,
|
|
5743
|
+
opacity: 0.4
|
|
5744
|
+
};
|
|
5745
|
+
var emptyStyle = (color) => ({
|
|
5746
|
+
fontSize: "0.88rem",
|
|
5747
|
+
color,
|
|
5748
|
+
textAlign: "center",
|
|
5749
|
+
padding: "32px 0",
|
|
5750
|
+
lineHeight: 1.5
|
|
5751
|
+
});
|
|
5401
5752
|
var LINK_STEPS = /* @__PURE__ */ new Set([
|
|
5402
5753
|
"create-passkey",
|
|
5403
5754
|
"verify-passkey",
|
|
@@ -5445,6 +5796,9 @@ function StepRendererContent({
|
|
|
5445
5796
|
selectSourceChoices,
|
|
5446
5797
|
selectSourceRecommended,
|
|
5447
5798
|
selectSourceAvailableBalance,
|
|
5799
|
+
guestTokenEntries,
|
|
5800
|
+
guestLoadingBalances,
|
|
5801
|
+
guestSettingSender,
|
|
5448
5802
|
authInput,
|
|
5449
5803
|
otpCode,
|
|
5450
5804
|
selectSourceChainName,
|
|
@@ -5526,6 +5880,7 @@ function StepRendererContent({
|
|
|
5526
5880
|
);
|
|
5527
5881
|
}
|
|
5528
5882
|
if (step === "wallet-picker") {
|
|
5883
|
+
const isEntryPoint = !state.isGuestFlow && !authenticated;
|
|
5529
5884
|
return /* @__PURE__ */ jsx(
|
|
5530
5885
|
WalletPickerScreen,
|
|
5531
5886
|
{
|
|
@@ -5538,8 +5893,10 @@ function StepRendererContent({
|
|
|
5538
5893
|
onPrepareProvider: handlers.onPrepareProvider,
|
|
5539
5894
|
onSelectProvider: handlers.onSelectProvider,
|
|
5540
5895
|
onContinueConnection: handlers.onContinueConnection,
|
|
5541
|
-
onBack: () => handlers.onNavigate(state.activeCredentialId ? "deposit" : "create-passkey"),
|
|
5542
|
-
onLogout: handlers.onLogout
|
|
5896
|
+
onBack: isEntryPoint ? onBack : () => handlers.onNavigate(state.activeCredentialId ? "deposit" : "create-passkey"),
|
|
5897
|
+
onLogout: authenticated ? handlers.onLogout : void 0,
|
|
5898
|
+
onLogin: handlers.onLogin,
|
|
5899
|
+
showLoginOption: isEntryPoint
|
|
5543
5900
|
}
|
|
5544
5901
|
);
|
|
5545
5902
|
}
|
|
@@ -5646,6 +6003,20 @@ function StepRendererContent({
|
|
|
5646
6003
|
);
|
|
5647
6004
|
}
|
|
5648
6005
|
if (step === "token-picker") {
|
|
6006
|
+
if (state.isGuestFlow) {
|
|
6007
|
+
return /* @__PURE__ */ jsx(
|
|
6008
|
+
GuestTokenPickerScreen,
|
|
6009
|
+
{
|
|
6010
|
+
entries: guestTokenEntries,
|
|
6011
|
+
loading: guestLoadingBalances,
|
|
6012
|
+
setting: guestSettingSender,
|
|
6013
|
+
depositAmount: depositAmount ?? void 0,
|
|
6014
|
+
error: state.error,
|
|
6015
|
+
onSelect: handlers.onSelectGuestToken,
|
|
6016
|
+
onBack: () => handlers.onNavigate("wallet-picker")
|
|
6017
|
+
}
|
|
6018
|
+
);
|
|
6019
|
+
}
|
|
5649
6020
|
if (!selectedAccount) {
|
|
5650
6021
|
return /* @__PURE__ */ jsx(BlinkLoadingScreen, {});
|
|
5651
6022
|
}
|
|
@@ -6401,12 +6772,68 @@ function useSourceSelectionHandlers(dispatch, authExecutor) {
|
|
|
6401
6772
|
preSelectSourceStepRef
|
|
6402
6773
|
};
|
|
6403
6774
|
}
|
|
6404
|
-
function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs) {
|
|
6775
|
+
function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, onComplete) {
|
|
6405
6776
|
const {
|
|
6406
6777
|
mobileSetupFlowRef,
|
|
6407
6778
|
handlingMobileReturnRef,
|
|
6408
6779
|
loadingDataRef
|
|
6409
6780
|
} = refs;
|
|
6781
|
+
const { apiBaseUrl } = useBlinkConfig();
|
|
6782
|
+
const onCompleteRef = useRef(onComplete);
|
|
6783
|
+
onCompleteRef.current = onComplete;
|
|
6784
|
+
const guestPollingActiveRef = useRef(false);
|
|
6785
|
+
useEffect(() => {
|
|
6786
|
+
const persisted = loadMobileFlowState();
|
|
6787
|
+
if (!persisted?.isGuestCheckout || !persisted.transferId || !persisted.guestSessionToken) return;
|
|
6788
|
+
if (guestPollingActiveRef.current) return;
|
|
6789
|
+
guestPollingActiveRef.current = true;
|
|
6790
|
+
const transferId = persisted.transferId;
|
|
6791
|
+
const guestSessionToken = persisted.guestSessionToken;
|
|
6792
|
+
let cancelled = false;
|
|
6793
|
+
const POLL_INTERVAL_MS = 3e3;
|
|
6794
|
+
dispatch({ type: "NAVIGATE", step: "processing" });
|
|
6795
|
+
const poll = async () => {
|
|
6796
|
+
if (cancelled) return;
|
|
6797
|
+
try {
|
|
6798
|
+
const transfer = await getGuestTransfer(apiBaseUrl, transferId, guestSessionToken);
|
|
6799
|
+
if (cancelled) return;
|
|
6800
|
+
if (transfer.status === "COMPLETED") {
|
|
6801
|
+
cancelled = true;
|
|
6802
|
+
guestPollingActiveRef.current = false;
|
|
6803
|
+
clearMobileFlowState();
|
|
6804
|
+
dispatch({ type: "GUEST_TRANSFER_COMPLETED", transfer });
|
|
6805
|
+
onCompleteRef.current?.(transfer);
|
|
6806
|
+
} else if (transfer.status === "FAILED") {
|
|
6807
|
+
cancelled = true;
|
|
6808
|
+
guestPollingActiveRef.current = false;
|
|
6809
|
+
clearMobileFlowState();
|
|
6810
|
+
dispatch({ type: "TRANSFER_FAILED", transfer, error: "Transfer failed." });
|
|
6811
|
+
}
|
|
6812
|
+
} catch {
|
|
6813
|
+
}
|
|
6814
|
+
};
|
|
6815
|
+
poll();
|
|
6816
|
+
const intervalId = window.setInterval(poll, POLL_INTERVAL_MS);
|
|
6817
|
+
const handleVisibility = () => {
|
|
6818
|
+
if (document.visibilityState === "visible" && !cancelled) {
|
|
6819
|
+
poll();
|
|
6820
|
+
}
|
|
6821
|
+
};
|
|
6822
|
+
const handlePageShow = (e) => {
|
|
6823
|
+
if (e.persisted && !cancelled) {
|
|
6824
|
+
poll();
|
|
6825
|
+
}
|
|
6826
|
+
};
|
|
6827
|
+
document.addEventListener("visibilitychange", handleVisibility);
|
|
6828
|
+
window.addEventListener("pageshow", handlePageShow);
|
|
6829
|
+
return () => {
|
|
6830
|
+
cancelled = true;
|
|
6831
|
+
guestPollingActiveRef.current = false;
|
|
6832
|
+
window.clearInterval(intervalId);
|
|
6833
|
+
document.removeEventListener("visibilitychange", handleVisibility);
|
|
6834
|
+
window.removeEventListener("pageshow", handlePageShow);
|
|
6835
|
+
};
|
|
6836
|
+
}, [apiBaseUrl, dispatch]);
|
|
6410
6837
|
const handleAuthorizedMobileReturn = useCallback(async (authorizedTransfer, isSetup) => {
|
|
6411
6838
|
if (handlingMobileReturnRef.current) return;
|
|
6412
6839
|
handlingMobileReturnRef.current = true;
|
|
@@ -6465,9 +6892,17 @@ function useProviderHandlers(deps) {
|
|
|
6465
6892
|
handlingMobileReturnRef,
|
|
6466
6893
|
setupAccountIdRef,
|
|
6467
6894
|
reauthSessionIdRef,
|
|
6468
|
-
reauthTokenRef
|
|
6895
|
+
reauthTokenRef,
|
|
6896
|
+
authenticated,
|
|
6897
|
+
merchantAuthorization,
|
|
6898
|
+
destination
|
|
6469
6899
|
} = deps;
|
|
6900
|
+
const wagmiConfig2 = useConfig();
|
|
6901
|
+
const { connectAsync, connectors } = useConnect();
|
|
6470
6902
|
const handlePrepareProvider = useCallback(async (providerId) => {
|
|
6903
|
+
if (!authenticated) {
|
|
6904
|
+
return null;
|
|
6905
|
+
}
|
|
6471
6906
|
if (!activeCredentialId) {
|
|
6472
6907
|
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6473
6908
|
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
@@ -6495,8 +6930,85 @@ function useProviderHandlers(deps) {
|
|
|
6495
6930
|
onError?.(msg);
|
|
6496
6931
|
return null;
|
|
6497
6932
|
}
|
|
6498
|
-
}, [activeCredentialId, providers, apiBaseUrl, getAccessToken, onError, dispatch]);
|
|
6933
|
+
}, [authenticated, activeCredentialId, providers, apiBaseUrl, getAccessToken, onError, dispatch]);
|
|
6934
|
+
const handleGuestSelectProvider = useCallback(async (providerId) => {
|
|
6935
|
+
if (!merchantAuthorization || !destination) {
|
|
6936
|
+
const msg = "Missing payment configuration for guest checkout.";
|
|
6937
|
+
dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
|
|
6938
|
+
onError?.(msg);
|
|
6939
|
+
return;
|
|
6940
|
+
}
|
|
6941
|
+
const isMobile = !shouldUseWalletConnector({
|
|
6942
|
+
useWalletConnector: useWalletConnectorProp,
|
|
6943
|
+
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
6944
|
+
});
|
|
6945
|
+
dispatch({ type: "SELECT_PROVIDER", providerId });
|
|
6946
|
+
try {
|
|
6947
|
+
const result = await createGuestTransfer(apiBaseUrl, {
|
|
6948
|
+
merchantAuthorization,
|
|
6949
|
+
destinations: [{
|
|
6950
|
+
chainId: destination.chainId,
|
|
6951
|
+
token: { address: destination.token.address },
|
|
6952
|
+
address: destination.address
|
|
6953
|
+
}],
|
|
6954
|
+
amount: depositAmount ?? 0,
|
|
6955
|
+
providerId
|
|
6956
|
+
});
|
|
6957
|
+
if (isMobile) {
|
|
6958
|
+
if (!result.uri) {
|
|
6959
|
+
dispatch({ type: "PAY_ERROR", error: "This wallet is not available on mobile.", fallbackStep: "wallet-picker" });
|
|
6960
|
+
return;
|
|
6961
|
+
}
|
|
6962
|
+
persistMobileFlowState({
|
|
6963
|
+
transferId: result.id,
|
|
6964
|
+
guestSessionToken: result.guestSessionToken,
|
|
6965
|
+
isGuestCheckout: true,
|
|
6966
|
+
deeplinkUri: result.uri,
|
|
6967
|
+
providerId,
|
|
6968
|
+
isSetup: false
|
|
6969
|
+
});
|
|
6970
|
+
triggerDeeplink(result.uri);
|
|
6971
|
+
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: result.uri });
|
|
6972
|
+
} else {
|
|
6973
|
+
const account = getAccount(wagmiConfig2);
|
|
6974
|
+
if (!account.isConnected) {
|
|
6975
|
+
const connector = connectors.find((c) => c.type === "injected") ?? connectors[0];
|
|
6976
|
+
if (!connector) {
|
|
6977
|
+
dispatch({ type: "PAY_ERROR", error: "No wallet extension found. Please install a supported wallet.", fallbackStep: "wallet-picker" });
|
|
6978
|
+
return;
|
|
6979
|
+
}
|
|
6980
|
+
await connectAsync({ connector });
|
|
6981
|
+
}
|
|
6982
|
+
dispatch({
|
|
6983
|
+
type: "GUEST_PROVIDER_SELECTED",
|
|
6984
|
+
providerId,
|
|
6985
|
+
transferId: result.id,
|
|
6986
|
+
guestSessionToken: result.guestSessionToken
|
|
6987
|
+
});
|
|
6988
|
+
}
|
|
6989
|
+
} catch (err) {
|
|
6990
|
+
captureException(err);
|
|
6991
|
+
const msg = err instanceof Error ? err.message : "Failed to start guest checkout";
|
|
6992
|
+
dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
|
|
6993
|
+
onError?.(msg);
|
|
6994
|
+
}
|
|
6995
|
+
}, [
|
|
6996
|
+
merchantAuthorization,
|
|
6997
|
+
destination,
|
|
6998
|
+
apiBaseUrl,
|
|
6999
|
+
depositAmount,
|
|
7000
|
+
useWalletConnectorProp,
|
|
7001
|
+
wagmiConfig2,
|
|
7002
|
+
connectors,
|
|
7003
|
+
connectAsync,
|
|
7004
|
+
onError,
|
|
7005
|
+
dispatch
|
|
7006
|
+
]);
|
|
6499
7007
|
const handleSelectProvider = useCallback(async (providerId, preparedSession) => {
|
|
7008
|
+
if (!authenticated) {
|
|
7009
|
+
await handleGuestSelectProvider(providerId);
|
|
7010
|
+
return;
|
|
7011
|
+
}
|
|
6500
7012
|
dispatch({ type: "SELECT_PROVIDER", providerId });
|
|
6501
7013
|
if (!activeCredentialId) {
|
|
6502
7014
|
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
@@ -6566,6 +7078,8 @@ function useProviderHandlers(deps) {
|
|
|
6566
7078
|
}
|
|
6567
7079
|
}
|
|
6568
7080
|
}, [
|
|
7081
|
+
authenticated,
|
|
7082
|
+
handleGuestSelectProvider,
|
|
6569
7083
|
activeCredentialId,
|
|
6570
7084
|
providers,
|
|
6571
7085
|
apiBaseUrl,
|
|
@@ -6801,6 +7315,217 @@ function useProviderHandlers(deps) {
|
|
|
6801
7315
|
handleAuthorizeToken
|
|
6802
7316
|
};
|
|
6803
7317
|
}
|
|
7318
|
+
|
|
7319
|
+
// src/guestTokens.ts
|
|
7320
|
+
function mapBalancesToGuestTokenEntries(options) {
|
|
7321
|
+
return options.map((opt) => ({
|
|
7322
|
+
chainId: opt.chainId,
|
|
7323
|
+
sourceChainId: opt.sourceChainId,
|
|
7324
|
+
chainName: opt.chainName,
|
|
7325
|
+
tokenSymbol: opt.tokenSymbol,
|
|
7326
|
+
tokenAddress: opt.tokenAddress,
|
|
7327
|
+
decimals: opt.decimals,
|
|
7328
|
+
rawBalance: opt.rawBalance,
|
|
7329
|
+
balance: Number(opt.rawBalance) / 10 ** opt.decimals
|
|
7330
|
+
})).filter((entry) => entry.balance > 0).sort((a, b) => b.balance - a.balance);
|
|
7331
|
+
}
|
|
7332
|
+
|
|
7333
|
+
// src/hooks/useGuestTransferHandlers.ts
|
|
7334
|
+
var GUEST_SIGN_POLL_MS = 2e3;
|
|
7335
|
+
var GUEST_SIGN_MAX_POLLS = 90;
|
|
7336
|
+
var GUEST_COMPLETION_POLL_MS = 3e3;
|
|
7337
|
+
var GUEST_COMPLETION_MAX_POLLS = 120;
|
|
7338
|
+
function isUserRejection2(msg) {
|
|
7339
|
+
const lower = msg.toLowerCase();
|
|
7340
|
+
return lower.includes("rejected") || lower.includes("denied") || lower.includes("cancelled");
|
|
7341
|
+
}
|
|
7342
|
+
function useGuestTransferHandlers(deps) {
|
|
7343
|
+
const {
|
|
7344
|
+
dispatch,
|
|
7345
|
+
isGuestFlow,
|
|
7346
|
+
guestTransferId,
|
|
7347
|
+
guestSessionToken,
|
|
7348
|
+
step,
|
|
7349
|
+
onComplete,
|
|
7350
|
+
onError
|
|
7351
|
+
} = deps;
|
|
7352
|
+
const { apiBaseUrl } = useBlinkConfig();
|
|
7353
|
+
const wagmiConfig2 = useConfig();
|
|
7354
|
+
const { switchChainAsync } = useSwitchChain();
|
|
7355
|
+
const [guestTokenEntries, setGuestTokenEntries] = useState([]);
|
|
7356
|
+
const [loadingBalances, setLoadingBalances] = useState(false);
|
|
7357
|
+
const [settingSender, setSettingSender] = useState(false);
|
|
7358
|
+
const executingBridgeRef = useRef(false);
|
|
7359
|
+
const fetchedRef = useRef(false);
|
|
7360
|
+
const selectedGuestTokenRef = useRef(null);
|
|
7361
|
+
useEffect(() => {
|
|
7362
|
+
if (!isGuestFlow || step !== "token-picker" || fetchedRef.current) return;
|
|
7363
|
+
if (!guestTransferId || !guestSessionToken) return;
|
|
7364
|
+
const account = getAccount(wagmiConfig2);
|
|
7365
|
+
if (!account.address) return;
|
|
7366
|
+
fetchedRef.current = true;
|
|
7367
|
+
setLoadingBalances(true);
|
|
7368
|
+
fetchGuestTransferBalances(apiBaseUrl, guestTransferId, guestSessionToken, account.address).then((options) => mapBalancesToGuestTokenEntries(options)).then((entries) => {
|
|
7369
|
+
setGuestTokenEntries(entries);
|
|
7370
|
+
if (entries.length === 0) {
|
|
7371
|
+
dispatch({ type: "SET_ERROR", error: "No supported tokens found in your wallet." });
|
|
7372
|
+
}
|
|
7373
|
+
}).catch((err) => {
|
|
7374
|
+
captureException(err);
|
|
7375
|
+
dispatch({ type: "SET_ERROR", error: "Failed to fetch token balances." });
|
|
7376
|
+
}).finally(() => setLoadingBalances(false));
|
|
7377
|
+
}, [isGuestFlow, step, guestTransferId, guestSessionToken, apiBaseUrl, wagmiConfig2, dispatch]);
|
|
7378
|
+
useEffect(() => {
|
|
7379
|
+
if (!isGuestFlow) {
|
|
7380
|
+
fetchedRef.current = false;
|
|
7381
|
+
selectedGuestTokenRef.current = null;
|
|
7382
|
+
setGuestTokenEntries([]);
|
|
7383
|
+
}
|
|
7384
|
+
}, [isGuestFlow]);
|
|
7385
|
+
const handleSelectGuestToken = useCallback(async (entry) => {
|
|
7386
|
+
if (!guestTransferId || !guestSessionToken) return;
|
|
7387
|
+
const account = getAccount(wagmiConfig2);
|
|
7388
|
+
if (!account.address) {
|
|
7389
|
+
dispatch({ type: "SET_ERROR", error: "Wallet not connected." });
|
|
7390
|
+
return;
|
|
7391
|
+
}
|
|
7392
|
+
setSettingSender(true);
|
|
7393
|
+
try {
|
|
7394
|
+
console.info(
|
|
7395
|
+
`[blink-sdk] type=guest Setting sender: address=${account.address}, chain=${entry.sourceChainId}, token=${entry.tokenSymbol}`
|
|
7396
|
+
);
|
|
7397
|
+
await setTransferSender(
|
|
7398
|
+
apiBaseUrl,
|
|
7399
|
+
guestTransferId,
|
|
7400
|
+
guestSessionToken,
|
|
7401
|
+
account.address,
|
|
7402
|
+
entry.sourceChainId,
|
|
7403
|
+
entry.tokenAddress
|
|
7404
|
+
);
|
|
7405
|
+
selectedGuestTokenRef.current = entry;
|
|
7406
|
+
dispatch({ type: "NAVIGATE", step: "processing" });
|
|
7407
|
+
} catch (err) {
|
|
7408
|
+
captureException(err);
|
|
7409
|
+
const msg = err instanceof Error ? err.message : "Failed to set transfer sender";
|
|
7410
|
+
dispatch({ type: "SET_ERROR", error: msg });
|
|
7411
|
+
onError?.(msg);
|
|
7412
|
+
} finally {
|
|
7413
|
+
setSettingSender(false);
|
|
7414
|
+
}
|
|
7415
|
+
}, [guestTransferId, guestSessionToken, wagmiConfig2, apiBaseUrl, dispatch, onError]);
|
|
7416
|
+
useEffect(() => {
|
|
7417
|
+
if (!isGuestFlow || step !== "processing" || !guestTransferId || !guestSessionToken) return;
|
|
7418
|
+
if (executingBridgeRef.current) return;
|
|
7419
|
+
executingBridgeRef.current = true;
|
|
7420
|
+
const execute = async () => {
|
|
7421
|
+
try {
|
|
7422
|
+
let signPayload = null;
|
|
7423
|
+
for (let i = 0; i < GUEST_SIGN_MAX_POLLS; i++) {
|
|
7424
|
+
const transfer = await getGuestTransfer(apiBaseUrl, guestTransferId, guestSessionToken);
|
|
7425
|
+
const payload = transfer.signPayload;
|
|
7426
|
+
if (payload?.bridgeSteps && payload.bridgeSteps.length > 0) {
|
|
7427
|
+
signPayload = payload;
|
|
7428
|
+
break;
|
|
7429
|
+
}
|
|
7430
|
+
if (transfer.status === "FAILED") {
|
|
7431
|
+
dispatch({ type: "PAY_ERROR", error: "Transfer failed.", fallbackStep: "wallet-picker" });
|
|
7432
|
+
return;
|
|
7433
|
+
}
|
|
7434
|
+
await new Promise((r) => setTimeout(r, GUEST_SIGN_POLL_MS));
|
|
7435
|
+
}
|
|
7436
|
+
if (!signPayload) {
|
|
7437
|
+
dispatch({
|
|
7438
|
+
type: "PAY_ERROR",
|
|
7439
|
+
error: "Timed out waiting for bridge quote. Please try again.",
|
|
7440
|
+
fallbackStep: "wallet-picker"
|
|
7441
|
+
});
|
|
7442
|
+
return;
|
|
7443
|
+
}
|
|
7444
|
+
console.info(
|
|
7445
|
+
`[blink-sdk] type=guest Bridge quote ready: ${signPayload.bridgeSteps.length} step(s), token=${signPayload.tokenSymbol}, chain=${signPayload.chainName}`
|
|
7446
|
+
);
|
|
7447
|
+
const selectedToken = selectedGuestTokenRef.current;
|
|
7448
|
+
const account = getAccount(wagmiConfig2);
|
|
7449
|
+
const targetChainId = selectedToken?.chainId;
|
|
7450
|
+
if (targetChainId) {
|
|
7451
|
+
const numericChainId = Number(targetChainId);
|
|
7452
|
+
if (!isNaN(numericChainId) && account.chainId !== numericChainId) {
|
|
7453
|
+
console.info(`[blink-sdk] type=guest Switching chain to ${numericChainId}`);
|
|
7454
|
+
await switchChainAsync({ chainId: numericChainId });
|
|
7455
|
+
}
|
|
7456
|
+
}
|
|
7457
|
+
const walletClient = await getWalletClient(wagmiConfig2);
|
|
7458
|
+
const sender = account.address;
|
|
7459
|
+
if (!sender) {
|
|
7460
|
+
dispatch({ type: "PAY_ERROR", error: "Wallet not connected.", fallbackStep: "wallet-picker" });
|
|
7461
|
+
return;
|
|
7462
|
+
}
|
|
7463
|
+
let lastTxHash = null;
|
|
7464
|
+
for (let stepIdx = 0; stepIdx < signPayload.bridgeSteps.length; stepIdx++) {
|
|
7465
|
+
const bridgeStep = signPayload.bridgeSteps[stepIdx];
|
|
7466
|
+
console.info(
|
|
7467
|
+
`[blink-sdk] type=guest Executing bridge step ${stepIdx + 1}/${signPayload.bridgeSteps.length} to=${bridgeStep.to}`
|
|
7468
|
+
);
|
|
7469
|
+
const txHash = await walletClient.request({
|
|
7470
|
+
method: "eth_sendTransaction",
|
|
7471
|
+
params: [{
|
|
7472
|
+
from: sender,
|
|
7473
|
+
to: bridgeStep.to,
|
|
7474
|
+
data: bridgeStep.data,
|
|
7475
|
+
value: bridgeStep.value
|
|
7476
|
+
}]
|
|
7477
|
+
});
|
|
7478
|
+
console.info(`[blink-sdk] type=guest Bridge step ${stepIdx + 1} tx sent: ${txHash}`);
|
|
7479
|
+
await waitForTransactionReceipt(wagmiConfig2, {
|
|
7480
|
+
hash: txHash
|
|
7481
|
+
});
|
|
7482
|
+
lastTxHash = txHash;
|
|
7483
|
+
}
|
|
7484
|
+
if (!lastTxHash) {
|
|
7485
|
+
dispatch({ type: "PAY_ERROR", error: "No bridge transactions were executed.", fallbackStep: "wallet-picker" });
|
|
7486
|
+
return;
|
|
7487
|
+
}
|
|
7488
|
+
console.info(`[blink-sdk] type=guest Submitting originTxHash: ${lastTxHash}`);
|
|
7489
|
+
await signGuestTransfer(apiBaseUrl, guestTransferId, guestSessionToken, lastTxHash);
|
|
7490
|
+
for (let i = 0; i < GUEST_COMPLETION_MAX_POLLS; i++) {
|
|
7491
|
+
const transfer = await getGuestTransfer(apiBaseUrl, guestTransferId, guestSessionToken);
|
|
7492
|
+
if (transfer.status === "COMPLETED") {
|
|
7493
|
+
console.info(`[blink-sdk] type=guest Transfer completed`);
|
|
7494
|
+
dispatch({ type: "GUEST_TRANSFER_COMPLETED", transfer });
|
|
7495
|
+
onComplete?.(transfer);
|
|
7496
|
+
return;
|
|
7497
|
+
}
|
|
7498
|
+
if (transfer.status === "FAILED") {
|
|
7499
|
+
dispatch({ type: "TRANSFER_FAILED", transfer, error: "Transfer failed." });
|
|
7500
|
+
return;
|
|
7501
|
+
}
|
|
7502
|
+
await new Promise((r) => setTimeout(r, GUEST_COMPLETION_POLL_MS));
|
|
7503
|
+
}
|
|
7504
|
+
dispatch({
|
|
7505
|
+
type: "PAY_ERROR",
|
|
7506
|
+
error: "Transfer is taking longer than expected. It may still complete.",
|
|
7507
|
+
fallbackStep: "wallet-picker"
|
|
7508
|
+
});
|
|
7509
|
+
} catch (err) {
|
|
7510
|
+
captureException(err);
|
|
7511
|
+
const msg = err instanceof Error ? err.message : "Bridge execution failed";
|
|
7512
|
+
console.error("[blink-sdk] type=guest Bridge execution error:", err);
|
|
7513
|
+
const displayMsg = isUserRejection2(msg) ? "You rejected the transaction. Please approve in your wallet to continue." : msg;
|
|
7514
|
+
dispatch({ type: "PAY_ERROR", error: displayMsg, fallbackStep: "wallet-picker" });
|
|
7515
|
+
onError?.(displayMsg);
|
|
7516
|
+
} finally {
|
|
7517
|
+
executingBridgeRef.current = false;
|
|
7518
|
+
}
|
|
7519
|
+
};
|
|
7520
|
+
execute();
|
|
7521
|
+
}, [isGuestFlow, step, guestTransferId, guestSessionToken, apiBaseUrl, wagmiConfig2, switchChainAsync, dispatch, onComplete, onError]);
|
|
7522
|
+
return {
|
|
7523
|
+
guestTokenEntries,
|
|
7524
|
+
loadingBalances,
|
|
7525
|
+
settingSender,
|
|
7526
|
+
handleSelectGuestToken
|
|
7527
|
+
};
|
|
7528
|
+
}
|
|
6804
7529
|
function useOneTapSetupHandlers(deps) {
|
|
6805
7530
|
const {
|
|
6806
7531
|
dispatch,
|
|
@@ -7596,7 +8321,8 @@ function BlinkPaymentInner({
|
|
|
7596
8321
|
transfer.reloadAccounts,
|
|
7597
8322
|
transfer.pollingTransferIdRef,
|
|
7598
8323
|
state.transfer,
|
|
7599
|
-
mobileFlowRefs
|
|
8324
|
+
mobileFlowRefs,
|
|
8325
|
+
onComplete
|
|
7600
8326
|
);
|
|
7601
8327
|
const sourceSelection = useSourceSelectionHandlers(dispatch, authExecutor);
|
|
7602
8328
|
const provider = useProviderHandlers({
|
|
@@ -7619,7 +8345,10 @@ function BlinkPaymentInner({
|
|
|
7619
8345
|
handlingMobileReturnRef: mobileFlowRefs.handlingMobileReturnRef,
|
|
7620
8346
|
setupAccountIdRef: mobileFlowRefs.setupAccountIdRef,
|
|
7621
8347
|
reauthSessionIdRef: mobileFlowRefs.reauthSessionIdRef,
|
|
7622
|
-
reauthTokenRef: mobileFlowRefs.reauthTokenRef
|
|
8348
|
+
reauthTokenRef: mobileFlowRefs.reauthTokenRef,
|
|
8349
|
+
authenticated,
|
|
8350
|
+
merchantAuthorization,
|
|
8351
|
+
destination
|
|
7623
8352
|
});
|
|
7624
8353
|
const oneTapSetup = useOneTapSetupHandlers({
|
|
7625
8354
|
dispatch,
|
|
@@ -7629,6 +8358,15 @@ function BlinkPaymentInner({
|
|
|
7629
8358
|
selectSourceChainName: sourceSelection.selectSourceChainName,
|
|
7630
8359
|
selectSourceTokenSymbol: sourceSelection.selectSourceTokenSymbol
|
|
7631
8360
|
});
|
|
8361
|
+
const guestTransfer = useGuestTransferHandlers({
|
|
8362
|
+
dispatch,
|
|
8363
|
+
isGuestFlow: state.isGuestFlow,
|
|
8364
|
+
guestTransferId: state.guestTransferId,
|
|
8365
|
+
guestSessionToken: state.guestSessionToken,
|
|
8366
|
+
step: state.step,
|
|
8367
|
+
onComplete,
|
|
8368
|
+
onError
|
|
8369
|
+
});
|
|
7632
8370
|
const handleNewPayment = useCallback(() => {
|
|
7633
8371
|
clearMobileFlowState();
|
|
7634
8372
|
transfer.processingStartedAtRef.current = null;
|
|
@@ -7729,7 +8467,9 @@ function BlinkPaymentInner({
|
|
|
7729
8467
|
onSetupOneTap: oneTapSetup.handleSetupOneTap,
|
|
7730
8468
|
onSelectToken: provider.handleNavigateToTokenPicker,
|
|
7731
8469
|
onSelectAuthorizedToken: provider.handleSelectAuthorizedToken,
|
|
7732
|
-
onAuthorizeToken: provider.handleAuthorizeToken
|
|
8470
|
+
onAuthorizeToken: provider.handleAuthorizeToken,
|
|
8471
|
+
onSelectGuestToken: guestTransfer.handleSelectGuestToken,
|
|
8472
|
+
onLogin: () => dispatch({ type: "NAVIGATE", step: "login" })
|
|
7733
8473
|
}), [
|
|
7734
8474
|
auth,
|
|
7735
8475
|
passkey,
|
|
@@ -7738,6 +8478,7 @@ function BlinkPaymentInner({
|
|
|
7738
8478
|
mobileFlow,
|
|
7739
8479
|
sourceSelection,
|
|
7740
8480
|
oneTapSetup,
|
|
8481
|
+
guestTransfer,
|
|
7741
8482
|
handleLogout,
|
|
7742
8483
|
handleNewPayment
|
|
7743
8484
|
]);
|
|
@@ -7763,6 +8504,9 @@ function BlinkPaymentInner({
|
|
|
7763
8504
|
selectSourceChoices: sourceSelection.selectSourceChoices,
|
|
7764
8505
|
selectSourceRecommended: sourceSelection.selectSourceRecommended,
|
|
7765
8506
|
selectSourceAvailableBalance: sourceSelection.selectSourceAvailableBalance,
|
|
8507
|
+
guestTokenEntries: guestTransfer.guestTokenEntries,
|
|
8508
|
+
guestLoadingBalances: guestTransfer.loadingBalances,
|
|
8509
|
+
guestSettingSender: guestTransfer.settingSender,
|
|
7766
8510
|
authInput: auth.authInput,
|
|
7767
8511
|
otpCode: auth.otpCode,
|
|
7768
8512
|
selectSourceChainName: sourceSelection.selectSourceChainName,
|