@ab-org/predicate-market-sdk 0.0.2 → 0.1.1
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/README.md +12 -2
- package/dist/constants/chains.d.ts +2 -22
- package/dist/constants/chains.js +3 -23
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/modules/api.d.ts +13 -8
- package/dist/modules/api.js +6 -4
- package/dist/modules/balanceQuery.d.ts +11 -4
- package/dist/modules/balanceQuery.js +12 -10
- package/dist/modules/deposit.js +2 -1
- package/dist/modules/marketData.d.ts +1 -1
- package/dist/modules/marketData.js +27 -33
- package/dist/modules/withdraw.js +2 -1
- package/dist/modules/withdrawDirect.d.ts +14 -0
- package/dist/modules/withdrawDirect.js +33 -0
- package/dist/modules/withdrawExecutor.d.ts +15 -6
- package/dist/modules/withdrawExecutor.js +22 -20
- package/dist/ui/DepositModal.d.ts +1 -1
- package/dist/ui/DepositModal.js +46 -18
- package/dist/ui/WithdrawModal.d.ts +12 -2
- package/dist/ui/WithdrawModal.js +101 -55
- package/dist/ui/components/DepositDetailsPanel.d.ts +1 -1
- package/dist/ui/components/DepositDetailsPanel.js +31 -5
- package/dist/ui/signInTypes.d.ts +3 -0
- package/dist/ui/useSignInModalController.js +1 -36
- package/dist/utils/env.js +2 -0
- package/dist/walletUtils.d.ts +1 -1
- package/dist/walletUtils.js +1 -1
- package/package.json +3 -2
package/dist/ui/DepositModal.js
CHANGED
|
@@ -8,7 +8,8 @@ import { DepositDetailsPanel } from "./components/DepositDetailsPanel.js";
|
|
|
8
8
|
import { LoginRequiredOverlay } from "./components/LoginRequiredOverlay.js";
|
|
9
9
|
import { useSession } from "./hooks/useSession.js";
|
|
10
10
|
import { colors, fonts, radii } from "./theme.js";
|
|
11
|
-
import { getChains, quote, } from "../modules/api.js";
|
|
11
|
+
import { getChains, quote, registerPlatform, } from "../modules/api.js";
|
|
12
|
+
import { getEnv } from "../utils/env";
|
|
12
13
|
/** 校验是否为合法的充值地址(传入值):非空且长度满足常见链地址格式 */
|
|
13
14
|
function isValidDepositAddress(v) {
|
|
14
15
|
return typeof v === "string" && v.trim().length >= 20;
|
|
@@ -43,8 +44,6 @@ const DefaultCryptoIcons = () => {
|
|
|
43
44
|
}, children: t.label }, i))) }));
|
|
44
45
|
};
|
|
45
46
|
/* ─── Helpers: derive options from getChains ─── */
|
|
46
|
-
/** Deposit 时不可选 USD1(充值是转入 USD1,源代币为 USDT/USDC 等) */
|
|
47
|
-
const DEPOSIT_EXCLUDED_TOKEN = "USD1";
|
|
48
47
|
function chainsToTokenOptions(chains) {
|
|
49
48
|
const bySymbol = new Map();
|
|
50
49
|
for (const c of chains) {
|
|
@@ -54,7 +53,6 @@ function chainsToTokenOptions(chains) {
|
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
return Array.from(bySymbol.entries())
|
|
57
|
-
.filter(([id]) => id !== DEPOSIT_EXCLUDED_TOKEN)
|
|
58
56
|
.map(([id, { symbol }]) => ({
|
|
59
57
|
id,
|
|
60
58
|
label: symbol,
|
|
@@ -88,6 +86,8 @@ function getTokenAddressForChain(chains, chainId, tokenSymbol) {
|
|
|
88
86
|
const chain = chains.find((c) => c.chain_id === chainId);
|
|
89
87
|
return chain?.tokens.find((t) => t.symbol === tokenSymbol)?.address;
|
|
90
88
|
}
|
|
89
|
+
/* ─── Main Component ─────────────────────────── */
|
|
90
|
+
const FUNDING_TOKEN_SYMBOL = getEnv("FUNDING_TOKEN_SYMBOL");
|
|
91
91
|
export const DepositModal = ({ token, chain, tokenOptions: tokenOptionsProp, chainOptions: chainOptionsProp, depositAddress, minimumDeposit, qrCenterIcon, cryptoIcons, depositAmount, onShowToast, txHash, explorerTxUrl, onTokenSelect, onChainSelect, onCopyAddress, onBuyCrypto, onSignIn, onBack, onClose, }) => {
|
|
92
92
|
const session = useSession();
|
|
93
93
|
const [view, setView] = useState("entry");
|
|
@@ -97,10 +97,12 @@ export const DepositModal = ({ token, chain, tokenOptions: tokenOptionsProp, cha
|
|
|
97
97
|
const [loadingChains, setLoadingChains] = useState(false);
|
|
98
98
|
const [loadingQuote, setLoadingQuote] = useState(false);
|
|
99
99
|
const [quoteRefreshKey, setQuoteRefreshKey] = useState(0);
|
|
100
|
+
const [internalDepositAddress, setInternalDepositAddress] = useState(undefined);
|
|
101
|
+
const lastEmittedAddressRef = useRef(undefined);
|
|
102
|
+
const lastEmittedChainRef = useRef(undefined);
|
|
100
103
|
const tokenOptions = useMemo(() => {
|
|
101
|
-
const excludeUsd1 = (opts) => opts.filter((o) => o.id !== DEPOSIT_EXCLUDED_TOKEN && o.label !== DEPOSIT_EXCLUDED_TOKEN);
|
|
102
104
|
if (tokenOptionsProp?.length)
|
|
103
|
-
return
|
|
105
|
+
return tokenOptionsProp;
|
|
104
106
|
if (!apiChains?.length)
|
|
105
107
|
return undefined;
|
|
106
108
|
return chainsToTokenOptions(apiChains);
|
|
@@ -112,12 +114,6 @@ export const DepositModal = ({ token, chain, tokenOptions: tokenOptionsProp, cha
|
|
|
112
114
|
return undefined;
|
|
113
115
|
return chainsToChainOptionsForToken(apiChains, token);
|
|
114
116
|
}, [chainOptionsProp, apiChains, token]);
|
|
115
|
-
// 当前选中的是 USD1 时自动切到第一个可选 token(deposit 不允许选 USD1)
|
|
116
|
-
useEffect(() => {
|
|
117
|
-
if (token !== DEPOSIT_EXCLUDED_TOKEN || !tokenOptions?.length || !onTokenSelect)
|
|
118
|
-
return;
|
|
119
|
-
onTokenSelect(tokenOptions[0].id);
|
|
120
|
-
}, [token, tokenOptions, onTokenSelect]);
|
|
121
117
|
// 仅有一个 chain 选项时默认选中
|
|
122
118
|
useEffect(() => {
|
|
123
119
|
if (chainOptions?.length !== 1 || !onChainSelect)
|
|
@@ -135,6 +131,25 @@ export const DepositModal = ({ token, chain, tokenOptions: tokenOptionsProp, cha
|
|
|
135
131
|
.then((res) => setApiChains(res?.chains ?? {}))
|
|
136
132
|
.finally(() => setLoadingChains(false));
|
|
137
133
|
}, [view]);
|
|
134
|
+
// Fetch depositAddress internally when user is signed in and a chain has been selected.
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
if (view !== "transfer")
|
|
137
|
+
return;
|
|
138
|
+
if (!session?.address || !chain)
|
|
139
|
+
return;
|
|
140
|
+
registerPlatform({
|
|
141
|
+
platform_contract_address: session.address,
|
|
142
|
+
chain_id: chain,
|
|
143
|
+
})
|
|
144
|
+
.then((res) => {
|
|
145
|
+
if (res?.deposit_address) {
|
|
146
|
+
setInternalDepositAddress(res.deposit_address);
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
.catch(() => {
|
|
150
|
+
// silent failure; UI will keep placeholder if any
|
|
151
|
+
});
|
|
152
|
+
}, [view, chain, session?.address]);
|
|
138
153
|
useEffect(() => {
|
|
139
154
|
if (!apiChains?.length || !token || !chain) {
|
|
140
155
|
setApiQuote(null);
|
|
@@ -166,12 +181,25 @@ export const DepositModal = ({ token, chain, tokenOptions: tokenOptionsProp, cha
|
|
|
166
181
|
rate: "1",
|
|
167
182
|
chain_id: Number(chain) || 56,
|
|
168
183
|
deposit_address: "0x" + "0".repeat(39) + "1",
|
|
169
|
-
|
|
184
|
+
dst_token_amount: depositAmount ?? "0",
|
|
170
185
|
expires_at: new Date(Date.now() + 60000).toISOString(),
|
|
171
186
|
});
|
|
172
187
|
})
|
|
173
188
|
.finally(() => setLoadingQuote(false));
|
|
174
189
|
}, [apiChains, token, chain, depositAmount, quoteRefreshKey, onShowToast]);
|
|
190
|
+
// Emit resolved address when external prop is provided/changes
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
if (!chain)
|
|
193
|
+
return;
|
|
194
|
+
if (!depositAddress)
|
|
195
|
+
return;
|
|
196
|
+
if (lastEmittedAddressRef.current === depositAddress &&
|
|
197
|
+
lastEmittedChainRef.current === chain) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
lastEmittedAddressRef.current = depositAddress;
|
|
201
|
+
lastEmittedChainRef.current = chain;
|
|
202
|
+
}, [depositAddress, chain]);
|
|
175
203
|
const handleQuoteExpired = useCallback(() => {
|
|
176
204
|
setQuoteRefreshKey((k) => k + 1);
|
|
177
205
|
}, []);
|
|
@@ -187,8 +215,8 @@ export const DepositModal = ({ token, chain, tokenOptions: tokenOptionsProp, cha
|
|
|
187
215
|
setView("entry");
|
|
188
216
|
onBack?.();
|
|
189
217
|
};
|
|
190
|
-
const handleCopyAddress = useCallback(() => {
|
|
191
|
-
onCopyAddress?.();
|
|
218
|
+
const handleCopyAddress = useCallback((address) => {
|
|
219
|
+
onCopyAddress?.(address);
|
|
192
220
|
onShowToast?.("Address copied");
|
|
193
221
|
setCopySuccessMessage("Address copied");
|
|
194
222
|
}, [onCopyAddress, onShowToast]);
|
|
@@ -211,7 +239,7 @@ export const DepositModal = ({ token, chain, tokenOptions: tokenOptionsProp, cha
|
|
|
211
239
|
fontWeight: 500,
|
|
212
240
|
boxShadow: "0 4px 12px rgba(0,0,0,.25)",
|
|
213
241
|
zIndex: 10,
|
|
214
|
-
}, children: copySuccessMessage })), view === "entry" ? (_jsx(EntryView, { cryptoIcons: cryptoIcons, onTransferCrypto: () => setView("transfer"), onBuyCrypto: onBuyCrypto })) : (_jsx(TransferView, { token: token, chain: chain, tokenOptions: tokenOptions, chainOptions: chainOptions, depositAddress: depositAddress, minimumDeposit: minimumDeposit, qrCenterIcon: qrCenterIcon, quote: apiQuote, quoteLoading: loadingQuote, txHash: txHash, chainIdForExplorer: chain, explorerTxUrl: explorerTxUrl, loadingChains: loadingChains, onTokenSelect: onTokenSelect, onChainSelect: onChainSelect, onCopyAddress: handleCopyAddress, onQuoteExpired: handleQuoteExpired, onRefreshQuote: () => {
|
|
242
|
+
}, children: copySuccessMessage })), view === "entry" ? (_jsx(EntryView, { cryptoIcons: cryptoIcons, onTransferCrypto: () => setView("transfer"), onBuyCrypto: onBuyCrypto })) : (_jsx(TransferView, { token: token, chain: chain, tokenOptions: tokenOptions, chainOptions: chainOptions, depositAddress: depositAddress ?? internalDepositAddress, minimumDeposit: minimumDeposit, qrCenterIcon: qrCenterIcon, quote: apiQuote, quoteLoading: loadingQuote, txHash: txHash, chainIdForExplorer: chain, explorerTxUrl: explorerTxUrl, loadingChains: loadingChains, onTokenSelect: onTokenSelect, onChainSelect: onChainSelect, onCopyAddress: handleCopyAddress, onQuoteExpired: handleQuoteExpired, onRefreshQuote: () => {
|
|
215
243
|
if (!apiChains?.length || !token || !chain)
|
|
216
244
|
return;
|
|
217
245
|
const tokenAddress = getTokenAddressForChain(apiChains, chain, token);
|
|
@@ -227,7 +255,7 @@ export const DepositModal = ({ token, chain, tokenOptions: tokenOptionsProp, cha
|
|
|
227
255
|
rate: "1",
|
|
228
256
|
chain_id: Number(chain) || 56,
|
|
229
257
|
deposit_address: "0x" + "0".repeat(39) + "1",
|
|
230
|
-
|
|
258
|
+
dst_token_amount: depositAmount ?? "0",
|
|
231
259
|
expires_at: new Date(Date.now() + 60000).toISOString(),
|
|
232
260
|
});
|
|
233
261
|
})
|
|
@@ -302,7 +330,7 @@ const TransferView = ({ token, chain, tokenOptions, chainOptions, depositAddress
|
|
|
302
330
|
display: "flex",
|
|
303
331
|
flexDirection: "column",
|
|
304
332
|
gap: 8,
|
|
305
|
-
}, children: quoteLoading ? (_jsx("span", { style: { fontSize: 13, color: colors.textSecondary }, children: "Loading\u2026" })) : (_jsxs(_Fragment, { children: [_jsxs("span", { style: { fontSize: 13, color: colors.textSecondary }, children: ["1 ", quoteData.token_symbol, " = ", quoteData.rate, "
|
|
333
|
+
}, children: quoteLoading ? (_jsx("span", { style: { fontSize: 13, color: colors.textSecondary }, children: "Loading\u2026" })) : (_jsxs(_Fragment, { children: [_jsxs("span", { style: { fontSize: 13, color: colors.textSecondary }, children: ["1 ", quoteData.token_symbol, " = ", quoteData.rate, " ", FUNDING_TOKEN_SYMBOL] }), quoteData.expires_at && (_jsx(Countdown, { expiresAt: quoteData.expires_at, isExpired: quoteExpired, onExpired: onQuoteExpired })), quoteExpired && (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [_jsx("span", { style: { fontSize: 13, color: "#f59e0b" }, children: "Quote expired, please refresh" }), onRefreshQuote && (_jsx("button", { type: "button", onClick: onRefreshQuote, style: {
|
|
306
334
|
padding: "4px 12px",
|
|
307
335
|
fontSize: 12,
|
|
308
336
|
borderRadius: radii.pill,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ChangeEventHandler } from "react";
|
|
2
2
|
import { type SelectOption } from "./components/DropdownField.js";
|
|
3
|
+
import { type WithdrawOrderResponseData } from "../modules/api.js";
|
|
3
4
|
export type WithdrawUiStatus = "idle" | "pending" | "success" | "manual_review";
|
|
4
5
|
export interface WithdrawModalProps {
|
|
5
6
|
address?: string;
|
|
@@ -18,6 +19,14 @@ export interface WithdrawModalProps {
|
|
|
18
19
|
useMerchantApi?: boolean;
|
|
19
20
|
/** 创建订单后传入,用于轮询提现订单状态 */
|
|
20
21
|
orderId?: string;
|
|
22
|
+
/** 提现模式:direct 直接提现,cross_chain 跨链提现 */
|
|
23
|
+
withdrawMode?: "direct" | "cross_chain";
|
|
24
|
+
/**
|
|
25
|
+
* 直接提现模式(无 orderId)下的结果数据;
|
|
26
|
+
* 将用来构造一个与 getWithdrawOrder 返回值兼容的对象,从而复用“有 orderId”时的全部交互与展示。
|
|
27
|
+
* 最少建议提供:status、dst_token_amount、target_chain_id、target_address(必要时包含 dst_tx_hash / out_tx_hash、fee)。
|
|
28
|
+
*/
|
|
29
|
+
withdrawDirectResult?: Partial<WithdrawOrderResponseData>;
|
|
21
30
|
/** 成功页 Fee 展示:优先用订单接口返回的 fee,若后端未返回则用此值(如询价时的 fee),均无则显示 "—" */
|
|
22
31
|
feeDisplay?: string;
|
|
23
32
|
/** 广播后的 funding tx 所在链 id,与 txHash 一起用于展示「查看交易」链接 */
|
|
@@ -30,11 +39,12 @@ export interface WithdrawModalProps {
|
|
|
30
39
|
onChainSelect?: (id: string) => void;
|
|
31
40
|
onAmountChange?: ChangeEventHandler<HTMLInputElement>;
|
|
32
41
|
onMaxClick?: () => void;
|
|
33
|
-
/** 提交时传入当前表单值(收款地址、金额、所选 token
|
|
42
|
+
/** 提交时传入当前表单值(收款地址、金额、所选 token、链上合约地址、所选 chain),由调用方执行提现 */
|
|
34
43
|
onSubmit?: (payload: {
|
|
35
44
|
toAddress: string;
|
|
36
45
|
amount: string;
|
|
37
46
|
token: string;
|
|
47
|
+
tokenAddress: string;
|
|
38
48
|
chain: string;
|
|
39
49
|
}) => void;
|
|
40
50
|
/** 提现订单状态变为 completed 时调用,用于调用方刷新余额等 */
|
|
@@ -44,4 +54,4 @@ export interface WithdrawModalProps {
|
|
|
44
54
|
onSignIn?: () => void;
|
|
45
55
|
onClose?: () => void;
|
|
46
56
|
}
|
|
47
|
-
export declare const WithdrawModal: ({ address, token, tokenSymbol, chain, amount, balance, status, receiveAmount: receiveAmountProp, txHash, tokenOptions: tokenOptionsProp, chainOptions: chainOptionsProp, useMerchantApi, orderId, feeDisplay, fundingChainId,
|
|
57
|
+
export declare const WithdrawModal: ({ address, token, tokenSymbol, chain, amount, balance, status, receiveAmount: receiveAmountProp, txHash, tokenOptions: tokenOptionsProp, chainOptions: chainOptionsProp, useMerchantApi, orderId, withdrawMode, withdrawDirectResult, feeDisplay, fundingChainId, onShowToast, onAddressChange, onTokenSelect, onChainSelect, onAmountChange, onMaxClick, onSubmit, onWithdrawCompleted, onStartAnotherWithdrawal, onSignIn, onClose, }: WithdrawModalProps) => import("react/jsx-runtime.js").JSX.Element;
|
package/dist/ui/WithdrawModal.js
CHANGED
|
@@ -8,11 +8,13 @@ import { LoginRequiredOverlay } from "./components/LoginRequiredOverlay.js";
|
|
|
8
8
|
import { useSession } from "./hooks/useSession.js";
|
|
9
9
|
import { colors, fonts, radii } from "./theme.js";
|
|
10
10
|
import { getChains, quote, getWithdrawOrder, } from "../modules/api.js";
|
|
11
|
+
import { getEnv } from "../utils/env";
|
|
11
12
|
import { getExplorerUrl } from "../utils/explorer.js";
|
|
12
13
|
import { SuccessIcon } from "./components/Success";
|
|
13
14
|
function CopyIcon() {
|
|
14
15
|
return (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": true, children: [_jsx("rect", { x: "5", y: "5", width: "9", height: "9", rx: "1", stroke: "currentColor", strokeWidth: "1.2", fill: "none" }), _jsx("path", { d: "M3 11V3a1 1 0 0 1 1-1h8", stroke: "currentColor", strokeWidth: "1.2", fill: "none" })] }));
|
|
15
16
|
}
|
|
17
|
+
const FUNDING_TOKEN_SYMBOL = getEnv("FUNDING_TOKEN_SYMBOL");
|
|
16
18
|
function chainsToTokenOptions(chains) {
|
|
17
19
|
const bySymbol = new Map();
|
|
18
20
|
for (const c of chains) {
|
|
@@ -36,7 +38,7 @@ function getTokenAddressForChain(chains, chainId, tokenSymbol) {
|
|
|
36
38
|
const chain = chains.find((c) => c.chain_id === chainId);
|
|
37
39
|
return chain?.tokens.find((t) => t.symbol === tokenSymbol)?.address;
|
|
38
40
|
}
|
|
39
|
-
/** 从 balance 字符串解析出数值部分(如 "123.46
|
|
41
|
+
/** 从 balance 字符串解析出数值部分(如 "123.46 xxx" → 123.46) */
|
|
40
42
|
function parseBalanceNumber(balance) {
|
|
41
43
|
const match = balance.trim().match(/^(\d*\.?\d*)/);
|
|
42
44
|
if (!match)
|
|
@@ -44,7 +46,7 @@ function parseBalanceNumber(balance) {
|
|
|
44
46
|
const n = Number(match[1]);
|
|
45
47
|
return Number.isNaN(n) ? null : n;
|
|
46
48
|
}
|
|
47
|
-
/** 将 balance 字符串格式化为小数点后 2 位(如 "123.456789012
|
|
49
|
+
/** 将 balance 字符串格式化为小数点后 2 位(如 "123.456789012 xxx" → "123.46 xxx") */
|
|
48
50
|
function formatBalanceTo2Decimals(balance) {
|
|
49
51
|
const match = balance.trim().match(/^(\d*\.?\d*)(.*)$/);
|
|
50
52
|
if (!match)
|
|
@@ -57,7 +59,6 @@ function formatBalanceTo2Decimals(balance) {
|
|
|
57
59
|
const formatted = n.toFixed(2);
|
|
58
60
|
return formatted + suffix;
|
|
59
61
|
}
|
|
60
|
-
const WEI_PER_ETHER = 1e18;
|
|
61
62
|
/** Wei (string) to ether display string; keeps up to 6 decimal places, strips trailing zeros */
|
|
62
63
|
function weiToEtherDisplay(wei) {
|
|
63
64
|
const s = (wei || "0").trim().replace(/^0+/, "") || "0";
|
|
@@ -74,7 +75,7 @@ function weiToEtherDisplay(wei) {
|
|
|
74
75
|
return fixed;
|
|
75
76
|
}
|
|
76
77
|
const POLL_INTERVAL_MS = 4000;
|
|
77
|
-
export const WithdrawModal = ({ address = "", token, tokenSymbol
|
|
78
|
+
export const WithdrawModal = ({ address = "", token, tokenSymbol, chain, amount = "", balance, status = "idle", receiveAmount: receiveAmountProp, txHash, tokenOptions: tokenOptionsProp, chainOptions: chainOptionsProp, useMerchantApi = false, orderId, withdrawMode, withdrawDirectResult, feeDisplay, fundingChainId, onShowToast, onAddressChange, onTokenSelect, onChainSelect, onAmountChange, onMaxClick, onSubmit, onWithdrawCompleted, onStartAnotherWithdrawal, onSignIn, onClose, }) => {
|
|
78
79
|
const session = useSession();
|
|
79
80
|
const addressInputRef = useRef(null);
|
|
80
81
|
const [addressInputFocused, setAddressInputFocused] = useState(false);
|
|
@@ -100,7 +101,7 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
100
101
|
: undefined;
|
|
101
102
|
if (!raw?.length)
|
|
102
103
|
return undefined;
|
|
103
|
-
return raw
|
|
104
|
+
return raw;
|
|
104
105
|
}, [tokenOptionsProp, apiChains]);
|
|
105
106
|
const chainOptions = useMemo(() => {
|
|
106
107
|
if (chainOptionsProp?.length)
|
|
@@ -109,7 +110,19 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
109
110
|
return undefined;
|
|
110
111
|
return chainsToChainOptionsForToken(apiChains, token);
|
|
111
112
|
}, [chainOptionsProp, apiChains, token]);
|
|
112
|
-
|
|
113
|
+
/** 当前选中的 token + chain 在 getChains 数据中的合约地址(与询价 / quote 使用同一解析方式) */
|
|
114
|
+
const resolvedTokenAddress = useMemo(() => {
|
|
115
|
+
if (!apiChains?.length || !token || !chain)
|
|
116
|
+
return undefined;
|
|
117
|
+
return getTokenAddressForChain(apiChains, chain, token);
|
|
118
|
+
}, [apiChains, token, chain]);
|
|
119
|
+
// direct 模式的内部激活标记(便于“Start another withdrawal”时重置为表单态)
|
|
120
|
+
const [directActive, setDirectActive] = useState(false);
|
|
121
|
+
// 当外部把 withdrawMode 设为 direct 且提供 withdrawDirectResut 时,进入“追踪提现”态
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
setDirectActive(withdrawMode === "direct" && Boolean(withdrawDirectResult));
|
|
124
|
+
}, [withdrawMode, withdrawDirectResult]);
|
|
125
|
+
const trackingWithdraw = useMemo(() => Boolean(orderId) || directActive, [orderId, directActive]);
|
|
113
126
|
// Default focus on recipient address when form is visible; white border while focused, revert on blur
|
|
114
127
|
useEffect(() => {
|
|
115
128
|
if (trackingWithdraw)
|
|
@@ -126,10 +139,10 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
126
139
|
return;
|
|
127
140
|
setLoadingChains(true);
|
|
128
141
|
getChains()
|
|
129
|
-
.then((res) => setApiChains(res?.chains ??
|
|
142
|
+
.then((res) => setApiChains(res?.chains ?? []))
|
|
130
143
|
.finally(() => setLoadingChains(false));
|
|
131
144
|
}, [shouldLoadChains]);
|
|
132
|
-
// 选中 token + chain 后即询价;未填 amount 时用 1
|
|
145
|
+
// 选中 token + chain 后即询价;未填 amount 时用 1 xxx 获取 rate
|
|
133
146
|
useEffect(() => {
|
|
134
147
|
if (!apiChains?.length || !token || !chain) {
|
|
135
148
|
setApiQuote(null);
|
|
@@ -147,7 +160,7 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
147
160
|
direction: "withdraw",
|
|
148
161
|
chain_id: chain,
|
|
149
162
|
token_address: tokenAddress,
|
|
150
|
-
|
|
163
|
+
dst_token_amount: amountWei,
|
|
151
164
|
})
|
|
152
165
|
.then((q) => setApiQuote(q ?? null))
|
|
153
166
|
.catch(() => {
|
|
@@ -183,41 +196,73 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
183
196
|
order_id: orderId ?? "",
|
|
184
197
|
status: "pending",
|
|
185
198
|
chain_id: "56",
|
|
186
|
-
|
|
199
|
+
dst_token_amount: "0",
|
|
187
200
|
target_chain_id: chain ?? "1",
|
|
188
201
|
target_address: address ?? "0x",
|
|
189
202
|
created_at: new Date().toISOString(),
|
|
190
203
|
updated_at: new Date().toISOString(),
|
|
191
204
|
}), [orderId, chain, address]);
|
|
192
205
|
useEffect(() => {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
206
|
+
// 1) 有 orderId:按原逻辑轮询
|
|
207
|
+
if (orderId) {
|
|
208
|
+
const t = setInterval(() => {
|
|
209
|
+
getWithdrawOrder(orderId)
|
|
210
|
+
.then((order) => {
|
|
211
|
+
setWithdrawOrder(order);
|
|
212
|
+
if (order.status === "completed" && onShowToast) {
|
|
213
|
+
onShowToast("Withdrawal completed");
|
|
214
|
+
}
|
|
215
|
+
})
|
|
216
|
+
.catch(() => setWithdrawOrder(mockWithdrawOrderState));
|
|
217
|
+
}, POLL_INTERVAL_MS);
|
|
198
218
|
getWithdrawOrder(orderId)
|
|
199
|
-
.then(
|
|
200
|
-
setWithdrawOrder(order);
|
|
201
|
-
if (order.status === "completed" && onShowToast) {
|
|
202
|
-
onShowToast("Withdrawal completed");
|
|
203
|
-
}
|
|
204
|
-
})
|
|
219
|
+
.then(setWithdrawOrder)
|
|
205
220
|
.catch(() => setWithdrawOrder(mockWithdrawOrderState));
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
221
|
+
return () => clearInterval(t);
|
|
222
|
+
}
|
|
223
|
+
// 2) 无 orderId 且 direct 模式:用传入的结果构造一个“伪订单”,以复用已提交/成功页
|
|
224
|
+
if (!orderId && directActive) {
|
|
225
|
+
const now = new Date().toISOString();
|
|
226
|
+
const inferredAmountWei = (() => {
|
|
227
|
+
if (withdrawDirectResult?.dst_token_amount)
|
|
228
|
+
return withdrawDirectResult.dst_token_amount;
|
|
229
|
+
const n = Number(amount || "0");
|
|
230
|
+
return String(n > 0 ? BigInt(Math.floor(n * 1e18)) : 0n);
|
|
231
|
+
})();
|
|
232
|
+
const synthetic = {
|
|
233
|
+
order_id: withdrawDirectResult?.order_id ?? `direct-${Date.now()}`,
|
|
234
|
+
status: withdrawDirectResult?.status ?? "pending",
|
|
235
|
+
chain_id: withdrawDirectResult?.chain_id ?? String(fundingChainId ?? "3131"),
|
|
236
|
+
dst_token_amount: inferredAmountWei,
|
|
237
|
+
fee: withdrawDirectResult?.fee ?? feeDisplay,
|
|
238
|
+
target_chain_id: withdrawDirectResult?.target_chain_id ?? (chain ?? ""),
|
|
239
|
+
target_address: withdrawDirectResult?.target_address ?? (address ?? ""),
|
|
240
|
+
funding_tx_hash: withdrawDirectResult?.funding_tx_hash ?? txHash,
|
|
241
|
+
dst_tx_hash: withdrawDirectResult?.dst_tx_hash,
|
|
242
|
+
out_tx_hash: withdrawDirectResult?.out_tx_hash,
|
|
243
|
+
created_at: withdrawDirectResult?.created_at ?? now,
|
|
244
|
+
updated_at: withdrawDirectResult?.updated_at ?? now,
|
|
245
|
+
one_time_address: withdrawDirectResult?.one_time_address,
|
|
246
|
+
};
|
|
247
|
+
setWithdrawOrder(synthetic);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
// 3) 默认:清空订单,显示表单
|
|
251
|
+
setWithdrawOrder(null);
|
|
252
|
+
}, [orderId, directActive, withdrawDirectResult, amount, feeDisplay, chain, address, txHash, fundingChainId, onShowToast, mockWithdrawOrderState]);
|
|
253
|
+
// 订单完成回调:支持 orderId 或 direct 模式
|
|
254
|
+
const completedKeyRef = useRef(null);
|
|
213
255
|
useEffect(() => {
|
|
214
|
-
if (withdrawOrder?.status
|
|
215
|
-
|
|
256
|
+
if (withdrawOrder?.status !== "completed")
|
|
257
|
+
return;
|
|
258
|
+
const key = orderId ?? withdrawOrder.order_id;
|
|
259
|
+
if (key && completedKeyRef.current !== key) {
|
|
260
|
+
completedKeyRef.current = key;
|
|
216
261
|
onWithdrawCompleted?.();
|
|
217
262
|
}
|
|
218
|
-
if (!
|
|
219
|
-
|
|
220
|
-
}, [withdrawOrder?.status, orderId, onWithdrawCompleted]);
|
|
263
|
+
if (!trackingWithdraw)
|
|
264
|
+
completedKeyRef.current = null;
|
|
265
|
+
}, [withdrawOrder?.status, orderId, trackingWithdraw, onWithdrawCompleted]);
|
|
221
266
|
const receiveAmount = useMemo(() => {
|
|
222
267
|
if (receiveAmountProp) {
|
|
223
268
|
const n = Number(receiveAmountProp);
|
|
@@ -254,7 +299,7 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
254
299
|
direction: "withdraw",
|
|
255
300
|
chain_id: chain,
|
|
256
301
|
token_address: tokenAddress,
|
|
257
|
-
|
|
302
|
+
dst_token_amount: amountWei,
|
|
258
303
|
})
|
|
259
304
|
.then((q) => setApiQuote(q ?? null))
|
|
260
305
|
.catch(() => {
|
|
@@ -379,7 +424,7 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
379
424
|
flexDirection: "column",
|
|
380
425
|
gap: 4,
|
|
381
426
|
width: "100%",
|
|
382
|
-
}, children: [_jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "8px 0", height: 36 }, children: [_jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textSecondary }, children: "Amount" }), _jsxs("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: [weiToEtherDisplay(withdrawOrder.
|
|
427
|
+
}, children: [_jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "8px 0", height: 36 }, children: [_jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textSecondary }, children: "Amount" }), _jsxs("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: [weiToEtherDisplay(withdrawOrder.dst_token_amount), " ", tokenSymbol] })] }), _jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "8px 0", height: 36 }, children: [_jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textSecondary }, children: "Fee" }), _jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: withdrawOrder.fee ?? feeDisplay ?? "—" })] }), _jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "8px 0", height: 36 }, children: [_jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textSecondary }, children: "Network" }), _jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: targetChainName })] }), destTxHash && (_jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "8px 0", minHeight: 38 }, children: [_jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textSecondary }, children: "Transaction Hash" }), _jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [explorerUrl ? (_jsxs("a", { href: explorerUrl, target: "_blank", rel: "noopener noreferrer", style: { fontSize: 14, color: colors.textPrimary, textDecoration: "underline" }, children: [destTxHash.slice(0, 10), "...", destTxHash.slice(-8)] })) : (_jsxs("span", { style: { fontSize: 14, color: colors.textPrimary }, children: [destTxHash.slice(0, 10), "...", destTxHash.slice(-8)] })), _jsx("button", { type: "button", onClick: copyHash, "aria-label": "Copy hash", style: {
|
|
383
428
|
padding: 0,
|
|
384
429
|
border: "none",
|
|
385
430
|
background: "transparent",
|
|
@@ -390,7 +435,12 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
390
435
|
justifyContent: "center",
|
|
391
436
|
width: 16,
|
|
392
437
|
height: 16,
|
|
393
|
-
}, children: _jsx(CopyIcon, {}) })] })] }))] }), _jsx("div", { style: { paddingTop: 24, width: "100%", display: "flex", justifyContent: "center" }, children: _jsx("button", { type: "button", onClick: () =>
|
|
438
|
+
}, children: _jsx(CopyIcon, {}) })] })] }))] }), _jsx("div", { style: { paddingTop: 24, width: "100%", display: "flex", justifyContent: "center" }, children: _jsx("button", { type: "button", onClick: () => {
|
|
439
|
+
// 重置 direct 模式追踪与本地订单,恢复到表单态
|
|
440
|
+
setDirectActive(false);
|
|
441
|
+
setWithdrawOrder(null);
|
|
442
|
+
(onStartAnotherWithdrawal ?? onClose)?.();
|
|
443
|
+
}, style: {
|
|
394
444
|
width: 274,
|
|
395
445
|
padding: "12px 0",
|
|
396
446
|
borderRadius: radii.full,
|
|
@@ -435,7 +485,7 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
435
485
|
display: "flex",
|
|
436
486
|
flexDirection: "column",
|
|
437
487
|
gap: 8,
|
|
438
|
-
}, children: loadingQuote ? (_jsx("span", { style: { fontSize: 13, color: colors.textSecondary }, children: "Loading\u2026" })) : (_jsxs(_Fragment, { children: [_jsxs("span", { style: { fontSize: 13, color: colors.textSecondary }, children: ["Rate: 1
|
|
488
|
+
}, children: loadingQuote ? (_jsx("span", { style: { fontSize: 13, color: colors.textSecondary }, children: "Loading\u2026" })) : (_jsxs(_Fragment, { children: [_jsxs("span", { style: { fontSize: 13, color: colors.textSecondary }, children: ["Rate: 1 ", FUNDING_TOKEN_SYMBOL, " = ", apiQuote.rate, " ", apiQuote.token_symbol] }), apiQuote.expires_at && (_jsx(Countdown, { expiresAt: apiQuote.expires_at, isExpired: quoteExpired, onExpired: handleRefreshQuote })), quoteExpired && (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [_jsx("span", { style: { fontSize: 13, color: "#f59e0b" }, children: "Quote expired, please refresh" }), _jsx("button", { type: "button", onClick: handleRefreshQuote, style: {
|
|
439
489
|
padding: "4px 12px",
|
|
440
490
|
fontSize: 12,
|
|
441
491
|
borderRadius: radii.pill,
|
|
@@ -444,7 +494,7 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
444
494
|
color: colors.textPrimary,
|
|
445
495
|
cursor: "pointer",
|
|
446
496
|
fontFamily: fonts.family,
|
|
447
|
-
}, children: "Refresh" })] }))] })) })), _jsx("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: _jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [_jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [_jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: "Amount" }), balance && (_jsxs("span", { style: { fontSize: 13, lineHeight: 1.2, color: colors.textSecondary }, children: ["Balance: \u00A0", formatBalanceTo2Decimals(balance)] }))] }), _jsxs("div", { style: {
|
|
497
|
+
}, children: "Refresh" })] }))] })) })), _jsx("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: _jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [_jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [_jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: "Amount" }), balance && (_jsxs("span", { style: { fontSize: 13, lineHeight: 1.2, color: colors.textSecondary }, children: ["Balance: \u00A0", formatBalanceTo2Decimals(balance), " ", FUNDING_TOKEN_SYMBOL] }))] }), _jsxs("div", { style: {
|
|
448
498
|
display: "flex",
|
|
449
499
|
alignItems: "center",
|
|
450
500
|
justifyContent: "space-between",
|
|
@@ -463,23 +513,18 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
463
513
|
fontFamily: fonts.family,
|
|
464
514
|
lineHeight: 1.4,
|
|
465
515
|
padding: 0,
|
|
466
|
-
} }),
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
fontWeight: 400,
|
|
479
|
-
color: "#15181D",
|
|
480
|
-
fontFamily: fonts.family,
|
|
481
|
-
cursor: "pointer",
|
|
482
|
-
}, children: "Max" })] })] })] }) })] }) })] })] })] }), _jsxs("div", { style: { padding: "20px 20px 0", display: "flex", flexDirection: "column", gap: 10, alignItems: "center" }, id: "WithdrawModalReceiveAmount", children: [!trackingWithdraw && amount && Number(amount) > 0 && (_jsxs("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: ["You will receive : ", receiveAmount] })), orderInProgress && withdrawOrder && (() => {
|
|
516
|
+
} }), _jsx("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: _jsx("button", { type: "button", onClick: onMaxClick, style: {
|
|
517
|
+
background: colors.textPrimary,
|
|
518
|
+
border: "none",
|
|
519
|
+
borderRadius: radii.pill,
|
|
520
|
+
padding: "2px 8px",
|
|
521
|
+
fontSize: 12,
|
|
522
|
+
lineHeight: 1.4,
|
|
523
|
+
fontWeight: 400,
|
|
524
|
+
color: "#15181D",
|
|
525
|
+
fontFamily: fonts.family,
|
|
526
|
+
cursor: "pointer",
|
|
527
|
+
}, children: "Max" }) })] })] }) })] }) })] })] })] }), _jsxs("div", { style: { padding: "20px 20px 0", display: "flex", flexDirection: "column", gap: 10, alignItems: "center" }, id: "WithdrawModalReceiveAmount", children: [!trackingWithdraw && amount && Number(amount) > 0 && (_jsxs("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: ["You will receive : ", receiveAmount] })), orderInProgress && withdrawOrder && (() => {
|
|
483
528
|
const fundingHash = txHash ?? withdrawOrder?.funding_tx_hash;
|
|
484
529
|
const showFundingLink = fundingHash && fundingChainId;
|
|
485
530
|
try {
|
|
@@ -500,6 +545,7 @@ export const WithdrawModal = ({ address = "", token, tokenSymbol = "USDT", chain
|
|
|
500
545
|
toAddress: address,
|
|
501
546
|
amount: amount ?? "",
|
|
502
547
|
token: token ?? "",
|
|
548
|
+
tokenAddress: resolvedTokenAddress ?? apiQuote?.token_address ?? "",
|
|
503
549
|
chain: chain ?? "",
|
|
504
550
|
}) }))] })] }));
|
|
505
551
|
};
|
|
@@ -3,6 +3,6 @@ export interface DepositDetailsPanelProps {
|
|
|
3
3
|
address: string;
|
|
4
4
|
tokenIcon?: ReactNode;
|
|
5
5
|
minimumDeposit?: string;
|
|
6
|
-
onCopyAddress?: () => void;
|
|
6
|
+
onCopyAddress?: (address: string) => void;
|
|
7
7
|
}
|
|
8
8
|
export declare const DepositDetailsPanel: ({ address, tokenIcon, minimumDeposit, onCopyAddress, }: DepositDetailsPanelProps) => import("react/jsx-runtime.js").JSX.Element;
|
|
@@ -56,9 +56,32 @@ const StyledQR = ({ data }) => {
|
|
|
56
56
|
const CopyIcon = () => (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: [_jsx("rect", { x: "4.5", y: "4.5", width: "7", height: "7", rx: "1.5", stroke: colors.textPrimary, strokeWidth: "1.2" }), _jsx("path", { d: "M9.5 4.5V3.5C9.5 2.67 8.83 2 8 2H3.5C2.67 2 2 2.67 2 3.5V8C2 8.83 2.67 9.5 3.5 9.5H4.5", stroke: colors.textPrimary, strokeWidth: "1.2" })] }));
|
|
57
57
|
/* ─── Main ──────────────────────────────────── */
|
|
58
58
|
export const DepositDetailsPanel = ({ address, tokenIcon, minimumDeposit, onCopyAddress, }) => {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
const canCopy = typeof address === "string" && address.trim().length > 0;
|
|
60
|
+
const handleCopy = async () => {
|
|
61
|
+
if (!canCopy)
|
|
62
|
+
return;
|
|
63
|
+
try {
|
|
64
|
+
if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
|
|
65
|
+
await navigator.clipboard.writeText(address);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const el = document.createElement("textarea");
|
|
69
|
+
el.value = address;
|
|
70
|
+
el.setAttribute("readonly", "");
|
|
71
|
+
el.style.position = "absolute";
|
|
72
|
+
el.style.left = "-9999px";
|
|
73
|
+
document.body.appendChild(el);
|
|
74
|
+
el.select();
|
|
75
|
+
try {
|
|
76
|
+
document.execCommand("copy");
|
|
77
|
+
}
|
|
78
|
+
catch { }
|
|
79
|
+
document.body.removeChild(el);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
onCopyAddress?.(address);
|
|
84
|
+
}
|
|
62
85
|
};
|
|
63
86
|
return (_jsxs("div", { style: {
|
|
64
87
|
display: "flex",
|
|
@@ -95,7 +118,7 @@ export const DepositDetailsPanel = ({ address, tokenIcon, minimumDeposit, onCopy
|
|
|
95
118
|
display: "flex",
|
|
96
119
|
justifyContent: "space-between",
|
|
97
120
|
fontSize: 13,
|
|
98
|
-
}, children: [_jsx("span", { style: { color: colors.textSecondary }, children: "Minimum deposit" }), _jsx("span", { style: { color: colors.textPrimary, fontWeight: 500 }, children: minimumDeposit })] })), _jsxs("button", { type: "button", onClick: handleCopy, style: {
|
|
121
|
+
}, children: [_jsx("span", { style: { color: colors.textSecondary }, children: "Minimum deposit" }), _jsx("span", { style: { color: colors.textPrimary, fontWeight: 500 }, children: minimumDeposit })] })), _jsxs("button", { type: "button", onClick: handleCopy, disabled: !canCopy, style: {
|
|
99
122
|
display: "flex",
|
|
100
123
|
alignItems: "center",
|
|
101
124
|
gap: 6,
|
|
@@ -106,10 +129,13 @@ export const DepositDetailsPanel = ({ address, tokenIcon, minimumDeposit, onCopy
|
|
|
106
129
|
color: colors.textPrimary,
|
|
107
130
|
fontSize: 14,
|
|
108
131
|
fontWeight: 500,
|
|
109
|
-
cursor: "pointer",
|
|
132
|
+
cursor: canCopy ? "pointer" : "not-allowed",
|
|
133
|
+
opacity: canCopy ? 1 : 0.6,
|
|
110
134
|
fontFamily: fonts.family,
|
|
111
135
|
transition: "background .15s",
|
|
112
136
|
}, onMouseEnter: (e) => {
|
|
137
|
+
if (!canCopy)
|
|
138
|
+
return;
|
|
113
139
|
e.currentTarget.style.background = "rgba(255,255,255,0.06)";
|
|
114
140
|
}, onMouseLeave: (e) => {
|
|
115
141
|
e.currentTarget.style.background = "transparent";
|
package/dist/ui/signInTypes.d.ts
CHANGED
|
@@ -16,6 +16,9 @@ export interface SignInUiConfig {
|
|
|
16
16
|
socialProviders?: SocialProvider[];
|
|
17
17
|
wallets?: WalletItem[];
|
|
18
18
|
initialVisibleCount?: number;
|
|
19
|
+
/**
|
|
20
|
+
* @deprecated Ignored by `SignInModal` / `useSignInModalController`: social login creates the session without `window.confirm`.
|
|
21
|
+
*/
|
|
19
22
|
sessionConfirmation?: {
|
|
20
23
|
enabled?: boolean;
|
|
21
24
|
title?: string;
|