@openfort/react 1.2.0 → 1.3.0
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/build/assets/logos.d.ts +3 -0
- package/build/assets/logos.js +2 -0
- package/build/assets/logos.js.map +1 -1
- package/build/components/Common/SolanaChain/index.d.ts +8 -0
- package/build/components/Common/SolanaChain/index.js +40 -0
- package/build/components/Common/SolanaChain/index.js.map +1 -0
- package/build/components/ConnectModal/index.js +2 -0
- package/build/components/ConnectModal/index.js.map +1 -1
- package/build/components/Openfort/types.d.ts +17 -11
- package/build/components/Openfort/types.js +1 -0
- package/build/components/Openfort/types.js.map +1 -1
- package/build/components/Pages/Buy/coinbaseApi.d.ts +1 -1
- package/build/components/Pages/Buy/coinbaseApi.js +2 -13
- package/build/components/Pages/Buy/coinbaseApi.js.map +1 -1
- package/build/components/Pages/Buy/evmCurrencies.d.ts +11 -0
- package/build/components/Pages/Buy/evmCurrencies.js +27 -0
- package/build/components/Pages/Buy/evmCurrencies.js.map +1 -0
- package/build/components/Pages/Buy/index.js +8 -1
- package/build/components/Pages/Buy/index.js.map +1 -1
- package/build/components/Pages/Buy/onrampApi.d.ts +8 -1
- package/build/components/Pages/Buy/onrampApi.js +24 -14
- package/build/components/Pages/Buy/onrampApi.js.map +1 -1
- package/build/components/Pages/Buy/solanaCurrencies.d.ts +9 -0
- package/build/components/Pages/Buy/solanaCurrencies.js +25 -0
- package/build/components/Pages/Buy/solanaCurrencies.js.map +1 -0
- package/build/components/Pages/Buy/stripeApi.d.ts +1 -1
- package/build/components/Pages/Buy/stripeApi.js +2 -13
- package/build/components/Pages/Buy/stripeApi.js.map +1 -1
- package/build/components/Pages/BuyComplete/index.js +7 -1
- package/build/components/Pages/BuyComplete/index.js.map +1 -1
- package/build/components/Pages/BuyProcessing/index.js +9 -5
- package/build/components/Pages/BuyProcessing/index.js.map +1 -1
- package/build/components/Pages/BuySelectProvider/index.js +10 -5
- package/build/components/Pages/BuySelectProvider/index.js.map +1 -1
- package/build/components/Pages/Connected/SolanaConnected.js +3 -2
- package/build/components/Pages/Connected/SolanaConnected.js.map +1 -1
- package/build/components/Pages/Deposit/DepositProgress.js +3 -2
- package/build/components/Pages/Deposit/DepositProgress.js.map +1 -1
- package/build/components/Pages/Deposit/DepositSuccess.js +2 -1
- package/build/components/Pages/Deposit/DepositSuccess.js.map +1 -1
- package/build/components/Pages/Deposit/index.js +16 -2
- package/build/components/Pages/Deposit/index.js.map +1 -1
- package/build/components/Pages/Deposit/paymentOptions.js +3 -3
- package/build/components/Pages/Deposit/useDepositRoute.d.ts +0 -1
- package/build/components/Pages/Deposit/useDepositRoute.js +10 -11
- package/build/components/Pages/Deposit/useDepositRoute.js.map +1 -1
- package/build/components/Pages/Deposit/useFundingTarget.d.ts +2 -4
- package/build/components/Pages/Deposit/useFundingTarget.js +3 -5
- package/build/components/Pages/Deposit/useFundingTarget.js.map +1 -1
- package/build/components/Pages/DepositCex/index.js +7 -8
- package/build/components/Pages/DepositCex/index.js.map +1 -1
- package/build/components/Pages/DepositWallet/DepositWalletDesktop.d.ts +4 -1
- package/build/components/Pages/DepositWallet/DepositWalletDesktop.js +11 -20
- package/build/components/Pages/DepositWallet/DepositWalletDesktop.js.map +1 -1
- package/build/components/Pages/DepositWallet/index.d.ts +5 -5
- package/build/components/Pages/DepositWallet/index.js +36 -31
- package/build/components/Pages/DepositWallet/index.js.map +1 -1
- package/build/components/Pages/DepositWallet/walletDeeplinks.d.ts +6 -4
- package/build/components/Pages/DepositWallet/walletDeeplinks.js +3 -1
- package/build/components/Pages/DepositWallet/walletDeeplinks.js.map +1 -1
- package/build/components/Pages/SelectToken/SolanaSelectToken.d.ts +1 -0
- package/build/components/Pages/SelectToken/SolanaSelectToken.js +50 -0
- package/build/components/Pages/SelectToken/SolanaSelectToken.js.map +1 -0
- package/build/components/Pages/SelectToken/index.js +13 -2
- package/build/components/Pages/SelectToken/index.js.map +1 -1
- package/build/components/Pages/Send/SolanaSend.js +32 -31
- package/build/components/Pages/Send/SolanaSend.js.map +1 -1
- package/build/components/Pages/Send/utils.js +4 -1
- package/build/components/Pages/Send/utils.js.map +1 -1
- package/build/components/Pages/SendConfirmation/SolanaSendConfirmation.js +57 -13
- package/build/components/Pages/SendConfirmation/SolanaSendConfirmation.js.map +1 -1
- package/build/components/Pages/SendConfirmation/styles.d.ts +0 -5
- package/build/components/Pages/SendConfirmation/styles.js +1 -39
- package/build/components/Pages/SendConfirmation/styles.js.map +1 -1
- package/build/hooks/openfort/useFunding.js +7 -7
- package/build/hooks/openfort/useFundingChains.js +4 -6
- package/build/hooks/openfort/useFundingChains.js.map +1 -1
- package/build/shared/hooks/useAsyncData.js +15 -2
- package/build/shared/hooks/useAsyncData.js.map +1 -1
- package/build/solana/transfer.d.ts +35 -6
- package/build/solana/transfer.js +112 -18
- package/build/solana/transfer.js.map +1 -1
- package/build/solana/types.d.ts +8 -0
- package/build/version.d.ts +1 -1
- package/build/version.js +1 -1
- package/package.json +5 -1
|
@@ -8,12 +8,15 @@ import { ModalHeading, ModalBody } from '../../Common/Modal/styles.js';
|
|
|
8
8
|
import { routes } from '../../Openfort/types.js';
|
|
9
9
|
import { useOpenfort } from '../../Openfort/useOpenfort.js';
|
|
10
10
|
import { PageContent } from '../../PageContent/index.js';
|
|
11
|
+
import { Section, SectionLabel, AmountCard, CurrencySymbol, AmountInput, PresetList, PresetButton } from '../Buy/styles.js';
|
|
11
12
|
import { AddressPageLink } from '../Deposit/AddressPageLink.js';
|
|
12
13
|
import { isDepositFlowActive, DepositProgress } from '../Deposit/DepositProgress.js';
|
|
13
14
|
import { walletListBtn } from '../Deposit/formStyles.js';
|
|
14
15
|
import { RouteSelectors } from '../Deposit/RouteSelectors.js';
|
|
16
|
+
import { isSolana } from '../Deposit/sources.js';
|
|
15
17
|
import { StepDivider, Skeleton, ButtonLogo } from '../Deposit/styles.js';
|
|
16
18
|
import { useDepositRoute } from '../Deposit/useDepositRoute.js';
|
|
19
|
+
import { sanitizeAmountInput } from '../Send/utils.js';
|
|
17
20
|
import { DepositWalletDesktop } from './DepositWalletDesktop.js';
|
|
18
21
|
import { OPENFORT_DEPOSIT_PAGE_URL, caipToChainId, buildDepositPageUrl, buildOpenDappLinks } from './walletDeeplinks.js';
|
|
19
22
|
|
|
@@ -26,58 +29,60 @@ const WALLET_LOGO = {
|
|
|
26
29
|
rainbow: jsx(Logos.Rainbow, { round: true }),
|
|
27
30
|
rabby: jsx(Logos.Rabby, {}),
|
|
28
31
|
};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
padding: '12px 14px',
|
|
32
|
-
borderRadius: 12,
|
|
33
|
-
border: '1px solid var(--ck-body-divider, #e4e4e7)',
|
|
34
|
-
background: 'var(--ck-body-background-secondary, #fafafa)',
|
|
35
|
-
color: 'var(--ck-body-color, #111)',
|
|
36
|
-
fontSize: 16,
|
|
37
|
-
outline: 'none',
|
|
38
|
-
marginTop: 14,
|
|
39
|
-
};
|
|
40
|
-
/** Keep only digits and a single decimal point. */
|
|
41
|
-
function sanitizeAmount(v) {
|
|
42
|
-
const cleaned = v.replace(/[^0-9.]/g, '');
|
|
43
|
-
const [whole, ...rest] = cleaned.split('.');
|
|
44
|
-
return rest.length ? `${whole}.${rest.join('')}` : cleaned;
|
|
45
|
-
}
|
|
32
|
+
/** Preset deposit amounts, in the selected source token's units. */
|
|
33
|
+
const PRESETS = [10, 25, 50];
|
|
46
34
|
/**
|
|
47
|
-
* Transfer from wallet.
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* from
|
|
51
|
-
*
|
|
35
|
+
* Transfer from wallet. Pick a source chain/token and an amount, then choose the
|
|
36
|
+
* wallet to send from. On mobile that's open-dApp deeplinks into the wallet app's
|
|
37
|
+
* in-app browser (address/chain/token/amount prefilled); on desktop it's a direct
|
|
38
|
+
* send from a browser-extension wallet. The manual deposit-address / QR path stays
|
|
39
|
+
* available below.
|
|
52
40
|
*/
|
|
53
41
|
const DepositWallet = () => {
|
|
54
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
42
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
55
43
|
const { triggerResize, uiConfig } = useOpenfort();
|
|
56
44
|
const isMobile = useIsMobile();
|
|
57
45
|
const route = useDepositRoute('crypto');
|
|
58
46
|
const [amount, setAmount] = useState('');
|
|
47
|
+
const [pressedPreset, setPressedPreset] = useState(null);
|
|
59
48
|
const depositPageUrl = (_b = (_a = uiConfig.funding) === null || _a === void 0 ? void 0 : _a.depositPageUrl) !== null && _b !== void 0 ? _b : OPENFORT_DEPOSIT_PAGE_URL;
|
|
60
|
-
|
|
49
|
+
// Solana sources have no numeric chain id and no desktop EVM-extension send, so
|
|
50
|
+
// they route through the deeplink (Phantom) on every platform instead of the
|
|
51
|
+
// wagmi-bridge desktop path.
|
|
52
|
+
const isSolanaSrc = isSolana((_d = (_c = route.activeChain) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : '');
|
|
53
|
+
const srcChainId = caipToChainId((_e = route.activeChain) === null || _e === void 0 ? void 0 : _e.id);
|
|
61
54
|
const amountValid = Number.parseFloat(amount) > 0;
|
|
55
|
+
const handleAmountChange = (event) => {
|
|
56
|
+
const raw = sanitizeAmountInput(event.target.value);
|
|
57
|
+
if (raw === '' || /^[0-9]*\.?[0-9]*$/.test(raw)) {
|
|
58
|
+
setPressedPreset(null);
|
|
59
|
+
setAmount(raw);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const handlePreset = (value) => {
|
|
63
|
+
setPressedPreset(value);
|
|
64
|
+
setAmount(String(value));
|
|
65
|
+
};
|
|
62
66
|
// Open-dApp deeplinks: prefer backend-provided ones; otherwise build them from
|
|
63
67
|
// the hosted deposit page URL (if the integrator configured one) carrying the
|
|
64
68
|
// resolved transfer params. The hosted page sends via the wallet's injected
|
|
65
69
|
// provider, so no backend wiring is required for the link itself.
|
|
66
|
-
const pageUrl = depositPageUrl && route.receiverAddress && route.activeCurrency && srcChainId
|
|
70
|
+
const pageUrl = depositPageUrl && route.receiverAddress && route.activeCurrency && (isSolanaSrc || srcChainId)
|
|
67
71
|
? buildDepositPageUrl(depositPageUrl, {
|
|
72
|
+
vm: isSolanaSrc ? 'svm' : 'evm',
|
|
68
73
|
to: route.receiverAddress,
|
|
69
|
-
chainId: srcChainId,
|
|
74
|
+
chainId: isSolanaSrc ? undefined : srcChainId,
|
|
70
75
|
token: route.activeCurrency.native ? undefined : route.activeCurrency.address,
|
|
71
76
|
decimals: route.activeCurrency.decimals,
|
|
72
77
|
symbol: route.activeCurrency.symbol,
|
|
73
|
-
chain: (
|
|
78
|
+
chain: (_f = route.activeChain) === null || _f === void 0 ? void 0 : _f.name,
|
|
74
79
|
amount: amountValid ? parseUnits(amount, route.activeCurrency.decimals).toString() : undefined,
|
|
75
80
|
})
|
|
76
81
|
: null;
|
|
77
|
-
const allDeeplinks = ((
|
|
82
|
+
const allDeeplinks = ((_h = (_g = route.pm) === null || _g === void 0 ? void 0 : _g.deeplinks) === null || _h === void 0 ? void 0 : _h.length)
|
|
78
83
|
? route.pm.deeplinks
|
|
79
84
|
: pageUrl
|
|
80
|
-
? buildOpenDappLinks(pageUrl, (
|
|
85
|
+
? buildOpenDappLinks(pageUrl, (_k = (_j = route.activeChain) === null || _j === void 0 ? void 0 : _j.vmType) !== null && _k !== void 0 ? _k : 'evm')
|
|
81
86
|
: [];
|
|
82
87
|
// Trust's in-app dApp browser was removed on iOS (Apple, 2021) — the link
|
|
83
88
|
// dead-ends there, so hide it on iOS while keeping it on Android.
|
|
@@ -87,7 +92,7 @@ const DepositWallet = () => {
|
|
|
87
92
|
}, [route.receiverAddress, route.loading, route.status, deeplinks.length, triggerResize]);
|
|
88
93
|
if (isDepositFlowActive(route.status))
|
|
89
94
|
return jsx(DepositProgress, { status: route.status });
|
|
90
|
-
return (jsxs(PageContent, { onBack: routes.DEPOSIT, children: [jsx(ModalHeading, { children: "Transfer from wallet" }), jsx(RouteSelectors, { chains: route.chains, chain: route.chain, currency: route.currency, chainLabel: "Supported chain", onChainChange: route.setChain, onCurrencyChange: route.setCurrency }), !route.isAvailable && jsx(ModalBody, { children: "Funding isn't available right now." }), jsx(
|
|
95
|
+
return (jsxs(PageContent, { onBack: routes.DEPOSIT, children: [jsx(ModalHeading, { children: "Transfer from wallet" }), jsx(RouteSelectors, { chains: route.chains, chain: route.chain, currency: route.currency, chainLabel: "Supported chain", onChainChange: route.setChain, onCurrencyChange: route.setCurrency }), !route.isAvailable && jsx(ModalBody, { children: "Funding isn't available right now." }), jsxs(Section, { children: [jsx(SectionLabel, { children: "Amount" }), jsxs(AmountCard, { children: [jsx(CurrencySymbol, { children: (_m = (_l = route.activeCurrency) === null || _l === void 0 ? void 0 : _l.symbol) !== null && _m !== void 0 ? _m : '' }), jsx(AmountInput, { value: amount, onChange: handleAmountChange, placeholder: "0.00", inputMode: "decimal", autoComplete: "off" })] }), jsx(PresetList, { children: PRESETS.map((preset) => (jsx(PresetButton, { type: "button", "$active": pressedPreset === preset, onClick: () => handlePreset(preset), children: preset }, preset))) })] }), jsx(StepDivider, { children: "Then select the wallet you want to use" }), isMobile || isSolanaSrc ? (jsxs(Fragment, { children: [!depositPageUrl && (jsx(ModalBody, { style: { marginTop: 12 }, children: "Use a deposit address below to fund from your wallet." })), route.loading && !route.pm && (jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8, marginTop: 14 }, children: [jsx(Skeleton, { "$h": "44px", "$r": "10px" }), jsx(Skeleton, { "$h": "44px", "$r": "10px" }), jsx(Skeleton, { "$h": "44px", "$r": "10px" })] })), deeplinks.length > 0 && (jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 8, marginTop: 14 }, children: deeplinks.map((d) => (jsxs("a", { href: amountValid ? d.url : undefined, "aria-disabled": !amountValid, target: "_blank", rel: "noreferrer", style: {
|
|
91
96
|
...walletListBtn,
|
|
92
97
|
display: 'flex',
|
|
93
98
|
alignItems: 'center',
|
|
@@ -95,7 +100,7 @@ const DepositWallet = () => {
|
|
|
95
100
|
gap: 8,
|
|
96
101
|
opacity: amountValid ? 1 : 0.55,
|
|
97
102
|
pointerEvents: amountValid ? 'auto' : 'none',
|
|
98
|
-
}, children: [WALLET_LOGO[d.app] && jsx(ButtonLogo, { children: WALLET_LOGO[d.app] }), d.label, " \u2197"] }, d.app))) }))] })) : (jsx(DepositWalletDesktop, { receiverAddress: route.receiverAddress, activeChain: route.activeChain, activeCurrency: route.activeCurrency, loading: route.loading })), jsx(AddressPageLink, { label: "Or send to a deposit address" }), route.error && jsx(ModalBody, { style: { color: '#dc2626', marginTop: 12 }, children: route.error.message })] }));
|
|
103
|
+
}, children: [WALLET_LOGO[d.app] && jsx(ButtonLogo, { children: WALLET_LOGO[d.app] }), d.label, " \u2197"] }, d.app))) }))] })) : (jsx(DepositWalletDesktop, { receiverAddress: route.receiverAddress, activeChain: route.activeChain, activeCurrency: route.activeCurrency, loading: route.loading, amount: amount })), jsx(AddressPageLink, { label: "Or send to a deposit address" }), route.error && jsx(ModalBody, { style: { color: '#dc2626', marginTop: 12 }, children: route.error.message })] }));
|
|
99
104
|
};
|
|
100
105
|
|
|
101
106
|
export { DepositWallet as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -23,11 +23,13 @@ export type VmType = 'evm' | 'svm';
|
|
|
23
23
|
*/
|
|
24
24
|
export declare const OPENFORT_DEPOSIT_PAGE_URL = "https://deposit.openfort.io";
|
|
25
25
|
type DepositPageParams = {
|
|
26
|
-
/**
|
|
26
|
+
/** Source VM family. `evm` drives a window.ethereum send; `svm` a Solana Pay request. */
|
|
27
|
+
vm: VmType;
|
|
28
|
+
/** Relay deposit address the source funds go to (0x for EVM, base58 for Solana). */
|
|
27
29
|
to: string;
|
|
28
|
-
/** Numeric source chain id (e.g. 42161). */
|
|
29
|
-
chainId
|
|
30
|
-
/** ERC-20 contract, or empty/undefined for the chain's native token. */
|
|
30
|
+
/** Numeric source chain id (e.g. 42161). EVM only. */
|
|
31
|
+
chainId?: number;
|
|
32
|
+
/** ERC-20 contract / SPL mint, or empty/undefined for the chain's native token. */
|
|
31
33
|
token?: string;
|
|
32
34
|
decimals: number;
|
|
33
35
|
symbol: string;
|
|
@@ -19,8 +19,10 @@ const OPENFORT_DEPOSIT_PAGE_URL = 'https://deposit.openfort.io';
|
|
|
19
19
|
/** Build the deposit "send" page URL with the transfer params encoded. */
|
|
20
20
|
function buildDepositPageUrl(baseUrl, p) {
|
|
21
21
|
const url = new URL(baseUrl);
|
|
22
|
+
url.searchParams.set('vm', p.vm);
|
|
22
23
|
url.searchParams.set('to', p.to);
|
|
23
|
-
|
|
24
|
+
if (p.vm === 'evm' && p.chainId !== undefined)
|
|
25
|
+
url.searchParams.set('chainId', String(p.chainId));
|
|
24
26
|
if (p.token)
|
|
25
27
|
url.searchParams.set('token', p.token);
|
|
26
28
|
url.searchParams.set('decimals', String(p.decimals));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"walletDeeplinks.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"walletDeeplinks.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SolanaSelectToken: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { formatUnits } from 'viem';
|
|
4
|
+
import { TOKEN_LOGO, symbolToColor } from '../../../constants/logos.js';
|
|
5
|
+
import { useSolanaWalletAssets } from '../../../solana/hooks/useSolanaWalletAssets.js';
|
|
6
|
+
import { ModalHeading } from '../../Common/Modal/styles.js';
|
|
7
|
+
import { routes } from '../../Openfort/types.js';
|
|
8
|
+
import { useOpenfort } from '../../Openfort/useOpenfort.js';
|
|
9
|
+
import { SelectTokenContent, EmptyState, TokenList, TokenButton, TokenLeftGroup, TokenInfo, TokenSymbol, TokenName, TokenBalance, TokenLogoArea, TokenLogoImg, TokenLogoFallback } from './styles.js';
|
|
10
|
+
|
|
11
|
+
const ZERO = BigInt(0);
|
|
12
|
+
function SolanaTokenLogo({ symbol }) {
|
|
13
|
+
var _a;
|
|
14
|
+
const [imgError, setImgError] = useState(false);
|
|
15
|
+
const url = (_a = TOKEN_LOGO[symbol.toUpperCase()]) !== null && _a !== void 0 ? _a : null;
|
|
16
|
+
return (jsx(TokenLogoArea, { children: url && !imgError ? (jsx(TokenLogoImg, { src: url, alt: symbol, onError: () => setImgError(true) })) : (jsx(TokenLogoFallback, { "$bg": symbolToColor(symbol), children: symbol.charAt(0).toUpperCase() })) }));
|
|
17
|
+
}
|
|
18
|
+
const SolanaSelectToken = () => {
|
|
19
|
+
const { setSendForm, setRoute, triggerResize } = useOpenfort();
|
|
20
|
+
const { data, isLoading } = useSolanaWalletAssets();
|
|
21
|
+
const tokens = (data !== null && data !== void 0 ? data : []).filter((t) => t.amount > ZERO);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!isLoading)
|
|
24
|
+
triggerResize();
|
|
25
|
+
}, [isLoading, triggerResize]);
|
|
26
|
+
const handleSelect = (token) => {
|
|
27
|
+
const asset = token.isNative
|
|
28
|
+
? {
|
|
29
|
+
type: 'native',
|
|
30
|
+
balance: token.amount,
|
|
31
|
+
metadata: { symbol: 'SOL', decimals: token.decimals, fiat: { value: 0, currency: 'USD' } },
|
|
32
|
+
}
|
|
33
|
+
: {
|
|
34
|
+
type: 'spl',
|
|
35
|
+
address: token.mint,
|
|
36
|
+
balance: token.amount,
|
|
37
|
+
metadata: { symbol: token.symbol, name: token.name, decimals: token.decimals },
|
|
38
|
+
};
|
|
39
|
+
setSendForm((prev) => ({ ...prev, asset, amount: '' }));
|
|
40
|
+
setRoute(routes.SOL_SEND);
|
|
41
|
+
};
|
|
42
|
+
return (jsxs(SelectTokenContent, { onBack: routes.SOL_SEND, children: [jsx(ModalHeading, { children: "Select asset" }), tokens.length === 0 ? (jsx(EmptyState, { children: isLoading ? 'Loading balances…' : 'No assets found' })) : (jsx(TokenList, { children: tokens.map((token) => {
|
|
43
|
+
const amount = Number(formatUnits(token.amount, token.decimals));
|
|
44
|
+
const balanceStr = `${amount.toLocaleString('en-US', { maximumFractionDigits: 4 })} ${token.symbol}`;
|
|
45
|
+
return (jsxs(TokenButton, { type: "button", onClick: () => handleSelect(token), children: [jsxs(TokenLeftGroup, { children: [jsx(SolanaTokenLogo, { symbol: token.symbol }), jsxs(TokenInfo, { style: { textAlign: 'left' }, children: [jsx(TokenSymbol, { children: token.name }), jsx(TokenName, { children: token.symbol })] })] }), jsx(TokenBalance, { children: balanceStr })] }, token.mint));
|
|
46
|
+
}) }))] }));
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export { SolanaSelectToken };
|
|
50
|
+
//# sourceMappingURL=SolanaSelectToken.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SolanaSelectToken.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { ChainTypeEnum } from '@openfort/openfort-js';
|
|
2
3
|
import { useState, useEffect } from 'react';
|
|
3
4
|
import { formatUnits } from 'viem';
|
|
4
5
|
import { useEthereumWalletAssets } from '../../../ethereum/hooks/useEthereumWalletAssets.js';
|
|
6
|
+
import { useOpenfortCore } from '../../../openfort/useOpenfort.js';
|
|
5
7
|
import { Arrow, ArrowChevron, TextLinkButton } from '../../Common/Button/styles.js';
|
|
6
8
|
import { ModalHeading } from '../../Common/Modal/styles.js';
|
|
7
9
|
import { routes } from '../../Openfort/types.js';
|
|
8
10
|
import { useOpenfort } from '../../Openfort/useOpenfort.js';
|
|
11
|
+
import { EVM_BUY_CURRENCIES } from '../Buy/evmCurrencies.js';
|
|
12
|
+
import { SOLANA_BUY_CURRENCIES } from '../Buy/solanaCurrencies.js';
|
|
9
13
|
import { getAssetSymbol, getAssetDecimals, formatBalanceWithSymbol } from '../Send/utils.js';
|
|
10
14
|
import { SelectTokenContent, EmptyState, TokenList, TokenButton, TokenInfo, TokenSymbol, TokenName, TokenBalance } from './styles.js';
|
|
11
15
|
|
|
@@ -22,9 +26,16 @@ const SelectToken = ({ isBuyFlow }) => {
|
|
|
22
26
|
useEffect(() => {
|
|
23
27
|
triggerResize();
|
|
24
28
|
}, [viewAllAssets]);
|
|
29
|
+
const { chainType } = useOpenfortCore();
|
|
25
30
|
const { data: walletAssets, isLoading: isBalancesLoading } = useEthereumWalletAssets();
|
|
26
|
-
//
|
|
27
|
-
|
|
31
|
+
// Buys pick from a fixed buyable-currency list (USDC first, then native) per
|
|
32
|
+
// chain family, so the picker always has options even for a fresh wallet with no
|
|
33
|
+
// indexed balances. The send flow reads the EVM wallet's actual assets.
|
|
34
|
+
const selectableTokens = isBuyFlow
|
|
35
|
+
? chainType === ChainTypeEnum.SVM
|
|
36
|
+
? SOLANA_BUY_CURRENCIES
|
|
37
|
+
: EVM_BUY_CURRENCIES
|
|
38
|
+
: walletAssets || [];
|
|
28
39
|
const handleSelect = (asset) => {
|
|
29
40
|
var _a;
|
|
30
41
|
// In send flow, don't allow selecting tokens with 0 balance
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
3
|
import { parseUnits, formatUnits } from 'viem';
|
|
4
|
-
import {
|
|
5
|
-
import { useAsyncData } from '../../../shared/hooks/useAsyncData.js';
|
|
6
|
-
import { useSolanaEmbeddedWallet } from '../../../solana/hooks/useSolanaEmbeddedWallet.js';
|
|
4
|
+
import { useSolanaWalletAssets } from '../../../solana/hooks/useSolanaWalletAssets.js';
|
|
7
5
|
import Button from '../../Common/Button/index.js';
|
|
6
|
+
import { Arrow, ArrowChevron } from '../../Common/Button/styles.js';
|
|
8
7
|
import Input from '../../Common/Input/index.js';
|
|
9
8
|
import { ModalHeading } from '../../Common/Modal/styles.js';
|
|
10
9
|
import { routes } from '../../Openfort/types.js';
|
|
11
10
|
import { useOpenfort } from '../../Openfort/useOpenfort.js';
|
|
12
11
|
import { PageContent } from '../../PageContent/index.js';
|
|
13
|
-
import { Form, Field, FieldLabel, AmountInputWrapper, MaxButton, HelperText, ErrorText } from './styles.js';
|
|
12
|
+
import { Form, Field, FieldLabel, TokenSelectorButton, TokenSelectorContent, TokenSelectorValue, TokenSelectorRight, AmountInputWrapper, MaxButton, HelperText, ErrorText } from './styles.js';
|
|
14
13
|
import { sanitizeForParsing, formatBalance, sanitizeAmountInput } from './utils.js';
|
|
15
14
|
|
|
16
15
|
const SOL_DECIMALS = 9;
|
|
@@ -18,39 +17,40 @@ const SOL_DECIMALS = 9;
|
|
|
18
17
|
function isLikelySolanaAddress(value) {
|
|
19
18
|
return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(value);
|
|
20
19
|
}
|
|
20
|
+
/** A native SOL asset with the canonical metadata (the default form asset has none). */
|
|
21
|
+
function solAsset(balance) {
|
|
22
|
+
return {
|
|
23
|
+
type: 'native',
|
|
24
|
+
balance,
|
|
25
|
+
metadata: { symbol: 'SOL', decimals: SOL_DECIMALS, fiat: { value: 0, currency: 'USD' } },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
21
28
|
const SolanaSend = () => {
|
|
22
|
-
var _a;
|
|
23
29
|
const { sendForm, setSendForm, setRoute } = useOpenfort();
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const { value } = await fetchSolanaBalance(address, rpcUrl, 'confirmed');
|
|
33
|
-
return value;
|
|
34
|
-
},
|
|
35
|
-
enabled: Boolean(address && rpcUrl),
|
|
36
|
-
});
|
|
37
|
-
const balanceLamports = (_a = balanceResult.data) !== null && _a !== void 0 ? _a : undefined;
|
|
30
|
+
const { data: assets } = useSolanaWalletAssets();
|
|
31
|
+
const asset = sendForm.asset;
|
|
32
|
+
const selected = asset.type === 'spl'
|
|
33
|
+
? { isSpl: true, mint: asset.address, decimals: asset.metadata.decimals, symbol: asset.metadata.symbol }
|
|
34
|
+
: { isSpl: false, mint: 'native', decimals: SOL_DECIMALS, symbol: 'SOL' };
|
|
35
|
+
// Live balance (base units) for the selected token, matched by mint.
|
|
36
|
+
const liveToken = assets === null || assets === void 0 ? void 0 : assets.find((t) => (selected.isSpl ? t.mint === selected.mint : t.isNative));
|
|
37
|
+
const balanceBase = liveToken === null || liveToken === void 0 ? void 0 : liveToken.amount;
|
|
38
38
|
const parsedAmount = useMemo(() => {
|
|
39
39
|
const raw = sanitizeForParsing(sendForm.amount);
|
|
40
40
|
if (!raw)
|
|
41
41
|
return null;
|
|
42
42
|
try {
|
|
43
|
-
return parseUnits(raw,
|
|
43
|
+
return parseUnits(raw, selected.decimals);
|
|
44
44
|
}
|
|
45
45
|
catch {
|
|
46
46
|
return null;
|
|
47
47
|
}
|
|
48
|
-
}, [sendForm.amount]);
|
|
48
|
+
}, [sendForm.amount, selected.decimals]);
|
|
49
49
|
const recipientValid = isLikelySolanaAddress(sendForm.recipient.trim());
|
|
50
|
-
const insufficientBalance = parsedAmount !== null &&
|
|
50
|
+
const insufficientBalance = parsedAmount !== null && balanceBase !== undefined ? parsedAmount > balanceBase : false;
|
|
51
51
|
const amountValid = parsedAmount !== null && parsedAmount > BigInt(0) && !insufficientBalance;
|
|
52
52
|
const canProceed = recipientValid && amountValid;
|
|
53
|
-
const availableLabel = formatBalance(
|
|
53
|
+
const availableLabel = formatBalance(balanceBase, selected.decimals);
|
|
54
54
|
const handleSubmit = (event) => {
|
|
55
55
|
event.preventDefault();
|
|
56
56
|
if (!canProceed)
|
|
@@ -58,15 +58,15 @@ const SolanaSend = () => {
|
|
|
58
58
|
const normalized = sanitizeForParsing(sendForm.amount);
|
|
59
59
|
if (!normalized)
|
|
60
60
|
return;
|
|
61
|
+
// Persist the selected token with its live balance so the confirmation reads it.
|
|
62
|
+
const nextAsset = asset.type === 'spl'
|
|
63
|
+
? { type: 'spl', address: asset.address, balance: balanceBase !== null && balanceBase !== void 0 ? balanceBase : asset.balance, metadata: asset.metadata }
|
|
64
|
+
: solAsset(balanceBase !== null && balanceBase !== void 0 ? balanceBase : BigInt(0));
|
|
61
65
|
setSendForm((prev) => ({
|
|
62
66
|
...prev,
|
|
63
67
|
recipient: prev.recipient.trim(),
|
|
64
68
|
amount: normalized,
|
|
65
|
-
asset:
|
|
66
|
-
type: 'native',
|
|
67
|
-
balance: balanceLamports !== null && balanceLamports !== void 0 ? balanceLamports : BigInt(0),
|
|
68
|
-
metadata: { symbol: 'SOL', decimals: SOL_DECIMALS, fiat: { value: 0, currency: 'USD' } },
|
|
69
|
-
},
|
|
69
|
+
asset: nextAsset,
|
|
70
70
|
}));
|
|
71
71
|
setRoute(routes.SOL_SEND_CONFIRMATION);
|
|
72
72
|
};
|
|
@@ -77,11 +77,12 @@ const SolanaSend = () => {
|
|
|
77
77
|
}
|
|
78
78
|
};
|
|
79
79
|
const handleMax = () => {
|
|
80
|
-
if (
|
|
80
|
+
if (balanceBase === undefined)
|
|
81
81
|
return;
|
|
82
|
-
setSendForm((prev) => ({ ...prev, amount: formatUnits(
|
|
82
|
+
setSendForm((prev) => ({ ...prev, amount: formatUnits(balanceBase, selected.decimals) }));
|
|
83
83
|
};
|
|
84
|
-
|
|
84
|
+
const handleOpenTokenSelector = () => setRoute(routes.SOL_SEND_TOKEN_SELECT);
|
|
85
|
+
return (jsxs(PageContent, { onBack: routes.SOL_CONNECTED, children: [jsx(ModalHeading, { children: "Send assets" }), jsxs(Form, { onSubmit: handleSubmit, children: [jsxs(Field, { children: [jsx(FieldLabel, { children: "Asset" }), jsxs(TokenSelectorButton, { type: "button", onClick: handleOpenTokenSelector, children: [jsx(TokenSelectorContent, { children: jsx(TokenSelectorValue, { "$primary": true, children: selected.symbol }) }), jsxs(TokenSelectorRight, { children: [jsx(TokenSelectorValue, { children: availableLabel === '--' ? '--' : `${availableLabel} ${selected.symbol}` }), jsx(Arrow, { width: "13", height: "12", viewBox: "0 0 13 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx(ArrowChevron, { stroke: "currentColor", d: "M7.51431 1.5L11.757 5.74264M7.5 10.4858L11.7426 6.24314", strokeWidth: "2", strokeLinecap: "round" }) })] })] })] }), jsxs(Field, { children: [jsx(FieldLabel, { children: "Amount" }), jsxs(AmountInputWrapper, { children: [jsx(Input, { placeholder: "0.00", value: sendForm.amount, onChange: handleAmountChange, inputMode: "decimal", autoComplete: "off", style: { paddingRight: '86px' } }), jsx(MaxButton, { type: "button", onClick: handleMax, disabled: balanceBase === undefined, children: "Max" })] }), jsxs(HelperText, { children: ["Available: ", availableLabel, " ", selected.symbol] }), sendForm.amount && parsedAmount === null && jsx(ErrorText, { children: "Enter a valid amount." }), insufficientBalance && jsxs(ErrorText, { children: ["Insufficient ", selected.symbol, " balance for this transfer."] })] }), jsxs(Field, { children: [jsx(FieldLabel, { children: "Recipient address" }), jsx(Input, { placeholder: "Solana address", value: sendForm.recipient, onChange: (e) => setSendForm((prev) => ({ ...prev, recipient: e.target.value })), autoComplete: "off" }), sendForm.recipient && !recipientValid && jsx(ErrorText, { children: "Enter a valid Solana address." })] }), jsx(Button, { variant: "primary", disabled: !canProceed, children: "Review transfer" })] })] }));
|
|
85
86
|
};
|
|
86
87
|
|
|
87
88
|
export { SolanaSend };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SolanaSend.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SolanaSend.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -44,10 +44,13 @@ const isSameToken = (a, b) => {
|
|
|
44
44
|
return false;
|
|
45
45
|
if (a.type === 'native')
|
|
46
46
|
return true;
|
|
47
|
-
// At this point, a.type === 'erc20' and b.type === 'erc20'
|
|
48
47
|
if (a.type === 'erc20' && b.type === 'erc20') {
|
|
49
48
|
return a.address.toLowerCase() === b.address.toLowerCase();
|
|
50
49
|
}
|
|
50
|
+
// SPL mints are base58 and case-sensitive — compare verbatim.
|
|
51
|
+
if (a.type === 'spl' && b.type === 'spl') {
|
|
52
|
+
return a.address === b.address;
|
|
53
|
+
}
|
|
51
54
|
return false;
|
|
52
55
|
};
|
|
53
56
|
const getAssetSymbol = (asset) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { ChainTypeEnum } from '@openfort/openfort-js';
|
|
3
3
|
import { useState, useEffect } from 'react';
|
|
4
|
+
import { parseUnits } from 'viem';
|
|
4
5
|
import { getExplorerUrl } from '../../../shared/utils/explorer.js';
|
|
5
6
|
import { useSolanaEmbeddedWallet } from '../../../solana/hooks/useSolanaEmbeddedWallet.js';
|
|
6
|
-
import { sendSolGasless, sendSol } from '../../../solana/transfer.js';
|
|
7
|
+
import { sendSplTokenGasless, sendSplToken, sendSolGasless, sendSol } from '../../../solana/transfer.js';
|
|
7
8
|
import 'detect-browser';
|
|
8
9
|
import { truncateSolanaAddress } from '../../../utils/format.js';
|
|
9
10
|
import Button from '../../Common/Button/index.js';
|
|
@@ -13,11 +14,12 @@ import { ModalHeading, ModalBody } from '../../Common/Modal/styles.js';
|
|
|
13
14
|
import { routes } from '../../Openfort/types.js';
|
|
14
15
|
import { useOpenfort } from '../../Openfort/useOpenfort.js';
|
|
15
16
|
import { PageContent } from '../../PageContent/index.js';
|
|
16
|
-
import { ButtonRow, SummaryList, SummaryItem, SummaryLabel, AmountValue, AddressValue,
|
|
17
|
+
import { ButtonRow, SummaryList, SummaryItem, SummaryLabel, AmountValue, AddressValue, FeesValue, ErrorContainer, ErrorTitle, ErrorMessage } from './styles.js';
|
|
17
18
|
|
|
19
|
+
const SOL_DECIMALS = 9;
|
|
18
20
|
const SolanaSendConfirmation = () => {
|
|
19
|
-
var _a;
|
|
20
|
-
const { sendForm, setRoute, publishableKey, triggerResize } = useOpenfort();
|
|
21
|
+
var _a, _b;
|
|
22
|
+
const { sendForm, setRoute, publishableKey, triggerResize, walletConfig } = useOpenfort();
|
|
21
23
|
const wallet = useSolanaEmbeddedWallet();
|
|
22
24
|
const address = wallet.status === 'connected' ? wallet.address : undefined;
|
|
23
25
|
const provider = wallet.status === 'connected' ? wallet.provider : undefined;
|
|
@@ -25,7 +27,11 @@ const SolanaSendConfirmation = () => {
|
|
|
25
27
|
const rpcUrl = wallet.rpcUrl;
|
|
26
28
|
const recipient = sendForm.recipient;
|
|
27
29
|
const amount = sendForm.amount;
|
|
28
|
-
const
|
|
30
|
+
const asset = sendForm.asset;
|
|
31
|
+
const symbol = asset.type === 'spl' ? asset.metadata.symbol : 'SOL';
|
|
32
|
+
const decimals = asset.type === 'spl' ? asset.metadata.decimals : SOL_DECIMALS;
|
|
33
|
+
// Fees are sponsored from config (the SVM counterpart of ethereumFeeSponsorshipId).
|
|
34
|
+
const isSponsored = Boolean((_b = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.solana) === null || _b === void 0 ? void 0 : _b.sponsorFees);
|
|
29
35
|
const [isLoading, setIsLoading] = useState(false);
|
|
30
36
|
const [signature, setSignature] = useState(null);
|
|
31
37
|
const [error, setError] = useState(null);
|
|
@@ -37,21 +43,59 @@ const SolanaSendConfirmation = () => {
|
|
|
37
43
|
const handleConfirm = async () => {
|
|
38
44
|
if (!address || !provider || isLoading)
|
|
39
45
|
return;
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
// The Send screen validates these before navigating here; re-guard in case
|
|
47
|
+
// this page is reached directly with an unvalidated form.
|
|
48
|
+
if (!recipient.trim()) {
|
|
49
|
+
setError('Enter a recipient address.');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const amountNum = Number(amount);
|
|
53
|
+
if (!Number.isFinite(amountNum) || amountNum <= 0) {
|
|
42
54
|
setError('Enter a valid amount.');
|
|
43
55
|
return;
|
|
44
56
|
}
|
|
45
|
-
if (!
|
|
57
|
+
if (!isSponsored && !rpcUrl) {
|
|
46
58
|
setError('No Solana RPC is configured for this network.');
|
|
47
59
|
return;
|
|
48
60
|
}
|
|
49
61
|
setIsLoading(true);
|
|
50
62
|
setError(null);
|
|
51
63
|
try {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
let sig;
|
|
65
|
+
if (asset.type === 'spl') {
|
|
66
|
+
const baseUnits = parseUnits(amount, decimals);
|
|
67
|
+
sig = isSponsored
|
|
68
|
+
? await sendSplTokenGasless({
|
|
69
|
+
from: address,
|
|
70
|
+
to: recipient,
|
|
71
|
+
mint: asset.address,
|
|
72
|
+
amount: baseUnits,
|
|
73
|
+
provider,
|
|
74
|
+
cluster,
|
|
75
|
+
publishableKey,
|
|
76
|
+
})
|
|
77
|
+
: await sendSplToken({
|
|
78
|
+
from: address,
|
|
79
|
+
to: recipient,
|
|
80
|
+
mint: asset.address,
|
|
81
|
+
amount: baseUnits,
|
|
82
|
+
decimals,
|
|
83
|
+
provider,
|
|
84
|
+
rpcUrl: rpcUrl !== null && rpcUrl !== void 0 ? rpcUrl : '',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
sig = isSponsored
|
|
89
|
+
? await sendSolGasless({
|
|
90
|
+
from: address,
|
|
91
|
+
to: recipient,
|
|
92
|
+
amountSol: amountNum,
|
|
93
|
+
provider,
|
|
94
|
+
cluster,
|
|
95
|
+
publishableKey,
|
|
96
|
+
})
|
|
97
|
+
: await sendSol({ from: address, to: recipient, amountSol: amountNum, provider, rpcUrl: rpcUrl !== null && rpcUrl !== void 0 ? rpcUrl : '' });
|
|
98
|
+
}
|
|
55
99
|
setSignature(sig);
|
|
56
100
|
}
|
|
57
101
|
catch (err) {
|
|
@@ -68,9 +112,9 @@ const SolanaSendConfirmation = () => {
|
|
|
68
112
|
window.open(getExplorerUrl(ChainTypeEnum.SVM, { txHash: signature, cluster }), '_blank', 'noopener,noreferrer');
|
|
69
113
|
};
|
|
70
114
|
if (signature) {
|
|
71
|
-
return (jsxs(PageContent, { children: [jsx(Loader, { isSuccess: true, header: "Transfer sent", description: `${amount}
|
|
115
|
+
return (jsxs(PageContent, { children: [jsx(Loader, { isSuccess: true, header: "Transfer sent", description: `${amount} ${symbol} sent successfully` }), jsxs(ButtonRow, { children: [jsx(Button, { variant: "primary", onClick: handleViewExplorer, children: "View on Explorer" }), jsx(Button, { variant: "secondary", onClick: handleFinish, children: "Back to profile" })] })] }));
|
|
72
116
|
}
|
|
73
|
-
return (jsxs(PageContent, { onBack: routes.SOL_SEND, children: [jsx(ModalHeading, { children: "Confirm transfer" }), jsx(ModalBody, { children: "Review the transaction details before sending." }), jsxs(SummaryList, { children: [jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "Sending" }), jsxs(AmountValue, { children: [amount || '0', "
|
|
117
|
+
return (jsxs(PageContent, { onBack: routes.SOL_SEND, children: [jsx(ModalHeading, { children: "Confirm transfer" }), jsx(ModalBody, { children: "Review the transaction details before sending." }), jsxs(SummaryList, { children: [jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "Sending" }), jsxs(AmountValue, { children: [amount || '0', " ", symbol] })] }), jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "From" }), jsx(AddressValue, { children: address ? (jsx(CopyText, { size: "1rem", value: address, children: truncateSolanaAddress(address) })) : ('--') })] }), jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "To" }), jsx(AddressValue, { children: recipient ? (jsx(CopyText, { size: "1rem", value: recipient, children: truncateSolanaAddress(recipient) })) : ('--') })] }), isSponsored && (jsxs(SummaryItem, { children: [jsx(SummaryLabel, { children: "Network fee" }), jsx(FeesValue, { "$completed": true, children: "Sponsored" })] }))] }), error && (jsxs(ErrorContainer, { children: [jsx(ErrorTitle, { children: "Transaction failed" }), jsx(ErrorMessage, { children: error })] })), jsxs(ButtonRow, { children: [jsx(Button, { variant: "primary", onClick: handleConfirm, disabled: !address || isLoading, waiting: isLoading, children: isLoading ? 'Confirming...' : 'Confirm' }), jsx(Button, { variant: "secondary", onClick: () => setRoute(routes.SOL_SEND), disabled: isLoading, children: "Cancel" })] })] }));
|
|
74
118
|
};
|
|
75
119
|
|
|
76
120
|
export { SolanaSendConfirmation };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SolanaSendConfirmation.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SolanaSendConfirmation.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -16,8 +16,3 @@ export declare const ErrorContainer: import("styled-components").StyledComponent
|
|
|
16
16
|
export declare const ErrorTitle: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
17
17
|
export declare const ErrorMessage: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
18
18
|
export declare const ErrorAction: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
19
|
-
export declare const GaslessRow: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
20
|
-
/** A minimal theme-aware switch for the Solana "sponsor fee" toggle. */
|
|
21
|
-
export declare const GaslessToggle: import("styled-components").StyledComponent<"button", any, {
|
|
22
|
-
$on?: boolean;
|
|
23
|
-
}, never>;
|
|
@@ -124,44 +124,6 @@ const ErrorAction = styled.div `
|
|
|
124
124
|
color: var(--ck-body-color-muted);
|
|
125
125
|
line-height: 1.4;
|
|
126
126
|
`;
|
|
127
|
-
const GaslessRow = styled.div `
|
|
128
|
-
display: flex;
|
|
129
|
-
align-items: center;
|
|
130
|
-
justify-content: space-between;
|
|
131
|
-
gap: 12px;
|
|
132
|
-
margin: 4px 0 8px;
|
|
133
|
-
text-align: left;
|
|
134
|
-
`;
|
|
135
|
-
/** A minimal theme-aware switch for the Solana "sponsor fee" toggle. */
|
|
136
|
-
const GaslessToggle = styled.button `
|
|
137
|
-
position: relative;
|
|
138
|
-
flex-shrink: 0;
|
|
139
|
-
width: 40px;
|
|
140
|
-
height: 24px;
|
|
141
|
-
border-radius: 999px;
|
|
142
|
-
border: 1px solid var(--ck-body-divider);
|
|
143
|
-
background: ${(props) => (props.$on ? 'var(--ck-body-color-valid, #22c55e)' : 'var(--ck-body-background-secondary)')};
|
|
144
|
-
cursor: pointer;
|
|
145
|
-
transition: background 150ms ease;
|
|
146
|
-
padding: 0;
|
|
147
|
-
|
|
148
|
-
&:disabled {
|
|
149
|
-
opacity: 0.5;
|
|
150
|
-
cursor: not-allowed;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
> span {
|
|
154
|
-
position: absolute;
|
|
155
|
-
top: 50%;
|
|
156
|
-
left: ${(props) => (props.$on ? '18px' : '2px')};
|
|
157
|
-
transform: translateY(-50%);
|
|
158
|
-
width: 18px;
|
|
159
|
-
height: 18px;
|
|
160
|
-
border-radius: 50%;
|
|
161
|
-
background: #fff;
|
|
162
|
-
transition: left 150ms ease;
|
|
163
|
-
}
|
|
164
|
-
`;
|
|
165
127
|
|
|
166
|
-
export { AddressValue, AmountValue, ButtonRow, CheckIconWrapper, ErrorAction, ErrorContainer, ErrorMessage, ErrorTitle, FeesValue,
|
|
128
|
+
export { AddressValue, AmountValue, ButtonRow, CheckIconWrapper, ErrorAction, ErrorContainer, ErrorMessage, ErrorTitle, FeesValue, InfoIconWrapper, StatusMessage, SummaryItem, SummaryLabel, SummaryList };
|
|
167
129
|
//# sourceMappingURL=styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"styles.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|