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