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