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