@swype-org/react-sdk 0.1.218 → 0.1.220
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 +792 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -4
- package/dist/index.d.ts +76 -4
- package/dist/index.js +793 -17
- 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
|
|
@@ -443,9 +488,11 @@ async function throwApiError(res) {
|
|
|
443
488
|
throw new Error(`${res.status} \u2014 ${code}: ${msg}`);
|
|
444
489
|
}
|
|
445
490
|
async function fetchProviders(apiBaseUrl, token) {
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
|
|
491
|
+
const headers = {};
|
|
492
|
+
if (token) {
|
|
493
|
+
headers.Authorization = `Bearer ${token}`;
|
|
494
|
+
}
|
|
495
|
+
const res = await fetch(`${apiBaseUrl}/v1/providers`, { headers });
|
|
449
496
|
if (!res.ok) await throwApiError(res);
|
|
450
497
|
const data = await res.json();
|
|
451
498
|
return data.items;
|
|
@@ -643,6 +690,79 @@ async function updateUserConfigBySession(apiBaseUrl, sessionId, config) {
|
|
|
643
690
|
);
|
|
644
691
|
if (!res.ok) await throwApiError(res);
|
|
645
692
|
}
|
|
693
|
+
async function createGuestTransfer(apiBaseUrl, params) {
|
|
694
|
+
const body = {
|
|
695
|
+
id: params.id ?? crypto.randomUUID(),
|
|
696
|
+
type: "guest",
|
|
697
|
+
merchantAuthorization: params.merchantAuthorization,
|
|
698
|
+
destinations: params.destinations,
|
|
699
|
+
amount: {
|
|
700
|
+
amount: params.amount,
|
|
701
|
+
currency: params.currency ?? "USD"
|
|
702
|
+
},
|
|
703
|
+
providerId: params.providerId
|
|
704
|
+
};
|
|
705
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers`, {
|
|
706
|
+
method: "POST",
|
|
707
|
+
headers: { "Content-Type": "application/json" },
|
|
708
|
+
body: JSON.stringify(body)
|
|
709
|
+
});
|
|
710
|
+
if (!res.ok) await throwApiError(res);
|
|
711
|
+
return await res.json();
|
|
712
|
+
}
|
|
713
|
+
async function getTransferByGuestToken(apiBaseUrl, guestToken) {
|
|
714
|
+
const params = new URLSearchParams({ guestToken });
|
|
715
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers?${params.toString()}`);
|
|
716
|
+
if (!res.ok) await throwApiError(res);
|
|
717
|
+
return await res.json();
|
|
718
|
+
}
|
|
719
|
+
async function setTransferSender(apiBaseUrl, transferId, guestSessionToken, senderAddress, sourceChainId, sourceToken) {
|
|
720
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}/sender`, {
|
|
721
|
+
method: "PUT",
|
|
722
|
+
headers: {
|
|
723
|
+
"Content-Type": "application/json",
|
|
724
|
+
"x-guest-session-token": guestSessionToken
|
|
725
|
+
},
|
|
726
|
+
body: JSON.stringify({ senderAddress, sourceChainId, sourceToken })
|
|
727
|
+
});
|
|
728
|
+
if (!res.ok) await throwApiError(res);
|
|
729
|
+
return await res.json();
|
|
730
|
+
}
|
|
731
|
+
async function signGuestTransfer(apiBaseUrl, transferId, guestSessionToken, originTxHash) {
|
|
732
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
|
|
733
|
+
method: "PATCH",
|
|
734
|
+
headers: {
|
|
735
|
+
"Content-Type": "application/json",
|
|
736
|
+
"x-guest-session-token": guestSessionToken
|
|
737
|
+
},
|
|
738
|
+
body: JSON.stringify({ originTxHash })
|
|
739
|
+
});
|
|
740
|
+
if (!res.ok) await throwApiError(res);
|
|
741
|
+
return await res.json();
|
|
742
|
+
}
|
|
743
|
+
async function getGuestTransfer(apiBaseUrl, transferId, guestSessionToken) {
|
|
744
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
|
|
745
|
+
headers: {
|
|
746
|
+
"x-guest-session-token": guestSessionToken
|
|
747
|
+
}
|
|
748
|
+
});
|
|
749
|
+
if (!res.ok) await throwApiError(res);
|
|
750
|
+
return await res.json();
|
|
751
|
+
}
|
|
752
|
+
async function fetchGuestTransferBalances(apiBaseUrl, transferId, guestSessionToken, walletAddress) {
|
|
753
|
+
const params = new URLSearchParams({ walletAddress });
|
|
754
|
+
const res = await fetch(
|
|
755
|
+
`${apiBaseUrl}/v1/transfers/${transferId}/balances?${params.toString()}`,
|
|
756
|
+
{
|
|
757
|
+
headers: {
|
|
758
|
+
"x-guest-session-token": guestSessionToken
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
);
|
|
762
|
+
if (!res.ok) await throwApiError(res);
|
|
763
|
+
const data = await res.json();
|
|
764
|
+
return data.items;
|
|
765
|
+
}
|
|
646
766
|
async function reportActionCompletion(apiBaseUrl, actionId, result) {
|
|
647
767
|
const res = await fetch(
|
|
648
768
|
`${apiBaseUrl}/v1/authorization-actions/${actionId}`,
|
|
@@ -1789,8 +1909,9 @@ function deriveSourceTypeAndId(state) {
|
|
|
1789
1909
|
return { sourceType: "accountId", sourceId: "" };
|
|
1790
1910
|
}
|
|
1791
1911
|
function createInitialState(config) {
|
|
1912
|
+
const isReturningUser = config.activeCredentialId != null;
|
|
1792
1913
|
return {
|
|
1793
|
-
step: "login",
|
|
1914
|
+
step: isReturningUser ? "login" : "wallet-picker",
|
|
1794
1915
|
error: null,
|
|
1795
1916
|
providers: [],
|
|
1796
1917
|
accounts: [],
|
|
@@ -1813,7 +1934,10 @@ function createInitialState(config) {
|
|
|
1813
1934
|
mobileFlow: false,
|
|
1814
1935
|
deeplinkUri: null,
|
|
1815
1936
|
increasingLimit: false,
|
|
1816
|
-
previousStep: null
|
|
1937
|
+
previousStep: null,
|
|
1938
|
+
isGuestFlow: false,
|
|
1939
|
+
guestTransferId: null,
|
|
1940
|
+
guestSessionToken: null
|
|
1817
1941
|
};
|
|
1818
1942
|
}
|
|
1819
1943
|
function paymentReducer(state, action) {
|
|
@@ -2036,6 +2160,27 @@ function paymentReducer(state, action) {
|
|
|
2036
2160
|
mobileFlow: true,
|
|
2037
2161
|
deeplinkUri: action.deeplinkUri
|
|
2038
2162
|
};
|
|
2163
|
+
// ── Guest checkout ────────────────────────────────────────────
|
|
2164
|
+
case "GUEST_PROVIDER_SELECTED":
|
|
2165
|
+
return {
|
|
2166
|
+
...state,
|
|
2167
|
+
isGuestFlow: true,
|
|
2168
|
+
selectedProviderId: action.providerId,
|
|
2169
|
+
guestTransferId: action.transferId,
|
|
2170
|
+
guestSessionToken: action.guestSessionToken,
|
|
2171
|
+
selectedAccountId: null,
|
|
2172
|
+
selectedWalletId: null,
|
|
2173
|
+
selectedTokenSymbol: null,
|
|
2174
|
+
step: "token-picker"
|
|
2175
|
+
};
|
|
2176
|
+
case "GUEST_TRANSFER_COMPLETED":
|
|
2177
|
+
return {
|
|
2178
|
+
...state,
|
|
2179
|
+
transfer: action.transfer,
|
|
2180
|
+
step: "success",
|
|
2181
|
+
mobileFlow: false,
|
|
2182
|
+
deeplinkUri: null
|
|
2183
|
+
};
|
|
2039
2184
|
// ── Navigation & error ───────────────────────────────────────
|
|
2040
2185
|
case "NAVIGATE":
|
|
2041
2186
|
return { ...state, step: action.step, previousStep: state.step, error: null };
|
|
@@ -2045,7 +2190,7 @@ function paymentReducer(state, action) {
|
|
|
2045
2190
|
case "NEW_PAYMENT":
|
|
2046
2191
|
return {
|
|
2047
2192
|
...state,
|
|
2048
|
-
step: "deposit",
|
|
2193
|
+
step: state.isGuestFlow ? "wallet-picker" : "deposit",
|
|
2049
2194
|
transfer: null,
|
|
2050
2195
|
error: null,
|
|
2051
2196
|
amount: action.depositAmount != null ? action.depositAmount.toString() : "",
|
|
@@ -2053,7 +2198,10 @@ function paymentReducer(state, action) {
|
|
|
2053
2198
|
deeplinkUri: null,
|
|
2054
2199
|
selectedProviderId: null,
|
|
2055
2200
|
selectedWalletId: null,
|
|
2056
|
-
selectedAccountId: action.firstAccountId
|
|
2201
|
+
selectedAccountId: action.firstAccountId,
|
|
2202
|
+
isGuestFlow: false,
|
|
2203
|
+
guestTransferId: null,
|
|
2204
|
+
guestSessionToken: null
|
|
2057
2205
|
};
|
|
2058
2206
|
case "LOGOUT":
|
|
2059
2207
|
return {
|
|
@@ -3236,7 +3384,9 @@ function WalletPickerScreen({
|
|
|
3236
3384
|
onSelectProvider,
|
|
3237
3385
|
onContinueConnection,
|
|
3238
3386
|
onBack,
|
|
3239
|
-
onLogout
|
|
3387
|
+
onLogout,
|
|
3388
|
+
onLogin,
|
|
3389
|
+
showLoginOption
|
|
3240
3390
|
}) {
|
|
3241
3391
|
const { tokens } = useBlinkConfig();
|
|
3242
3392
|
const [hoveredId, setHoveredId] = useState(null);
|
|
@@ -3391,6 +3541,18 @@ function WalletPickerScreen({
|
|
|
3391
3541
|
/* @__PURE__ */ jsxs("div", { style: categoryRowStyle(tokens, false, true), children: [
|
|
3392
3542
|
/* @__PURE__ */ jsx("span", { style: categoryLabelStyle, children: "Bank Account" }),
|
|
3393
3543
|
/* @__PURE__ */ jsx("span", { style: comingSoonBadgeStyle(tokens), children: "Coming Soon" })
|
|
3544
|
+
] }),
|
|
3545
|
+
showLoginOption && onLogin && /* @__PURE__ */ jsxs("div", { style: loginOptionStyle, children: [
|
|
3546
|
+
/* @__PURE__ */ jsx("span", { style: loginTextStyle(tokens.textSecondary), children: "Already have an account?" }),
|
|
3547
|
+
/* @__PURE__ */ jsx(
|
|
3548
|
+
"button",
|
|
3549
|
+
{
|
|
3550
|
+
type: "button",
|
|
3551
|
+
onClick: onLogin,
|
|
3552
|
+
style: loginButtonStyle(tokens.accent),
|
|
3553
|
+
children: "Log in"
|
|
3554
|
+
}
|
|
3555
|
+
)
|
|
3394
3556
|
] })
|
|
3395
3557
|
]
|
|
3396
3558
|
}
|
|
@@ -3557,6 +3719,28 @@ var dividerTextStyle = (color) => ({
|
|
|
3557
3719
|
color,
|
|
3558
3720
|
whiteSpace: "nowrap"
|
|
3559
3721
|
});
|
|
3722
|
+
var loginOptionStyle = {
|
|
3723
|
+
display: "flex",
|
|
3724
|
+
alignItems: "center",
|
|
3725
|
+
justifyContent: "center",
|
|
3726
|
+
gap: 6,
|
|
3727
|
+
padding: "12px 0 4px"
|
|
3728
|
+
};
|
|
3729
|
+
var loginTextStyle = (color) => ({
|
|
3730
|
+
fontSize: "0.85rem",
|
|
3731
|
+
color
|
|
3732
|
+
});
|
|
3733
|
+
var loginButtonStyle = (accentColor) => ({
|
|
3734
|
+
fontSize: "0.85rem",
|
|
3735
|
+
fontWeight: 600,
|
|
3736
|
+
color: accentColor,
|
|
3737
|
+
background: "none",
|
|
3738
|
+
border: "none",
|
|
3739
|
+
cursor: "pointer",
|
|
3740
|
+
padding: 0,
|
|
3741
|
+
fontFamily: "inherit",
|
|
3742
|
+
textDecoration: "underline"
|
|
3743
|
+
});
|
|
3560
3744
|
var DEFAULT_MAX = 1e7;
|
|
3561
3745
|
var ABSOLUTE_MIN = 0.01;
|
|
3562
3746
|
var PRESETS = [100, 250, 1e3];
|
|
@@ -5394,6 +5578,179 @@ var selectCircleSelectedStyle = (color) => ({
|
|
|
5394
5578
|
justifyContent: "center",
|
|
5395
5579
|
flexShrink: 0
|
|
5396
5580
|
});
|
|
5581
|
+
function GuestTokenPickerScreen({
|
|
5582
|
+
entries,
|
|
5583
|
+
loading,
|
|
5584
|
+
setting,
|
|
5585
|
+
depositAmount,
|
|
5586
|
+
error,
|
|
5587
|
+
onSelect,
|
|
5588
|
+
onBack
|
|
5589
|
+
}) {
|
|
5590
|
+
const { tokens: t } = useBlinkConfig();
|
|
5591
|
+
if (loading) {
|
|
5592
|
+
return /* @__PURE__ */ jsxs(ScreenLayout, { children: [
|
|
5593
|
+
/* @__PURE__ */ jsx(ScreenHeader, { title: "Select Token", onBack }),
|
|
5594
|
+
/* @__PURE__ */ jsx("div", { style: loadingWrapStyle, children: /* @__PURE__ */ jsx(Spinner, { label: "Loading balances..." }) })
|
|
5595
|
+
] });
|
|
5596
|
+
}
|
|
5597
|
+
return /* @__PURE__ */ jsxs(ScreenLayout, { footer: /* @__PURE__ */ jsx(PoweredByFooter, {}), children: [
|
|
5598
|
+
/* @__PURE__ */ jsx(ScreenHeader, { title: "Select Token", onBack }),
|
|
5599
|
+
depositAmount != null && /* @__PURE__ */ jsxs("div", { style: depositHeaderStyle, children: [
|
|
5600
|
+
/* @__PURE__ */ jsx("div", { style: depositLabelStyle3(t.textMuted), children: "Depositing" }),
|
|
5601
|
+
/* @__PURE__ */ jsxs("div", { style: depositAmountStyle2(t.text), children: [
|
|
5602
|
+
"$",
|
|
5603
|
+
depositAmount.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
|
5604
|
+
] })
|
|
5605
|
+
] }),
|
|
5606
|
+
error && /* @__PURE__ */ jsx("p", { style: errorStyle3(t.error), children: error }),
|
|
5607
|
+
/* @__PURE__ */ jsx("div", { style: sectionLabelStyle2(t.textMuted), children: "Choose token to pay with" }),
|
|
5608
|
+
/* @__PURE__ */ jsx("div", { style: tokenListStyle3, children: entries.map((entry) => /* @__PURE__ */ jsxs(
|
|
5609
|
+
"button",
|
|
5610
|
+
{
|
|
5611
|
+
type: "button",
|
|
5612
|
+
onClick: () => onSelect(entry),
|
|
5613
|
+
disabled: setting,
|
|
5614
|
+
style: tokenRowStyle3(t, setting),
|
|
5615
|
+
children: [
|
|
5616
|
+
/* @__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: "$" }) }),
|
|
5617
|
+
/* @__PURE__ */ jsxs("div", { style: tokenInfoStyle3, children: [
|
|
5618
|
+
/* @__PURE__ */ jsxs("div", { style: tokenNameRowStyle2, children: [
|
|
5619
|
+
/* @__PURE__ */ jsx("span", { style: tokenSymbolTextStyle2(t.text), children: entry.tokenSymbol }),
|
|
5620
|
+
/* @__PURE__ */ jsx("span", { style: tokenChainDotStyle2(t.textMuted), children: "\xB7" }),
|
|
5621
|
+
/* @__PURE__ */ jsx("span", { style: tokenChainTextStyle2(t.textMuted), children: entry.chainName })
|
|
5622
|
+
] }),
|
|
5623
|
+
/* @__PURE__ */ jsxs("span", { style: tokenBalanceStyle2(t.textMuted), children: [
|
|
5624
|
+
"$",
|
|
5625
|
+
entry.balance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
|
5626
|
+
] })
|
|
5627
|
+
] }),
|
|
5628
|
+
/* @__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 }) })
|
|
5629
|
+
]
|
|
5630
|
+
},
|
|
5631
|
+
`${entry.chainId}-${entry.tokenAddress}`
|
|
5632
|
+
)) }),
|
|
5633
|
+
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." })
|
|
5634
|
+
] });
|
|
5635
|
+
}
|
|
5636
|
+
var loadingWrapStyle = {
|
|
5637
|
+
textAlign: "center",
|
|
5638
|
+
padding: "48px 0",
|
|
5639
|
+
flex: 1,
|
|
5640
|
+
display: "flex",
|
|
5641
|
+
alignItems: "center",
|
|
5642
|
+
justifyContent: "center"
|
|
5643
|
+
};
|
|
5644
|
+
var depositHeaderStyle = {
|
|
5645
|
+
marginBottom: 20
|
|
5646
|
+
};
|
|
5647
|
+
var depositLabelStyle3 = (color) => ({
|
|
5648
|
+
fontSize: "0.75rem",
|
|
5649
|
+
fontWeight: 500,
|
|
5650
|
+
color,
|
|
5651
|
+
marginBottom: 4
|
|
5652
|
+
});
|
|
5653
|
+
var depositAmountStyle2 = (color) => ({
|
|
5654
|
+
fontSize: "2.4rem",
|
|
5655
|
+
fontWeight: 700,
|
|
5656
|
+
letterSpacing: "-0.02em",
|
|
5657
|
+
color
|
|
5658
|
+
});
|
|
5659
|
+
var errorStyle3 = (color) => ({
|
|
5660
|
+
fontSize: "0.84rem",
|
|
5661
|
+
color,
|
|
5662
|
+
margin: "0 0 12px",
|
|
5663
|
+
lineHeight: 1.5
|
|
5664
|
+
});
|
|
5665
|
+
var sectionLabelStyle2 = (color) => ({
|
|
5666
|
+
fontSize: "0.84rem",
|
|
5667
|
+
fontWeight: 500,
|
|
5668
|
+
color,
|
|
5669
|
+
marginBottom: 12
|
|
5670
|
+
});
|
|
5671
|
+
var tokenListStyle3 = {
|
|
5672
|
+
display: "flex",
|
|
5673
|
+
flexDirection: "column",
|
|
5674
|
+
gap: 10
|
|
5675
|
+
};
|
|
5676
|
+
var tokenRowStyle3 = (tokens, disabled) => ({
|
|
5677
|
+
display: "flex",
|
|
5678
|
+
alignItems: "center",
|
|
5679
|
+
gap: 14,
|
|
5680
|
+
padding: "14px 16px",
|
|
5681
|
+
background: tokens.bgInput,
|
|
5682
|
+
border: `1px solid ${tokens.border}`,
|
|
5683
|
+
borderRadius: 16,
|
|
5684
|
+
cursor: disabled ? "default" : "pointer",
|
|
5685
|
+
fontFamily: "inherit",
|
|
5686
|
+
textAlign: "left",
|
|
5687
|
+
width: "100%",
|
|
5688
|
+
opacity: disabled ? 0.6 : 1,
|
|
5689
|
+
transition: "opacity 0.15s ease"
|
|
5690
|
+
});
|
|
5691
|
+
var tokenIconCircleStyle3 = (tokens, hasLogo) => ({
|
|
5692
|
+
width: 36,
|
|
5693
|
+
height: 36,
|
|
5694
|
+
borderRadius: "50%",
|
|
5695
|
+
border: hasLogo ? "none" : `1.5px solid ${tokens.border}`,
|
|
5696
|
+
display: "flex",
|
|
5697
|
+
alignItems: "center",
|
|
5698
|
+
justifyContent: "center",
|
|
5699
|
+
flexShrink: 0,
|
|
5700
|
+
overflow: "hidden"
|
|
5701
|
+
});
|
|
5702
|
+
var tokenLogoImgStyle3 = {
|
|
5703
|
+
width: 36,
|
|
5704
|
+
height: 36,
|
|
5705
|
+
borderRadius: "50%",
|
|
5706
|
+
objectFit: "cover"
|
|
5707
|
+
};
|
|
5708
|
+
var tokenIconTextStyle3 = (color) => ({
|
|
5709
|
+
fontSize: "1rem",
|
|
5710
|
+
fontWeight: 700,
|
|
5711
|
+
color
|
|
5712
|
+
});
|
|
5713
|
+
var tokenInfoStyle3 = {
|
|
5714
|
+
display: "flex",
|
|
5715
|
+
flexDirection: "column",
|
|
5716
|
+
gap: 2,
|
|
5717
|
+
flex: 1,
|
|
5718
|
+
minWidth: 0
|
|
5719
|
+
};
|
|
5720
|
+
var tokenNameRowStyle2 = {
|
|
5721
|
+
display: "flex",
|
|
5722
|
+
alignItems: "center",
|
|
5723
|
+
gap: 4
|
|
5724
|
+
};
|
|
5725
|
+
var tokenSymbolTextStyle2 = (color) => ({
|
|
5726
|
+
fontSize: "0.92rem",
|
|
5727
|
+
fontWeight: 600,
|
|
5728
|
+
color
|
|
5729
|
+
});
|
|
5730
|
+
var tokenChainDotStyle2 = (color) => ({
|
|
5731
|
+
fontSize: "0.8rem",
|
|
5732
|
+
color
|
|
5733
|
+
});
|
|
5734
|
+
var tokenChainTextStyle2 = (color) => ({
|
|
5735
|
+
fontSize: "0.84rem",
|
|
5736
|
+
fontWeight: 400,
|
|
5737
|
+
color
|
|
5738
|
+
});
|
|
5739
|
+
var tokenBalanceStyle2 = (color) => ({
|
|
5740
|
+
fontSize: "0.78rem",
|
|
5741
|
+
color
|
|
5742
|
+
});
|
|
5743
|
+
var chevronStyle = {
|
|
5744
|
+
flexShrink: 0,
|
|
5745
|
+
opacity: 0.4
|
|
5746
|
+
};
|
|
5747
|
+
var emptyStyle = (color) => ({
|
|
5748
|
+
fontSize: "0.88rem",
|
|
5749
|
+
color,
|
|
5750
|
+
textAlign: "center",
|
|
5751
|
+
padding: "32px 0",
|
|
5752
|
+
lineHeight: 1.5
|
|
5753
|
+
});
|
|
5397
5754
|
var LINK_STEPS = /* @__PURE__ */ new Set([
|
|
5398
5755
|
"create-passkey",
|
|
5399
5756
|
"verify-passkey",
|
|
@@ -5441,6 +5798,9 @@ function StepRendererContent({
|
|
|
5441
5798
|
selectSourceChoices,
|
|
5442
5799
|
selectSourceRecommended,
|
|
5443
5800
|
selectSourceAvailableBalance,
|
|
5801
|
+
guestTokenEntries,
|
|
5802
|
+
guestLoadingBalances,
|
|
5803
|
+
guestSettingSender,
|
|
5444
5804
|
authInput,
|
|
5445
5805
|
otpCode,
|
|
5446
5806
|
selectSourceChainName,
|
|
@@ -5522,6 +5882,7 @@ function StepRendererContent({
|
|
|
5522
5882
|
);
|
|
5523
5883
|
}
|
|
5524
5884
|
if (step === "wallet-picker") {
|
|
5885
|
+
const isEntryPoint = !state.isGuestFlow && !authenticated;
|
|
5525
5886
|
return /* @__PURE__ */ jsx(
|
|
5526
5887
|
WalletPickerScreen,
|
|
5527
5888
|
{
|
|
@@ -5534,8 +5895,10 @@ function StepRendererContent({
|
|
|
5534
5895
|
onPrepareProvider: handlers.onPrepareProvider,
|
|
5535
5896
|
onSelectProvider: handlers.onSelectProvider,
|
|
5536
5897
|
onContinueConnection: handlers.onContinueConnection,
|
|
5537
|
-
onBack: () => handlers.onNavigate(state.activeCredentialId ? "deposit" : "create-passkey"),
|
|
5538
|
-
onLogout: handlers.onLogout
|
|
5898
|
+
onBack: isEntryPoint ? onBack : () => handlers.onNavigate(state.activeCredentialId ? "deposit" : "create-passkey"),
|
|
5899
|
+
onLogout: authenticated ? handlers.onLogout : void 0,
|
|
5900
|
+
onLogin: handlers.onLogin,
|
|
5901
|
+
showLoginOption: isEntryPoint
|
|
5539
5902
|
}
|
|
5540
5903
|
);
|
|
5541
5904
|
}
|
|
@@ -5642,6 +6005,20 @@ function StepRendererContent({
|
|
|
5642
6005
|
);
|
|
5643
6006
|
}
|
|
5644
6007
|
if (step === "token-picker") {
|
|
6008
|
+
if (state.isGuestFlow) {
|
|
6009
|
+
return /* @__PURE__ */ jsx(
|
|
6010
|
+
GuestTokenPickerScreen,
|
|
6011
|
+
{
|
|
6012
|
+
entries: guestTokenEntries,
|
|
6013
|
+
loading: guestLoadingBalances,
|
|
6014
|
+
setting: guestSettingSender,
|
|
6015
|
+
depositAmount: depositAmount ?? void 0,
|
|
6016
|
+
error: state.error,
|
|
6017
|
+
onSelect: handlers.onSelectGuestToken,
|
|
6018
|
+
onBack: () => handlers.onNavigate("wallet-picker")
|
|
6019
|
+
}
|
|
6020
|
+
);
|
|
6021
|
+
}
|
|
5645
6022
|
if (!selectedAccount) {
|
|
5646
6023
|
return /* @__PURE__ */ jsx(BlinkLoadingScreen, {});
|
|
5647
6024
|
}
|
|
@@ -6397,12 +6774,68 @@ function useSourceSelectionHandlers(dispatch, authExecutor) {
|
|
|
6397
6774
|
preSelectSourceStepRef
|
|
6398
6775
|
};
|
|
6399
6776
|
}
|
|
6400
|
-
function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs) {
|
|
6777
|
+
function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, onComplete) {
|
|
6401
6778
|
const {
|
|
6402
6779
|
mobileSetupFlowRef,
|
|
6403
6780
|
handlingMobileReturnRef,
|
|
6404
6781
|
loadingDataRef
|
|
6405
6782
|
} = refs;
|
|
6783
|
+
const { apiBaseUrl } = useBlinkConfig();
|
|
6784
|
+
const onCompleteRef = useRef(onComplete);
|
|
6785
|
+
onCompleteRef.current = onComplete;
|
|
6786
|
+
const guestPollingActiveRef = useRef(false);
|
|
6787
|
+
useEffect(() => {
|
|
6788
|
+
const persisted = loadMobileFlowState();
|
|
6789
|
+
if (!persisted?.isGuestCheckout || !persisted.transferId || !persisted.guestSessionToken) return;
|
|
6790
|
+
if (guestPollingActiveRef.current) return;
|
|
6791
|
+
guestPollingActiveRef.current = true;
|
|
6792
|
+
const transferId = persisted.transferId;
|
|
6793
|
+
const guestSessionToken = persisted.guestSessionToken;
|
|
6794
|
+
let cancelled = false;
|
|
6795
|
+
const POLL_INTERVAL_MS = 3e3;
|
|
6796
|
+
dispatch({ type: "NAVIGATE", step: "processing" });
|
|
6797
|
+
const poll = async () => {
|
|
6798
|
+
if (cancelled) return;
|
|
6799
|
+
try {
|
|
6800
|
+
const transfer = await getGuestTransfer(apiBaseUrl, transferId, guestSessionToken);
|
|
6801
|
+
if (cancelled) return;
|
|
6802
|
+
if (transfer.status === "COMPLETED") {
|
|
6803
|
+
cancelled = true;
|
|
6804
|
+
guestPollingActiveRef.current = false;
|
|
6805
|
+
clearMobileFlowState();
|
|
6806
|
+
dispatch({ type: "GUEST_TRANSFER_COMPLETED", transfer });
|
|
6807
|
+
onCompleteRef.current?.(transfer);
|
|
6808
|
+
} else if (transfer.status === "FAILED") {
|
|
6809
|
+
cancelled = true;
|
|
6810
|
+
guestPollingActiveRef.current = false;
|
|
6811
|
+
clearMobileFlowState();
|
|
6812
|
+
dispatch({ type: "TRANSFER_FAILED", transfer, error: "Transfer failed." });
|
|
6813
|
+
}
|
|
6814
|
+
} catch {
|
|
6815
|
+
}
|
|
6816
|
+
};
|
|
6817
|
+
poll();
|
|
6818
|
+
const intervalId = window.setInterval(poll, POLL_INTERVAL_MS);
|
|
6819
|
+
const handleVisibility = () => {
|
|
6820
|
+
if (document.visibilityState === "visible" && !cancelled) {
|
|
6821
|
+
poll();
|
|
6822
|
+
}
|
|
6823
|
+
};
|
|
6824
|
+
const handlePageShow = (e) => {
|
|
6825
|
+
if (e.persisted && !cancelled) {
|
|
6826
|
+
poll();
|
|
6827
|
+
}
|
|
6828
|
+
};
|
|
6829
|
+
document.addEventListener("visibilitychange", handleVisibility);
|
|
6830
|
+
window.addEventListener("pageshow", handlePageShow);
|
|
6831
|
+
return () => {
|
|
6832
|
+
cancelled = true;
|
|
6833
|
+
guestPollingActiveRef.current = false;
|
|
6834
|
+
window.clearInterval(intervalId);
|
|
6835
|
+
document.removeEventListener("visibilitychange", handleVisibility);
|
|
6836
|
+
window.removeEventListener("pageshow", handlePageShow);
|
|
6837
|
+
};
|
|
6838
|
+
}, [apiBaseUrl, dispatch]);
|
|
6406
6839
|
const handleAuthorizedMobileReturn = useCallback(async (authorizedTransfer, isSetup) => {
|
|
6407
6840
|
if (handlingMobileReturnRef.current) return;
|
|
6408
6841
|
handlingMobileReturnRef.current = true;
|
|
@@ -6461,9 +6894,17 @@ function useProviderHandlers(deps) {
|
|
|
6461
6894
|
handlingMobileReturnRef,
|
|
6462
6895
|
setupAccountIdRef,
|
|
6463
6896
|
reauthSessionIdRef,
|
|
6464
|
-
reauthTokenRef
|
|
6897
|
+
reauthTokenRef,
|
|
6898
|
+
authenticated,
|
|
6899
|
+
merchantAuthorization,
|
|
6900
|
+
destination
|
|
6465
6901
|
} = deps;
|
|
6902
|
+
const wagmiConfig2 = useConfig();
|
|
6903
|
+
const { connectAsync, connectors } = useConnect();
|
|
6466
6904
|
const handlePrepareProvider = useCallback(async (providerId) => {
|
|
6905
|
+
if (!authenticated) {
|
|
6906
|
+
return null;
|
|
6907
|
+
}
|
|
6467
6908
|
if (!activeCredentialId) {
|
|
6468
6909
|
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6469
6910
|
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
@@ -6491,8 +6932,85 @@ function useProviderHandlers(deps) {
|
|
|
6491
6932
|
onError?.(msg);
|
|
6492
6933
|
return null;
|
|
6493
6934
|
}
|
|
6494
|
-
}, [activeCredentialId, providers, apiBaseUrl, getAccessToken, onError, dispatch]);
|
|
6935
|
+
}, [authenticated, activeCredentialId, providers, apiBaseUrl, getAccessToken, onError, dispatch]);
|
|
6936
|
+
const handleGuestSelectProvider = useCallback(async (providerId) => {
|
|
6937
|
+
if (!merchantAuthorization || !destination) {
|
|
6938
|
+
const msg = "Missing payment configuration for guest checkout.";
|
|
6939
|
+
dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
|
|
6940
|
+
onError?.(msg);
|
|
6941
|
+
return;
|
|
6942
|
+
}
|
|
6943
|
+
const isMobile = !shouldUseWalletConnector({
|
|
6944
|
+
useWalletConnector: useWalletConnectorProp,
|
|
6945
|
+
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
6946
|
+
});
|
|
6947
|
+
dispatch({ type: "SELECT_PROVIDER", providerId });
|
|
6948
|
+
try {
|
|
6949
|
+
const result = await createGuestTransfer(apiBaseUrl, {
|
|
6950
|
+
merchantAuthorization,
|
|
6951
|
+
destinations: [{
|
|
6952
|
+
chainId: destination.chainId,
|
|
6953
|
+
token: { address: destination.token.address },
|
|
6954
|
+
address: destination.address
|
|
6955
|
+
}],
|
|
6956
|
+
amount: depositAmount ?? 0,
|
|
6957
|
+
providerId
|
|
6958
|
+
});
|
|
6959
|
+
if (isMobile) {
|
|
6960
|
+
if (!result.uri) {
|
|
6961
|
+
dispatch({ type: "PAY_ERROR", error: "This wallet is not available on mobile.", fallbackStep: "wallet-picker" });
|
|
6962
|
+
return;
|
|
6963
|
+
}
|
|
6964
|
+
persistMobileFlowState({
|
|
6965
|
+
transferId: result.id,
|
|
6966
|
+
guestSessionToken: result.guestSessionToken,
|
|
6967
|
+
isGuestCheckout: true,
|
|
6968
|
+
deeplinkUri: result.uri,
|
|
6969
|
+
providerId,
|
|
6970
|
+
isSetup: false
|
|
6971
|
+
});
|
|
6972
|
+
triggerDeeplink(result.uri);
|
|
6973
|
+
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: result.uri });
|
|
6974
|
+
} else {
|
|
6975
|
+
const account = getAccount(wagmiConfig2);
|
|
6976
|
+
if (!account.isConnected) {
|
|
6977
|
+
const connector = connectors.find((c) => c.type === "injected") ?? connectors[0];
|
|
6978
|
+
if (!connector) {
|
|
6979
|
+
dispatch({ type: "PAY_ERROR", error: "No wallet extension found. Please install a supported wallet.", fallbackStep: "wallet-picker" });
|
|
6980
|
+
return;
|
|
6981
|
+
}
|
|
6982
|
+
await connectAsync({ connector });
|
|
6983
|
+
}
|
|
6984
|
+
dispatch({
|
|
6985
|
+
type: "GUEST_PROVIDER_SELECTED",
|
|
6986
|
+
providerId,
|
|
6987
|
+
transferId: result.id,
|
|
6988
|
+
guestSessionToken: result.guestSessionToken
|
|
6989
|
+
});
|
|
6990
|
+
}
|
|
6991
|
+
} catch (err) {
|
|
6992
|
+
captureException(err);
|
|
6993
|
+
const msg = err instanceof Error ? err.message : "Failed to start guest checkout";
|
|
6994
|
+
dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
|
|
6995
|
+
onError?.(msg);
|
|
6996
|
+
}
|
|
6997
|
+
}, [
|
|
6998
|
+
merchantAuthorization,
|
|
6999
|
+
destination,
|
|
7000
|
+
apiBaseUrl,
|
|
7001
|
+
depositAmount,
|
|
7002
|
+
useWalletConnectorProp,
|
|
7003
|
+
wagmiConfig2,
|
|
7004
|
+
connectors,
|
|
7005
|
+
connectAsync,
|
|
7006
|
+
onError,
|
|
7007
|
+
dispatch
|
|
7008
|
+
]);
|
|
6495
7009
|
const handleSelectProvider = useCallback(async (providerId, preparedSession) => {
|
|
7010
|
+
if (!authenticated) {
|
|
7011
|
+
await handleGuestSelectProvider(providerId);
|
|
7012
|
+
return;
|
|
7013
|
+
}
|
|
6496
7014
|
dispatch({ type: "SELECT_PROVIDER", providerId });
|
|
6497
7015
|
if (!activeCredentialId) {
|
|
6498
7016
|
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
@@ -6562,6 +7080,8 @@ function useProviderHandlers(deps) {
|
|
|
6562
7080
|
}
|
|
6563
7081
|
}
|
|
6564
7082
|
}, [
|
|
7083
|
+
authenticated,
|
|
7084
|
+
handleGuestSelectProvider,
|
|
6565
7085
|
activeCredentialId,
|
|
6566
7086
|
providers,
|
|
6567
7087
|
apiBaseUrl,
|
|
@@ -6797,6 +7317,217 @@ function useProviderHandlers(deps) {
|
|
|
6797
7317
|
handleAuthorizeToken
|
|
6798
7318
|
};
|
|
6799
7319
|
}
|
|
7320
|
+
|
|
7321
|
+
// src/guestTokens.ts
|
|
7322
|
+
function mapBalancesToGuestTokenEntries(options) {
|
|
7323
|
+
return options.map((opt) => ({
|
|
7324
|
+
chainId: opt.chainId,
|
|
7325
|
+
sourceChainId: opt.sourceChainId,
|
|
7326
|
+
chainName: opt.chainName,
|
|
7327
|
+
tokenSymbol: opt.tokenSymbol,
|
|
7328
|
+
tokenAddress: opt.tokenAddress,
|
|
7329
|
+
decimals: opt.decimals,
|
|
7330
|
+
rawBalance: opt.rawBalance,
|
|
7331
|
+
balance: Number(opt.rawBalance) / 10 ** opt.decimals
|
|
7332
|
+
})).filter((entry) => entry.balance > 0).sort((a, b) => b.balance - a.balance);
|
|
7333
|
+
}
|
|
7334
|
+
|
|
7335
|
+
// src/hooks/useGuestTransferHandlers.ts
|
|
7336
|
+
var GUEST_SIGN_POLL_MS = 2e3;
|
|
7337
|
+
var GUEST_SIGN_MAX_POLLS = 90;
|
|
7338
|
+
var GUEST_COMPLETION_POLL_MS = 3e3;
|
|
7339
|
+
var GUEST_COMPLETION_MAX_POLLS = 120;
|
|
7340
|
+
function isUserRejection2(msg) {
|
|
7341
|
+
const lower = msg.toLowerCase();
|
|
7342
|
+
return lower.includes("rejected") || lower.includes("denied") || lower.includes("cancelled");
|
|
7343
|
+
}
|
|
7344
|
+
function useGuestTransferHandlers(deps) {
|
|
7345
|
+
const {
|
|
7346
|
+
dispatch,
|
|
7347
|
+
isGuestFlow,
|
|
7348
|
+
guestTransferId,
|
|
7349
|
+
guestSessionToken,
|
|
7350
|
+
step,
|
|
7351
|
+
onComplete,
|
|
7352
|
+
onError
|
|
7353
|
+
} = deps;
|
|
7354
|
+
const { apiBaseUrl } = useBlinkConfig();
|
|
7355
|
+
const wagmiConfig2 = useConfig();
|
|
7356
|
+
const { switchChainAsync } = useSwitchChain();
|
|
7357
|
+
const [guestTokenEntries, setGuestTokenEntries] = useState([]);
|
|
7358
|
+
const [loadingBalances, setLoadingBalances] = useState(false);
|
|
7359
|
+
const [settingSender, setSettingSender] = useState(false);
|
|
7360
|
+
const executingBridgeRef = useRef(false);
|
|
7361
|
+
const fetchedRef = useRef(false);
|
|
7362
|
+
const selectedGuestTokenRef = useRef(null);
|
|
7363
|
+
useEffect(() => {
|
|
7364
|
+
if (!isGuestFlow || step !== "token-picker" || fetchedRef.current) return;
|
|
7365
|
+
if (!guestTransferId || !guestSessionToken) return;
|
|
7366
|
+
const account = getAccount(wagmiConfig2);
|
|
7367
|
+
if (!account.address) return;
|
|
7368
|
+
fetchedRef.current = true;
|
|
7369
|
+
setLoadingBalances(true);
|
|
7370
|
+
fetchGuestTransferBalances(apiBaseUrl, guestTransferId, guestSessionToken, account.address).then((options) => mapBalancesToGuestTokenEntries(options)).then((entries) => {
|
|
7371
|
+
setGuestTokenEntries(entries);
|
|
7372
|
+
if (entries.length === 0) {
|
|
7373
|
+
dispatch({ type: "SET_ERROR", error: "No supported tokens found in your wallet." });
|
|
7374
|
+
}
|
|
7375
|
+
}).catch((err) => {
|
|
7376
|
+
captureException(err);
|
|
7377
|
+
dispatch({ type: "SET_ERROR", error: "Failed to fetch token balances." });
|
|
7378
|
+
}).finally(() => setLoadingBalances(false));
|
|
7379
|
+
}, [isGuestFlow, step, guestTransferId, guestSessionToken, apiBaseUrl, wagmiConfig2, dispatch]);
|
|
7380
|
+
useEffect(() => {
|
|
7381
|
+
if (!isGuestFlow) {
|
|
7382
|
+
fetchedRef.current = false;
|
|
7383
|
+
selectedGuestTokenRef.current = null;
|
|
7384
|
+
setGuestTokenEntries([]);
|
|
7385
|
+
}
|
|
7386
|
+
}, [isGuestFlow]);
|
|
7387
|
+
const handleSelectGuestToken = useCallback(async (entry) => {
|
|
7388
|
+
if (!guestTransferId || !guestSessionToken) return;
|
|
7389
|
+
const account = getAccount(wagmiConfig2);
|
|
7390
|
+
if (!account.address) {
|
|
7391
|
+
dispatch({ type: "SET_ERROR", error: "Wallet not connected." });
|
|
7392
|
+
return;
|
|
7393
|
+
}
|
|
7394
|
+
setSettingSender(true);
|
|
7395
|
+
try {
|
|
7396
|
+
console.info(
|
|
7397
|
+
`[blink-sdk] type=guest Setting sender: address=${account.address}, chain=${entry.sourceChainId}, token=${entry.tokenSymbol}`
|
|
7398
|
+
);
|
|
7399
|
+
await setTransferSender(
|
|
7400
|
+
apiBaseUrl,
|
|
7401
|
+
guestTransferId,
|
|
7402
|
+
guestSessionToken,
|
|
7403
|
+
account.address,
|
|
7404
|
+
entry.sourceChainId,
|
|
7405
|
+
entry.tokenAddress
|
|
7406
|
+
);
|
|
7407
|
+
selectedGuestTokenRef.current = entry;
|
|
7408
|
+
dispatch({ type: "NAVIGATE", step: "processing" });
|
|
7409
|
+
} catch (err) {
|
|
7410
|
+
captureException(err);
|
|
7411
|
+
const msg = err instanceof Error ? err.message : "Failed to set transfer sender";
|
|
7412
|
+
dispatch({ type: "SET_ERROR", error: msg });
|
|
7413
|
+
onError?.(msg);
|
|
7414
|
+
} finally {
|
|
7415
|
+
setSettingSender(false);
|
|
7416
|
+
}
|
|
7417
|
+
}, [guestTransferId, guestSessionToken, wagmiConfig2, apiBaseUrl, dispatch, onError]);
|
|
7418
|
+
useEffect(() => {
|
|
7419
|
+
if (!isGuestFlow || step !== "processing" || !guestTransferId || !guestSessionToken) return;
|
|
7420
|
+
if (executingBridgeRef.current) return;
|
|
7421
|
+
executingBridgeRef.current = true;
|
|
7422
|
+
const execute = async () => {
|
|
7423
|
+
try {
|
|
7424
|
+
let signPayload = null;
|
|
7425
|
+
for (let i = 0; i < GUEST_SIGN_MAX_POLLS; i++) {
|
|
7426
|
+
const transfer = await getGuestTransfer(apiBaseUrl, guestTransferId, guestSessionToken);
|
|
7427
|
+
const payload = transfer.signPayload;
|
|
7428
|
+
if (payload?.bridgeSteps && payload.bridgeSteps.length > 0) {
|
|
7429
|
+
signPayload = payload;
|
|
7430
|
+
break;
|
|
7431
|
+
}
|
|
7432
|
+
if (transfer.status === "FAILED") {
|
|
7433
|
+
dispatch({ type: "PAY_ERROR", error: "Transfer failed.", fallbackStep: "wallet-picker" });
|
|
7434
|
+
return;
|
|
7435
|
+
}
|
|
7436
|
+
await new Promise((r) => setTimeout(r, GUEST_SIGN_POLL_MS));
|
|
7437
|
+
}
|
|
7438
|
+
if (!signPayload) {
|
|
7439
|
+
dispatch({
|
|
7440
|
+
type: "PAY_ERROR",
|
|
7441
|
+
error: "Timed out waiting for bridge quote. Please try again.",
|
|
7442
|
+
fallbackStep: "wallet-picker"
|
|
7443
|
+
});
|
|
7444
|
+
return;
|
|
7445
|
+
}
|
|
7446
|
+
console.info(
|
|
7447
|
+
`[blink-sdk] type=guest Bridge quote ready: ${signPayload.bridgeSteps.length} step(s), token=${signPayload.tokenSymbol}, chain=${signPayload.chainName}`
|
|
7448
|
+
);
|
|
7449
|
+
const selectedToken = selectedGuestTokenRef.current;
|
|
7450
|
+
const account = getAccount(wagmiConfig2);
|
|
7451
|
+
const targetChainId = selectedToken?.chainId;
|
|
7452
|
+
if (targetChainId) {
|
|
7453
|
+
const numericChainId = Number(targetChainId);
|
|
7454
|
+
if (!isNaN(numericChainId) && account.chainId !== numericChainId) {
|
|
7455
|
+
console.info(`[blink-sdk] type=guest Switching chain to ${numericChainId}`);
|
|
7456
|
+
await switchChainAsync({ chainId: numericChainId });
|
|
7457
|
+
}
|
|
7458
|
+
}
|
|
7459
|
+
const walletClient = await getWalletClient(wagmiConfig2);
|
|
7460
|
+
const sender = account.address;
|
|
7461
|
+
if (!sender) {
|
|
7462
|
+
dispatch({ type: "PAY_ERROR", error: "Wallet not connected.", fallbackStep: "wallet-picker" });
|
|
7463
|
+
return;
|
|
7464
|
+
}
|
|
7465
|
+
let lastTxHash = null;
|
|
7466
|
+
for (let stepIdx = 0; stepIdx < signPayload.bridgeSteps.length; stepIdx++) {
|
|
7467
|
+
const bridgeStep = signPayload.bridgeSteps[stepIdx];
|
|
7468
|
+
console.info(
|
|
7469
|
+
`[blink-sdk] type=guest Executing bridge step ${stepIdx + 1}/${signPayload.bridgeSteps.length} to=${bridgeStep.to}`
|
|
7470
|
+
);
|
|
7471
|
+
const txHash = await walletClient.request({
|
|
7472
|
+
method: "eth_sendTransaction",
|
|
7473
|
+
params: [{
|
|
7474
|
+
from: sender,
|
|
7475
|
+
to: bridgeStep.to,
|
|
7476
|
+
data: bridgeStep.data,
|
|
7477
|
+
value: bridgeStep.value
|
|
7478
|
+
}]
|
|
7479
|
+
});
|
|
7480
|
+
console.info(`[blink-sdk] type=guest Bridge step ${stepIdx + 1} tx sent: ${txHash}`);
|
|
7481
|
+
await waitForTransactionReceipt(wagmiConfig2, {
|
|
7482
|
+
hash: txHash
|
|
7483
|
+
});
|
|
7484
|
+
lastTxHash = txHash;
|
|
7485
|
+
}
|
|
7486
|
+
if (!lastTxHash) {
|
|
7487
|
+
dispatch({ type: "PAY_ERROR", error: "No bridge transactions were executed.", fallbackStep: "wallet-picker" });
|
|
7488
|
+
return;
|
|
7489
|
+
}
|
|
7490
|
+
console.info(`[blink-sdk] type=guest Submitting originTxHash: ${lastTxHash}`);
|
|
7491
|
+
await signGuestTransfer(apiBaseUrl, guestTransferId, guestSessionToken, lastTxHash);
|
|
7492
|
+
for (let i = 0; i < GUEST_COMPLETION_MAX_POLLS; i++) {
|
|
7493
|
+
const transfer = await getGuestTransfer(apiBaseUrl, guestTransferId, guestSessionToken);
|
|
7494
|
+
if (transfer.status === "COMPLETED") {
|
|
7495
|
+
console.info(`[blink-sdk] type=guest Transfer completed`);
|
|
7496
|
+
dispatch({ type: "GUEST_TRANSFER_COMPLETED", transfer });
|
|
7497
|
+
onComplete?.(transfer);
|
|
7498
|
+
return;
|
|
7499
|
+
}
|
|
7500
|
+
if (transfer.status === "FAILED") {
|
|
7501
|
+
dispatch({ type: "TRANSFER_FAILED", transfer, error: "Transfer failed." });
|
|
7502
|
+
return;
|
|
7503
|
+
}
|
|
7504
|
+
await new Promise((r) => setTimeout(r, GUEST_COMPLETION_POLL_MS));
|
|
7505
|
+
}
|
|
7506
|
+
dispatch({
|
|
7507
|
+
type: "PAY_ERROR",
|
|
7508
|
+
error: "Transfer is taking longer than expected. It may still complete.",
|
|
7509
|
+
fallbackStep: "wallet-picker"
|
|
7510
|
+
});
|
|
7511
|
+
} catch (err) {
|
|
7512
|
+
captureException(err);
|
|
7513
|
+
const msg = err instanceof Error ? err.message : "Bridge execution failed";
|
|
7514
|
+
console.error("[blink-sdk] type=guest Bridge execution error:", err);
|
|
7515
|
+
const displayMsg = isUserRejection2(msg) ? "You rejected the transaction. Please approve in your wallet to continue." : msg;
|
|
7516
|
+
dispatch({ type: "PAY_ERROR", error: displayMsg, fallbackStep: "wallet-picker" });
|
|
7517
|
+
onError?.(displayMsg);
|
|
7518
|
+
} finally {
|
|
7519
|
+
executingBridgeRef.current = false;
|
|
7520
|
+
}
|
|
7521
|
+
};
|
|
7522
|
+
execute();
|
|
7523
|
+
}, [isGuestFlow, step, guestTransferId, guestSessionToken, apiBaseUrl, wagmiConfig2, switchChainAsync, dispatch, onComplete, onError]);
|
|
7524
|
+
return {
|
|
7525
|
+
guestTokenEntries,
|
|
7526
|
+
loadingBalances,
|
|
7527
|
+
settingSender,
|
|
7528
|
+
handleSelectGuestToken
|
|
7529
|
+
};
|
|
7530
|
+
}
|
|
6800
7531
|
function useOneTapSetupHandlers(deps) {
|
|
6801
7532
|
const {
|
|
6802
7533
|
dispatch,
|
|
@@ -7259,6 +7990,32 @@ function usePaymentEffects(deps) {
|
|
|
7259
7990
|
state.selectedAccountId,
|
|
7260
7991
|
depositAmount
|
|
7261
7992
|
]);
|
|
7993
|
+
useEffect(() => {
|
|
7994
|
+
if (authenticated || state.providers.length > 0) return;
|
|
7995
|
+
if (state.step !== "wallet-picker") return;
|
|
7996
|
+
let cancelled = false;
|
|
7997
|
+
const loadProviders = async () => {
|
|
7998
|
+
try {
|
|
7999
|
+
const providers = await fetchProviders(apiBaseUrl);
|
|
8000
|
+
if (cancelled) return;
|
|
8001
|
+
dispatch({
|
|
8002
|
+
type: "DATA_LOADED",
|
|
8003
|
+
providers,
|
|
8004
|
+
accounts: state.accounts,
|
|
8005
|
+
chains: state.chains,
|
|
8006
|
+
defaults: null
|
|
8007
|
+
});
|
|
8008
|
+
} catch (err) {
|
|
8009
|
+
if (!cancelled) {
|
|
8010
|
+
captureException(err);
|
|
8011
|
+
}
|
|
8012
|
+
}
|
|
8013
|
+
};
|
|
8014
|
+
loadProviders();
|
|
8015
|
+
return () => {
|
|
8016
|
+
cancelled = true;
|
|
8017
|
+
};
|
|
8018
|
+
}, [authenticated, state.step, state.providers.length, apiBaseUrl]);
|
|
7262
8019
|
useEffect(() => {
|
|
7263
8020
|
if (!polling.transfer) return;
|
|
7264
8021
|
if (polling.transfer.status === "COMPLETED") {
|
|
@@ -7592,7 +8349,8 @@ function BlinkPaymentInner({
|
|
|
7592
8349
|
transfer.reloadAccounts,
|
|
7593
8350
|
transfer.pollingTransferIdRef,
|
|
7594
8351
|
state.transfer,
|
|
7595
|
-
mobileFlowRefs
|
|
8352
|
+
mobileFlowRefs,
|
|
8353
|
+
onComplete
|
|
7596
8354
|
);
|
|
7597
8355
|
const sourceSelection = useSourceSelectionHandlers(dispatch, authExecutor);
|
|
7598
8356
|
const provider = useProviderHandlers({
|
|
@@ -7615,7 +8373,10 @@ function BlinkPaymentInner({
|
|
|
7615
8373
|
handlingMobileReturnRef: mobileFlowRefs.handlingMobileReturnRef,
|
|
7616
8374
|
setupAccountIdRef: mobileFlowRefs.setupAccountIdRef,
|
|
7617
8375
|
reauthSessionIdRef: mobileFlowRefs.reauthSessionIdRef,
|
|
7618
|
-
reauthTokenRef: mobileFlowRefs.reauthTokenRef
|
|
8376
|
+
reauthTokenRef: mobileFlowRefs.reauthTokenRef,
|
|
8377
|
+
authenticated,
|
|
8378
|
+
merchantAuthorization,
|
|
8379
|
+
destination
|
|
7619
8380
|
});
|
|
7620
8381
|
const oneTapSetup = useOneTapSetupHandlers({
|
|
7621
8382
|
dispatch,
|
|
@@ -7625,6 +8386,15 @@ function BlinkPaymentInner({
|
|
|
7625
8386
|
selectSourceChainName: sourceSelection.selectSourceChainName,
|
|
7626
8387
|
selectSourceTokenSymbol: sourceSelection.selectSourceTokenSymbol
|
|
7627
8388
|
});
|
|
8389
|
+
const guestTransfer = useGuestTransferHandlers({
|
|
8390
|
+
dispatch,
|
|
8391
|
+
isGuestFlow: state.isGuestFlow,
|
|
8392
|
+
guestTransferId: state.guestTransferId,
|
|
8393
|
+
guestSessionToken: state.guestSessionToken,
|
|
8394
|
+
step: state.step,
|
|
8395
|
+
onComplete,
|
|
8396
|
+
onError
|
|
8397
|
+
});
|
|
7628
8398
|
const handleNewPayment = useCallback(() => {
|
|
7629
8399
|
clearMobileFlowState();
|
|
7630
8400
|
transfer.processingStartedAtRef.current = null;
|
|
@@ -7725,7 +8495,9 @@ function BlinkPaymentInner({
|
|
|
7725
8495
|
onSetupOneTap: oneTapSetup.handleSetupOneTap,
|
|
7726
8496
|
onSelectToken: provider.handleNavigateToTokenPicker,
|
|
7727
8497
|
onSelectAuthorizedToken: provider.handleSelectAuthorizedToken,
|
|
7728
|
-
onAuthorizeToken: provider.handleAuthorizeToken
|
|
8498
|
+
onAuthorizeToken: provider.handleAuthorizeToken,
|
|
8499
|
+
onSelectGuestToken: guestTransfer.handleSelectGuestToken,
|
|
8500
|
+
onLogin: () => dispatch({ type: "NAVIGATE", step: "login" })
|
|
7729
8501
|
}), [
|
|
7730
8502
|
auth,
|
|
7731
8503
|
passkey,
|
|
@@ -7734,6 +8506,7 @@ function BlinkPaymentInner({
|
|
|
7734
8506
|
mobileFlow,
|
|
7735
8507
|
sourceSelection,
|
|
7736
8508
|
oneTapSetup,
|
|
8509
|
+
guestTransfer,
|
|
7737
8510
|
handleLogout,
|
|
7738
8511
|
handleNewPayment
|
|
7739
8512
|
]);
|
|
@@ -7759,6 +8532,9 @@ function BlinkPaymentInner({
|
|
|
7759
8532
|
selectSourceChoices: sourceSelection.selectSourceChoices,
|
|
7760
8533
|
selectSourceRecommended: sourceSelection.selectSourceRecommended,
|
|
7761
8534
|
selectSourceAvailableBalance: sourceSelection.selectSourceAvailableBalance,
|
|
8535
|
+
guestTokenEntries: guestTransfer.guestTokenEntries,
|
|
8536
|
+
guestLoadingBalances: guestTransfer.loadingBalances,
|
|
8537
|
+
guestSettingSender: guestTransfer.settingSender,
|
|
7762
8538
|
authInput: auth.authInput,
|
|
7763
8539
|
otpCode: auth.otpCode,
|
|
7764
8540
|
selectSourceChainName: sourceSelection.selectSourceChainName,
|