@ab-org/predicate-market-sdk 0.0.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 +246 -0
- package/dist/auth/autoReconnect.d.ts +11 -0
- package/dist/auth/autoReconnect.js +36 -0
- package/dist/auth/bundledConfig.d.ts +2 -0
- package/dist/auth/bundledConfig.js +19 -0
- package/dist/auth/config.d.ts +29 -0
- package/dist/auth/config.js +53 -0
- package/dist/auth/google.d.ts +43 -0
- package/dist/auth/google.js +147 -0
- package/dist/auth/twitter.d.ts +7 -0
- package/dist/auth/twitter.js +94 -0
- package/dist/constants/chains.d.ts +22 -0
- package/dist/constants/chains.js +23 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +19 -0
- package/dist/modules/api.d.ts +144 -0
- package/dist/modules/api.js +93 -0
- package/dist/modules/balanceQuery.d.ts +20 -0
- package/dist/modules/balanceQuery.js +58 -0
- package/dist/modules/deposit.d.ts +31 -0
- package/dist/modules/deposit.js +57 -0
- package/dist/modules/marketData.d.ts +8 -0
- package/dist/modules/marketData.js +113 -0
- package/dist/modules/withdraw.d.ts +31 -0
- package/dist/modules/withdraw.js +60 -0
- package/dist/modules/withdrawExecutor.d.ts +47 -0
- package/dist/modules/withdrawExecutor.js +208 -0
- package/dist/policyAdapter.d.ts +11 -0
- package/dist/policyAdapter.js +38 -0
- package/dist/types.d.ts +62 -0
- package/dist/types.js +1 -0
- package/dist/ui/DepositModal.d.ts +36 -0
- package/dist/ui/DepositModal.js +326 -0
- package/dist/ui/SignInModal.d.ts +22 -0
- package/dist/ui/SignInModal.js +74 -0
- package/dist/ui/SignInModal.sections.d.ts +33 -0
- package/dist/ui/SignInModal.sections.js +45 -0
- package/dist/ui/SignInModal.shared.d.ts +15 -0
- package/dist/ui/SignInModal.shared.js +87 -0
- package/dist/ui/WalletSelectionModal.d.ts +14 -0
- package/dist/ui/WalletSelectionModal.js +54 -0
- package/dist/ui/WithdrawModal.d.ts +47 -0
- package/dist/ui/WithdrawModal.js +528 -0
- package/dist/ui/components/CloseButton.d.ts +4 -0
- package/dist/ui/components/CloseButton.js +15 -0
- package/dist/ui/components/Countdown.d.ts +16 -0
- package/dist/ui/components/Countdown.js +42 -0
- package/dist/ui/components/DepositDetailsPanel.d.ts +8 -0
- package/dist/ui/components/DepositDetailsPanel.js +117 -0
- package/dist/ui/components/DropdownField.d.ts +19 -0
- package/dist/ui/components/DropdownField.js +81 -0
- package/dist/ui/components/Field.d.ts +10 -0
- package/dist/ui/components/Field.js +21 -0
- package/dist/ui/components/LoginRequiredOverlay.d.ts +6 -0
- package/dist/ui/components/LoginRequiredOverlay.js +31 -0
- package/dist/ui/components/ModalCard.d.ts +9 -0
- package/dist/ui/components/ModalCard.js +14 -0
- package/dist/ui/components/ModalFrame.d.ts +9 -0
- package/dist/ui/components/ModalFrame.js +18 -0
- package/dist/ui/components/PrimaryButton.d.ts +2 -0
- package/dist/ui/components/PrimaryButton.js +14 -0
- package/dist/ui/components/QRCodePanel.d.ts +4 -0
- package/dist/ui/components/QRCodePanel.js +43 -0
- package/dist/ui/components/Select.d.ts +12 -0
- package/dist/ui/components/Select.js +29 -0
- package/dist/ui/components/StepIndicator.d.ts +7 -0
- package/dist/ui/components/StepIndicator.js +35 -0
- package/dist/ui/components/Success.d.ts +1 -0
- package/dist/ui/components/Success.js +4 -0
- package/dist/ui/components/Toast.d.ts +8 -0
- package/dist/ui/components/Toast.js +51 -0
- package/dist/ui/hooks/useSession.d.ts +2 -0
- package/dist/ui/hooks/useSession.js +10 -0
- package/dist/ui/signInTypes.d.ts +25 -0
- package/dist/ui/signInTypes.js +1 -0
- package/dist/ui/theme.d.ts +31 -0
- package/dist/ui/theme.js +31 -0
- package/dist/ui/useSignInModalController.d.ts +25 -0
- package/dist/ui/useSignInModalController.js +173 -0
- package/dist/utils/env.d.ts +1 -0
- package/dist/utils/env.js +61 -0
- package/dist/utils/explorer.d.ts +3 -0
- package/dist/utils/explorer.js +47 -0
- package/dist/walletUtils.d.ts +3 -0
- package/dist/walletUtils.js +3 -0
- package/package.json +41 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect, useCallback, useMemo, useRef } from "react";
|
|
3
|
+
import { ModalFrame } from "./components/ModalFrame.js";
|
|
4
|
+
import { StepIndicator } from "./components/StepIndicator.js";
|
|
5
|
+
import { DropdownField } from "./components/DropdownField.js";
|
|
6
|
+
import { Countdown } from "./components/Countdown.js";
|
|
7
|
+
import { DepositDetailsPanel } from "./components/DepositDetailsPanel.js";
|
|
8
|
+
import { LoginRequiredOverlay } from "./components/LoginRequiredOverlay.js";
|
|
9
|
+
import { useSession } from "./hooks/useSession.js";
|
|
10
|
+
import { colors, fonts, radii } from "./theme.js";
|
|
11
|
+
import { getChains, quote, } from "../modules/api.js";
|
|
12
|
+
/** 校验是否为合法的充值地址(传入值):非空且长度满足常见链地址格式 */
|
|
13
|
+
function isValidDepositAddress(v) {
|
|
14
|
+
return typeof v === "string" && v.trim().length >= 20;
|
|
15
|
+
}
|
|
16
|
+
/* ─── Icons ──────────────────────────────────── */
|
|
17
|
+
const BackArrow = () => (_jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M15 6L9 12L15 18", stroke: colors.textPrimary, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
18
|
+
const TransferIcon = () => (_jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [_jsx("circle", { cx: "18", cy: "18", r: "18", fill: "rgba(255,255,255,0.08)" }), _jsx("circle", { cx: "18", cy: "18", r: "7", stroke: colors.textPrimary, strokeWidth: "1.5" }), _jsx("circle", { cx: "18", cy: "18", r: "2.5", fill: colors.textPrimary }), _jsx("path", { d: "M18 7V11", stroke: colors.textPrimary, strokeWidth: "1.5", strokeLinecap: "round" }), _jsx("path", { d: "M18 25V29", stroke: colors.textPrimary, strokeWidth: "1.5", strokeLinecap: "round" }), _jsx("path", { d: "M7 18H11", stroke: colors.textPrimary, strokeWidth: "1.5", strokeLinecap: "round" }), _jsx("path", { d: "M25 18H29", stroke: colors.textPrimary, strokeWidth: "1.5", strokeLinecap: "round" })] }));
|
|
19
|
+
const FiatIcon = () => (_jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [_jsx("circle", { cx: "18", cy: "18", r: "18", fill: "rgba(255,255,255,0.06)" }), _jsx("circle", { cx: "18", cy: "18", r: "10", stroke: colors.textSecondary, strokeWidth: "1.5" }), _jsx("path", { d: "M18 12V24", stroke: colors.textSecondary, strokeWidth: "1.5", strokeLinecap: "round" }), _jsx("path", { d: "M15 15.5C15 14.12 16.34 13 18 13C19.66 13 21 14.12 21 15.5C21 16.88 19.66 18 18 18C16.34 18 15 19.12 15 20.5C15 21.88 16.34 23 18 23C19.66 23 21 21.88 21 20.5", stroke: colors.textSecondary, strokeWidth: "1.5", strokeLinecap: "round" })] }));
|
|
20
|
+
const DefaultCryptoIcons = () => {
|
|
21
|
+
const tokens = [
|
|
22
|
+
{ label: "B", bg: "#F7931A" },
|
|
23
|
+
{ label: "E", bg: "#627EEA" },
|
|
24
|
+
{ label: "≡", bg: "#26A17B" },
|
|
25
|
+
{ label: "$", bg: "#2775CA" },
|
|
26
|
+
{ label: "S", bg: "#9945FF" },
|
|
27
|
+
{ label: "A", bg: "#E84142" },
|
|
28
|
+
];
|
|
29
|
+
return (_jsx("div", { style: { display: "flex", gap: 0 }, children: tokens.map((t, i) => (_jsx("div", { style: {
|
|
30
|
+
width: 24,
|
|
31
|
+
height: 24,
|
|
32
|
+
borderRadius: "50%",
|
|
33
|
+
background: t.bg,
|
|
34
|
+
display: "flex",
|
|
35
|
+
alignItems: "center",
|
|
36
|
+
justifyContent: "center",
|
|
37
|
+
fontSize: 11,
|
|
38
|
+
fontWeight: 700,
|
|
39
|
+
color: "#fff",
|
|
40
|
+
marginLeft: i > 0 ? -4 : 0,
|
|
41
|
+
border: `2px solid ${colors.card}`,
|
|
42
|
+
boxSizing: "content-box",
|
|
43
|
+
}, children: t.label }, i))) }));
|
|
44
|
+
};
|
|
45
|
+
/* ─── Helpers: derive options from getChains ─── */
|
|
46
|
+
/** Deposit 时不可选 USD1(充值是转入 USD1,源代币为 USDT/USDC 等) */
|
|
47
|
+
const DEPOSIT_EXCLUDED_TOKEN = "USD1";
|
|
48
|
+
function chainsToTokenOptions(chains) {
|
|
49
|
+
const bySymbol = new Map();
|
|
50
|
+
for (const c of chains) {
|
|
51
|
+
for (const t of c.tokens) {
|
|
52
|
+
if (!bySymbol.has(t.symbol))
|
|
53
|
+
bySymbol.set(t.symbol, { symbol: t.symbol, decimals: t.decimals });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return Array.from(bySymbol.entries())
|
|
57
|
+
.filter(([id]) => id !== DEPOSIT_EXCLUDED_TOKEN)
|
|
58
|
+
.map(([id, { symbol }]) => ({
|
|
59
|
+
id,
|
|
60
|
+
label: symbol,
|
|
61
|
+
subtitle: symbol,
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
function chainsToChainOptionsForToken(chains, tokenSymbol) {
|
|
65
|
+
return chains
|
|
66
|
+
.filter((c) => c.tokens.some((t) => t.symbol === tokenSymbol))
|
|
67
|
+
.map((c) => ({
|
|
68
|
+
id: c.chain_id,
|
|
69
|
+
label: c.network,
|
|
70
|
+
subtitle: `chainId: ${c.chain_id}`,
|
|
71
|
+
icon: (_jsx("span", { style: {
|
|
72
|
+
display: "inline-flex",
|
|
73
|
+
alignItems: "center",
|
|
74
|
+
justifyContent: "center",
|
|
75
|
+
minWidth: 28,
|
|
76
|
+
height: 28,
|
|
77
|
+
padding: "0 6px",
|
|
78
|
+
borderRadius: radii.card,
|
|
79
|
+
background: "rgba(255,255,255,0.08)",
|
|
80
|
+
fontSize: 12,
|
|
81
|
+
fontWeight: 600,
|
|
82
|
+
color: colors.textPrimary,
|
|
83
|
+
fontFamily: fonts.family,
|
|
84
|
+
}, children: c.network })),
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
function getTokenAddressForChain(chains, chainId, tokenSymbol) {
|
|
88
|
+
const chain = chains.find((c) => c.chain_id === chainId);
|
|
89
|
+
return chain?.tokens.find((t) => t.symbol === tokenSymbol)?.address;
|
|
90
|
+
}
|
|
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
|
+
const session = useSession();
|
|
93
|
+
const [view, setView] = useState("entry");
|
|
94
|
+
const [copySuccessMessage, setCopySuccessMessage] = useState(null);
|
|
95
|
+
const [apiChains, setApiChains] = useState(null);
|
|
96
|
+
const [apiQuote, setApiQuote] = useState(null);
|
|
97
|
+
const [loadingChains, setLoadingChains] = useState(false);
|
|
98
|
+
const [loadingQuote, setLoadingQuote] = useState(false);
|
|
99
|
+
const [quoteRefreshKey, setQuoteRefreshKey] = useState(0);
|
|
100
|
+
const tokenOptions = useMemo(() => {
|
|
101
|
+
const excludeUsd1 = (opts) => opts.filter((o) => o.id !== DEPOSIT_EXCLUDED_TOKEN && o.label !== DEPOSIT_EXCLUDED_TOKEN);
|
|
102
|
+
if (tokenOptionsProp?.length)
|
|
103
|
+
return excludeUsd1(tokenOptionsProp);
|
|
104
|
+
if (!apiChains?.length)
|
|
105
|
+
return undefined;
|
|
106
|
+
return chainsToTokenOptions(apiChains);
|
|
107
|
+
}, [tokenOptionsProp, apiChains]);
|
|
108
|
+
const chainOptions = useMemo(() => {
|
|
109
|
+
if (chainOptionsProp?.length)
|
|
110
|
+
return chainOptionsProp;
|
|
111
|
+
if (!apiChains?.length || !token)
|
|
112
|
+
return undefined;
|
|
113
|
+
return chainsToChainOptionsForToken(apiChains, token);
|
|
114
|
+
}, [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
|
+
// 仅有一个 chain 选项时默认选中
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
if (chainOptions?.length !== 1 || !onChainSelect)
|
|
124
|
+
return;
|
|
125
|
+
const onlyId = chainOptions[0].id;
|
|
126
|
+
if (chain === onlyId)
|
|
127
|
+
return;
|
|
128
|
+
onChainSelect(onlyId);
|
|
129
|
+
}, [chainOptions, chain, onChainSelect]);
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (view !== "transfer")
|
|
132
|
+
return;
|
|
133
|
+
setLoadingChains(true);
|
|
134
|
+
getChains()
|
|
135
|
+
.then((res) => setApiChains(res?.chains ?? {}))
|
|
136
|
+
.finally(() => setLoadingChains(false));
|
|
137
|
+
}, [view]);
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
if (!apiChains?.length || !token || !chain) {
|
|
140
|
+
setApiQuote(null);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const tokenAddress = getTokenAddressForChain(apiChains, chain, token);
|
|
144
|
+
if (!tokenAddress) {
|
|
145
|
+
setApiQuote(null);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
setLoadingQuote(true);
|
|
149
|
+
console.log('setLoadingQuote', tokenAddress, depositAmount);
|
|
150
|
+
quote({
|
|
151
|
+
direction: "deposit",
|
|
152
|
+
chain_id: chain,
|
|
153
|
+
token_address: tokenAddress,
|
|
154
|
+
token_amount: depositAmount || undefined,
|
|
155
|
+
})
|
|
156
|
+
.then((q) => setApiQuote(q ?? null))
|
|
157
|
+
.catch((err) => {
|
|
158
|
+
const message = err?.message ?? String(err);
|
|
159
|
+
console.error('setLoadingQuote', message);
|
|
160
|
+
if (onShowToast)
|
|
161
|
+
onShowToast(message);
|
|
162
|
+
setApiQuote({
|
|
163
|
+
token_address: tokenAddress,
|
|
164
|
+
token_symbol: token,
|
|
165
|
+
token_decimals: 18,
|
|
166
|
+
rate: "1",
|
|
167
|
+
chain_id: Number(chain) || 56,
|
|
168
|
+
deposit_address: "0x" + "0".repeat(39) + "1",
|
|
169
|
+
usd1_amount: depositAmount ?? "0",
|
|
170
|
+
expires_at: new Date(Date.now() + 60000).toISOString(),
|
|
171
|
+
});
|
|
172
|
+
})
|
|
173
|
+
.finally(() => setLoadingQuote(false));
|
|
174
|
+
}, [apiChains, token, chain, depositAmount, quoteRefreshKey, onShowToast]);
|
|
175
|
+
const handleQuoteExpired = useCallback(() => {
|
|
176
|
+
setQuoteRefreshKey((k) => k + 1);
|
|
177
|
+
}, []);
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
if (txHash && chain && onShowToast) {
|
|
180
|
+
onShowToast("Transfer confirmed");
|
|
181
|
+
}
|
|
182
|
+
}, [txHash, chain, onShowToast]);
|
|
183
|
+
if (!session) {
|
|
184
|
+
return _jsx(LoginRequiredOverlay, { title: "Deposit", onSignIn: onSignIn, onClose: onClose });
|
|
185
|
+
}
|
|
186
|
+
const goToEntry = () => {
|
|
187
|
+
setView("entry");
|
|
188
|
+
onBack?.();
|
|
189
|
+
};
|
|
190
|
+
const handleCopyAddress = useCallback(() => {
|
|
191
|
+
onCopyAddress?.();
|
|
192
|
+
onShowToast?.("Address copied");
|
|
193
|
+
setCopySuccessMessage("Address copied");
|
|
194
|
+
}, [onCopyAddress, onShowToast]);
|
|
195
|
+
useEffect(() => {
|
|
196
|
+
if (!copySuccessMessage)
|
|
197
|
+
return;
|
|
198
|
+
const t = setTimeout(() => setCopySuccessMessage(null), 2000);
|
|
199
|
+
return () => clearTimeout(t);
|
|
200
|
+
}, [copySuccessMessage]);
|
|
201
|
+
return (_jsxs(ModalFrame, { onClose: onClose, contentStyle: { padding: "24px", position: "relative" }, children: [copySuccessMessage && (_jsx("div", { style: {
|
|
202
|
+
position: "absolute",
|
|
203
|
+
bottom: 24,
|
|
204
|
+
left: "50%",
|
|
205
|
+
transform: "translateX(-50%)",
|
|
206
|
+
padding: "10px 20px",
|
|
207
|
+
borderRadius: 8,
|
|
208
|
+
background: "var(--pm-colors-card, #1a1a2e)",
|
|
209
|
+
color: "var(--pm-colors-textPrimary, #fff)",
|
|
210
|
+
fontSize: 13,
|
|
211
|
+
fontWeight: 500,
|
|
212
|
+
boxShadow: "0 4px 12px rgba(0,0,0,.25)",
|
|
213
|
+
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: () => {
|
|
215
|
+
if (!apiChains?.length || !token || !chain)
|
|
216
|
+
return;
|
|
217
|
+
const tokenAddress = getTokenAddressForChain(apiChains, chain, token);
|
|
218
|
+
if (tokenAddress) {
|
|
219
|
+
setLoadingQuote(true);
|
|
220
|
+
quote({ direction: "deposit", chain_id: chain, token_address: tokenAddress, token_amount: depositAmount })
|
|
221
|
+
.then((q) => setApiQuote(q ?? null))
|
|
222
|
+
.catch(() => {
|
|
223
|
+
setApiQuote({
|
|
224
|
+
token_address: tokenAddress,
|
|
225
|
+
token_symbol: token,
|
|
226
|
+
token_decimals: 18,
|
|
227
|
+
rate: "1",
|
|
228
|
+
chain_id: Number(chain) || 56,
|
|
229
|
+
deposit_address: "0x" + "0".repeat(39) + "1",
|
|
230
|
+
usd1_amount: depositAmount ?? "0",
|
|
231
|
+
expires_at: new Date(Date.now() + 60000).toISOString(),
|
|
232
|
+
});
|
|
233
|
+
})
|
|
234
|
+
.finally(() => setLoadingQuote(false));
|
|
235
|
+
}
|
|
236
|
+
}, onShowToast: onShowToast, onBack: goToEntry }))] }));
|
|
237
|
+
};
|
|
238
|
+
/* ─── Entry View ─────────────────────────────── */
|
|
239
|
+
const EntryView = ({ cryptoIcons, onTransferCrypto, onBuyCrypto: _onBuyCrypto, }) => (_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 24 }, children: [_jsx("h2", { style: { margin: 0, fontSize: 24, fontWeight: 600, lineHeight: 1.4 }, children: "Deposit" }), _jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [_jsxs("button", { type: "button", onClick: onTransferCrypto, style: {
|
|
240
|
+
display: "flex",
|
|
241
|
+
alignItems: "center",
|
|
242
|
+
gap: 14,
|
|
243
|
+
padding: "18px 20px",
|
|
244
|
+
borderRadius: radii.card,
|
|
245
|
+
border: `1px solid ${colors.border}`,
|
|
246
|
+
background: "transparent",
|
|
247
|
+
cursor: "pointer",
|
|
248
|
+
textAlign: "left",
|
|
249
|
+
fontFamily: fonts.family,
|
|
250
|
+
width: "100%",
|
|
251
|
+
transition: "border-color .15s",
|
|
252
|
+
}, onMouseEnter: (e) => { e.target.closest("button").style.borderColor = colors.borderStrong; }, onMouseLeave: (e) => { e.target.closest("button").style.borderColor = colors.border; }, children: [_jsx(TransferIcon, {}), _jsxs("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: 2 }, children: [_jsx("span", { style: { color: colors.textPrimary, fontSize: 16, fontWeight: 600 }, children: "Transfer Crypto" }), _jsx("span", { style: { color: colors.textSecondary, fontSize: 13 }, children: "No limit \u00B7 Instant" })] }), cryptoIcons ?? _jsx(DefaultCryptoIcons, {})] }), _jsxs("div", { style: {
|
|
253
|
+
display: "flex",
|
|
254
|
+
alignItems: "center",
|
|
255
|
+
gap: 14,
|
|
256
|
+
padding: "18px 20px",
|
|
257
|
+
borderRadius: radii.card,
|
|
258
|
+
border: `1px solid ${colors.border}`,
|
|
259
|
+
opacity: 0.55,
|
|
260
|
+
}, children: [_jsx(FiatIcon, {}), _jsxs("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: 2 }, children: [_jsx("span", { style: { color: colors.textSecondary, fontSize: 16, fontWeight: 600 }, children: "Buy Crypto" }), _jsx("span", { style: { color: colors.textSecondary, fontSize: 13 }, children: "Debit card, credit card, ACH" })] }), _jsx("span", { style: {
|
|
261
|
+
padding: "5px 12px",
|
|
262
|
+
borderRadius: radii.pill,
|
|
263
|
+
border: `1px solid ${colors.border}`,
|
|
264
|
+
fontSize: 12,
|
|
265
|
+
fontWeight: 500,
|
|
266
|
+
color: colors.textSecondary,
|
|
267
|
+
whiteSpace: "nowrap",
|
|
268
|
+
}, children: "Coming Soon" })] })] })] }));
|
|
269
|
+
/* ─── Transfer View (stepper) ────────────────── */
|
|
270
|
+
const TransferView = ({ token, chain, tokenOptions, chainOptions, depositAddress, minimumDeposit, qrCenterIcon, quote: quoteData, quoteLoading, txHash, chainIdForExplorer, explorerTxUrl, loadingChains, onTokenSelect, onChainSelect, onCopyAddress, onQuoteExpired, onRefreshQuote, onShowToast, onBack, }) => {
|
|
271
|
+
const activeStep = chain ? 2 : token ? 1 : 0;
|
|
272
|
+
const stepActive = [!!token, !!chain, !!quoteData];
|
|
273
|
+
const quoteExpired = useMemo(() => {
|
|
274
|
+
if (!quoteData?.expires_at)
|
|
275
|
+
return false;
|
|
276
|
+
try {
|
|
277
|
+
return new Date(quoteData.expires_at).getTime() < Date.now();
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
}, [quoteData?.expires_at]);
|
|
283
|
+
const didToastWait = useRef(false);
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
if (!depositAddress || !onShowToast || didToastWait.current)
|
|
286
|
+
return;
|
|
287
|
+
didToastWait.current = true;
|
|
288
|
+
onShowToast("Please wait for deposit-address balance to update");
|
|
289
|
+
}, [depositAddress, onShowToast]);
|
|
290
|
+
return (_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 24 }, children: [_jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: _jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [onBack && (_jsx("button", { type: "button", onClick: onBack, style: {
|
|
291
|
+
background: "transparent",
|
|
292
|
+
border: "none",
|
|
293
|
+
cursor: "pointer",
|
|
294
|
+
padding: 0,
|
|
295
|
+
display: "flex",
|
|
296
|
+
alignItems: "center",
|
|
297
|
+
}, children: _jsx(BackArrow, {}) })), _jsx("h2", { style: { margin: 0, fontSize: 24, fontWeight: 600, lineHeight: 1.4 }, children: "Transfer Crypto" })] }) }), _jsxs("div", { style: { display: "flex", gap: 16, position: "relative" }, children: [_jsx(StepIndicator, { steps: 3, stepActive: stepActive, activeStep: activeStep }), _jsxs("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: 40 }, children: [_jsx(DropdownField, { label: "Select token", placeholder: loadingChains ? "Loading…" : "Token", value: token, options: tokenOptions, onSelect: onTokenSelect }), _jsx(DropdownField, { label: "Select chain", placeholder: loadingChains ? "Loading…" : "Chain", value: chain, options: chainOptions, onSelect: onChainSelect }), quoteData && token && chain && (_jsx("div", { id: "quote-panel", style: {
|
|
298
|
+
padding: "12px 16px",
|
|
299
|
+
borderRadius: radii.card,
|
|
300
|
+
margin: "-10px 0",
|
|
301
|
+
border: `1px solid ${colors.border}`,
|
|
302
|
+
display: "flex",
|
|
303
|
+
flexDirection: "column",
|
|
304
|
+
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, " USD1"] }), 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
|
+
padding: "4px 12px",
|
|
307
|
+
fontSize: 12,
|
|
308
|
+
borderRadius: radii.pill,
|
|
309
|
+
border: `1px solid ${colors.border}`,
|
|
310
|
+
background: "transparent",
|
|
311
|
+
color: colors.textPrimary,
|
|
312
|
+
cursor: "pointer",
|
|
313
|
+
fontFamily: fonts.family,
|
|
314
|
+
}, children: "Refresh" }))] }))] })) })), _jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8, marginTop: "-5px" }, id: "deposit-details", children: [_jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary }, children: "Deposit details" }), depositAddress ? (_jsxs(_Fragment, { children: [_jsx(DepositDetailsPanel, { address: depositAddress, tokenIcon: qrCenterIcon, minimumDeposit: minimumDeposit, onCopyAddress: onCopyAddress }), txHash && chainIdForExplorer && explorerTxUrl && (_jsx("a", { href: explorerTxUrl(chainIdForExplorer, txHash), target: "_blank", rel: "noopener noreferrer", style: {
|
|
315
|
+
fontSize: 13,
|
|
316
|
+
color: colors.textPrimary,
|
|
317
|
+
textDecoration: "underline",
|
|
318
|
+
}, children: "View on explorer" }))] })) : (_jsx("div", { style: {
|
|
319
|
+
padding: "20px",
|
|
320
|
+
borderRadius: radii.card,
|
|
321
|
+
border: `1px solid ${colors.border}`,
|
|
322
|
+
color: colors.textSecondary,
|
|
323
|
+
fontSize: 13,
|
|
324
|
+
textAlign: "center",
|
|
325
|
+
}, children: "Select token and chain to view deposit details" }))] })] })] })] }));
|
|
326
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type CubeSignerSession, type WalletSession } from "@ab-org/sdk-core";
|
|
2
|
+
import type { GoogleCredential } from "../auth/google.js";
|
|
3
|
+
import type { TwitterAuthResult } from "../auth/twitter.js";
|
|
4
|
+
import type { SocialProvider, WalletItem } from "./signInTypes.js";
|
|
5
|
+
export interface SignInModalProps {
|
|
6
|
+
title?: string;
|
|
7
|
+
socialProviders?: SocialProvider[];
|
|
8
|
+
wallets?: WalletItem[];
|
|
9
|
+
initialVisibleCount?: number;
|
|
10
|
+
privacyPolicyUrl?: string;
|
|
11
|
+
termsOfUseUrl?: string;
|
|
12
|
+
onGoogleLogin?: (credential: GoogleCredential) => void;
|
|
13
|
+
onTwitterLogin?: (result: TwitterAuthResult) => void;
|
|
14
|
+
onCubeSignerSession?: (session: CubeSignerSession) => void;
|
|
15
|
+
onWalletConnected?: (session: WalletSession, walletId: string) => void;
|
|
16
|
+
onSocialLogin?: (providerId: string) => void;
|
|
17
|
+
onWalletSelect?: (walletId: string) => void | Promise<void>;
|
|
18
|
+
onDismiss?: () => void;
|
|
19
|
+
onSuccess?: (session: WalletSession) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function clearSocialAccountInstance(): void;
|
|
22
|
+
export declare const SignInModal: ({ title, socialProviders, wallets, initialVisibleCount, privacyPolicyUrl, termsOfUseUrl, onGoogleLogin, onTwitterLogin, onCubeSignerSession, onWalletConnected, onSocialLogin, onWalletSelect, onDismiss, onSuccess, }: SignInModalProps) => import("react/jsx-runtime.js").JSX.Element;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { sessionStore } from "@ab-org/sdk-core";
|
|
4
|
+
import { getSDKConfig } from "../auth/config.js";
|
|
5
|
+
import { resolveSocialProviders } from "./SignInModal.shared.js";
|
|
6
|
+
import { SignInModalFooter, SignInModalFrame, SignInModalSocialSection, SignInModalWalletGrid, } from "./SignInModal.sections.js";
|
|
7
|
+
import { useSignInModalController } from "./useSignInModalController.js";
|
|
8
|
+
import { Toast } from "./components/Toast.js";
|
|
9
|
+
export function clearSocialAccountInstance() {
|
|
10
|
+
try {
|
|
11
|
+
const storage = typeof localStorage !== "undefined" ? localStorage : null;
|
|
12
|
+
const adapterId = storage?.getItem("ab:wallet:adapterId");
|
|
13
|
+
const session = sessionStore.getState().session;
|
|
14
|
+
const isSocialSession = session?.walletType === "social" ||
|
|
15
|
+
session?.authSource === "google" ||
|
|
16
|
+
session?.authSource === "twitter" ||
|
|
17
|
+
adapterId === "cubist";
|
|
18
|
+
if (!isSocialSession)
|
|
19
|
+
return;
|
|
20
|
+
sessionStore.clearSession();
|
|
21
|
+
storage?.removeItem("ab:wallet:session");
|
|
22
|
+
storage?.removeItem("ab:wallet:adapterId");
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
sessionStore.clearSession();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export const SignInModal = ({ title = "Welcome to PredicateMarket", socialProviders, wallets, initialVisibleCount, privacyPolicyUrl = "#", termsOfUseUrl = "#", onGoogleLogin, onTwitterLogin, onCubeSignerSession, onWalletConnected, onSocialLogin, onWalletSelect, onDismiss, onSuccess, }) => {
|
|
29
|
+
const sdkConfig = getSDKConfig();
|
|
30
|
+
const effectiveSocialProviders = resolveSocialProviders(socialProviders ?? sdkConfig.signIn?.socialProviders);
|
|
31
|
+
const effectiveWallets = wallets ?? sdkConfig.signIn?.wallets;
|
|
32
|
+
const effectiveInitialVisibleCount = initialVisibleCount ?? sdkConfig.signIn?.initialVisibleCount ?? 5;
|
|
33
|
+
const [toastError, setToastError] = useState(null);
|
|
34
|
+
const { expanded, loadingProvider, loadingWalletId, visibleWallets, showExpandToggle, isBusy, handleSocialClick, handleWalletClick, toggleExpanded, } = useSignInModalController({
|
|
35
|
+
wallets: effectiveWallets,
|
|
36
|
+
initialVisibleCount: effectiveInitialVisibleCount,
|
|
37
|
+
onGoogleLogin,
|
|
38
|
+
onTwitterLogin,
|
|
39
|
+
onCubeSignerSession,
|
|
40
|
+
onWalletConnected,
|
|
41
|
+
onSocialLogin,
|
|
42
|
+
onWalletSelect,
|
|
43
|
+
});
|
|
44
|
+
return (_jsxs(SignInModalFrame, { id: "SignInModalFrame", title: title, onClose: onDismiss, footer: _jsx(SignInModalFooter, { privacyPolicyUrl: privacyPolicyUrl, termsOfUseUrl: termsOfUseUrl }), children: [toastError ? (_jsx(Toast, { message: toastError, variant: "error", duration: 5000, onClose: () => setToastError(null) })) : null, _jsx(SignInModalSocialSection, { id: "SignInModalSocialSection", socialProviders: effectiveSocialProviders, isBusy: isBusy, loadingProvider: loadingProvider, onSocialClick: async (providerId) => {
|
|
45
|
+
try {
|
|
46
|
+
const session = await handleSocialClick(providerId);
|
|
47
|
+
if (!session)
|
|
48
|
+
return;
|
|
49
|
+
const normalizedAuthSource = providerId === "x"
|
|
50
|
+
? "twitter"
|
|
51
|
+
: providerId;
|
|
52
|
+
onSuccess?.({
|
|
53
|
+
...session,
|
|
54
|
+
walletType: session.walletType ?? "social",
|
|
55
|
+
authSource: session.authSource ?? normalizedAuthSource,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const msg = error instanceof Error ? error.message : "Social login failed";
|
|
60
|
+
setToastError(msg);
|
|
61
|
+
}
|
|
62
|
+
} }), _jsx(SignInModalWalletGrid, { wallets: visibleWallets, isBusy: isBusy, loadingWalletId: loadingWalletId, expanded: expanded, showExpandToggle: showExpandToggle, onWalletClick: async (walletId) => {
|
|
63
|
+
try {
|
|
64
|
+
const session = await handleWalletClick(walletId);
|
|
65
|
+
if (session) {
|
|
66
|
+
onSuccess?.(session);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const msg = error instanceof Error ? error.message : "Wallet connect failed";
|
|
71
|
+
setToastError(msg);
|
|
72
|
+
}
|
|
73
|
+
}, onToggleExpanded: toggleExpanded })] }));
|
|
74
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { SocialProvider, WalletItem } from "./signInTypes.js";
|
|
3
|
+
export interface SignInModalSocialSectionProps {
|
|
4
|
+
id: string;
|
|
5
|
+
socialProviders: SocialProvider[];
|
|
6
|
+
isBusy: boolean;
|
|
7
|
+
loadingProvider: string | null;
|
|
8
|
+
onSocialClick: (providerId: string) => void | Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export interface SignInModalFrameProps {
|
|
11
|
+
id: string;
|
|
12
|
+
title: string;
|
|
13
|
+
onClose?: () => void;
|
|
14
|
+
footer?: ReactNode;
|
|
15
|
+
children: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
export declare const SignInModalFrame: ({ id, title, onClose, footer, children, }: SignInModalFrameProps) => import("react/jsx-runtime.js").JSX.Element;
|
|
18
|
+
export declare const SignInModalSocialSection: ({ id, socialProviders, isBusy, loadingProvider, onSocialClick, }: SignInModalSocialSectionProps) => import("react/jsx-runtime.js").JSX.Element;
|
|
19
|
+
export interface SignInModalWalletGridProps {
|
|
20
|
+
wallets: WalletItem[];
|
|
21
|
+
isBusy: boolean;
|
|
22
|
+
loadingWalletId: string | null;
|
|
23
|
+
expanded: boolean;
|
|
24
|
+
showExpandToggle: boolean;
|
|
25
|
+
onWalletClick: (walletId: string) => void | Promise<void>;
|
|
26
|
+
onToggleExpanded: () => void;
|
|
27
|
+
}
|
|
28
|
+
export declare const SignInModalWalletGrid: ({ wallets, isBusy, loadingWalletId, expanded, showExpandToggle, onWalletClick, onToggleExpanded, }: SignInModalWalletGridProps) => import("react/jsx-runtime.js").JSX.Element;
|
|
29
|
+
export interface SignInModalFooterProps {
|
|
30
|
+
privacyPolicyUrl: string;
|
|
31
|
+
termsOfUseUrl: string;
|
|
32
|
+
}
|
|
33
|
+
export declare const SignInModalFooter: ({ privacyPolicyUrl, termsOfUseUrl, }: SignInModalFooterProps) => import("react/jsx-runtime.js").JSX.Element;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ModalFrame } from "./components/ModalFrame.js";
|
|
3
|
+
import { colors, fonts, radii } from "./theme.js";
|
|
4
|
+
import { DefaultWalletIcon, ExpandIcon, SpinnerIcon } from "./SignInModal.shared.js";
|
|
5
|
+
export const SignInModalFrame = ({ id, title, onClose, footer, children, }) => (_jsx(ModalFrame, { onClose: onClose, cardStyle: { padding: "32px 24px" }, contentStyle: { alignItems: "center" }, children: _jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: 24, alignItems: "center" }, id: id, children: [_jsx("h2", { style: { margin: 0, fontSize: 24, fontWeight: 600, lineHeight: 1.4, textAlign: "center" }, children: title }), _jsx("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: 12, alignItems: "center" }, children: children }), footer] }) }));
|
|
6
|
+
export const SignInModalSocialSection = ({ id, socialProviders, isBusy, loadingProvider, onSocialClick, }) => (_jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: 24 }, id: id, children: [_jsx("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: socialProviders.map((provider) => {
|
|
7
|
+
const isLoading = loadingProvider === provider.id;
|
|
8
|
+
return (_jsxs("button", { type: "button", disabled: isBusy, onClick: () => onSocialClick(provider.id), style: {
|
|
9
|
+
width: "100%",
|
|
10
|
+
height: 48,
|
|
11
|
+
borderRadius: radii.pill,
|
|
12
|
+
border: `1px solid ${colors.border}`,
|
|
13
|
+
background: "transparent",
|
|
14
|
+
display: "flex",
|
|
15
|
+
alignItems: "center",
|
|
16
|
+
justifyContent: "center",
|
|
17
|
+
gap: 12,
|
|
18
|
+
cursor: isBusy ? "wait" : "pointer",
|
|
19
|
+
padding: 12,
|
|
20
|
+
boxSizing: "border-box",
|
|
21
|
+
opacity: isLoading ? 0.6 : isBusy ? 0.8 : 1,
|
|
22
|
+
transition: "opacity .15s",
|
|
23
|
+
}, children: [isLoading ? _jsx(SpinnerIcon, {}) : provider.icon, _jsx("span", { style: { fontSize: 16, fontWeight: 500, lineHeight: 1.4, color: colors.textPrimary, fontFamily: fonts.family }, children: isLoading ? "Signing in..." : provider.label })] }, provider.id));
|
|
24
|
+
}) }), _jsxs("div", { style: { display: "flex", alignItems: "center", gap: 20, width: "100%" }, children: [_jsx("div", { style: { flex: 1, height: 1, background: colors.border } }), _jsx("span", { style: { fontSize: 14, lineHeight: 1.4, color: colors.textPrimary, opacity: 0.4, whiteSpace: "nowrap" }, children: "Or connect a wallet" }), _jsx("div", { style: { flex: 1, height: 1, background: colors.border } })] })] }));
|
|
25
|
+
export const SignInModalWalletGrid = ({ wallets, isBusy, loadingWalletId, expanded, showExpandToggle, onWalletClick, onToggleExpanded, }) => (_jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "column", gap: 8, alignItems: "center", paddingTop: 12 }, children: [_jsx("div", { style: { width: "100%", display: "flex", flexWrap: "wrap", gap: "14px 0" }, children: wallets.map((wallet) => (_jsxs("button", { type: "button", disabled: isBusy, onClick: () => onWalletClick(wallet.id), style: {
|
|
26
|
+
width: "25%",
|
|
27
|
+
display: "flex",
|
|
28
|
+
flexDirection: "column",
|
|
29
|
+
alignItems: "center",
|
|
30
|
+
gap: 4,
|
|
31
|
+
background: "transparent",
|
|
32
|
+
border: "none",
|
|
33
|
+
cursor: isBusy ? "wait" : "pointer",
|
|
34
|
+
padding: 0,
|
|
35
|
+
opacity: loadingWalletId === wallet.id ? 0.7 : isBusy ? 0.85 : 1,
|
|
36
|
+
}, children: [_jsx("div", { style: { width: 56, height: 56, display: "flex", alignItems: "center", justifyContent: "center" }, children: loadingWalletId === wallet.id ? (_jsx(SpinnerIcon, {})) : (wallet.icon ?? _jsx(DefaultWalletIcon, { walletId: wallet.id, name: wallet.name })) }), _jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", width: "100%" }, children: [_jsx("span", { style: { fontSize: 12, fontWeight: 500, lineHeight: 1.4, color: colors.textPrimary, fontFamily: fonts.family, textAlign: "center", whiteSpace: "nowrap" }, children: wallet.name }), loadingWalletId === wallet.id ? (_jsx("span", { style: { fontSize: 10, lineHeight: 1.4, color: colors.textSecondary, fontFamily: fonts.family }, children: "Connecting..." })) : wallet.installed ? (_jsx("span", { style: { fontSize: 10, lineHeight: 1.4, color: colors.accent, fontFamily: fonts.family }, children: "Installed" })) : wallet.installUrl ? (_jsx("a", { href: wallet.installUrl, target: "_blank", rel: "noopener noreferrer", onClick: (event) => event.stopPropagation(), style: { fontSize: 10, lineHeight: 1.4, color: colors.textSecondary, fontFamily: fonts.family, textDecoration: "underline" }, children: "Install" })) : null] })] }, wallet.id))) }), showExpandToggle && (_jsx("button", { type: "button", onClick: onToggleExpanded, style: {
|
|
37
|
+
background: "transparent",
|
|
38
|
+
border: "none",
|
|
39
|
+
cursor: "pointer",
|
|
40
|
+
display: "flex",
|
|
41
|
+
alignItems: "center",
|
|
42
|
+
justifyContent: "center",
|
|
43
|
+
padding: 4,
|
|
44
|
+
}, children: _jsx(ExpandIcon, { expanded: expanded }) }))] }));
|
|
45
|
+
export const SignInModalFooter = ({ privacyPolicyUrl, termsOfUseUrl, }) => (_jsx("div", { style: { padding: "12px 0", display: "flex", justifyContent: "center", width: "100%" }, children: _jsxs("p", { style: { margin: 0, fontSize: 14, lineHeight: 1.4, color: colors.textSecondary, fontFamily: fonts.family, textAlign: "center" }, children: ["By continuing, I agree to the", " ", _jsx("a", { href: privacyPolicyUrl, style: { color: colors.textPrimary, textDecoration: "underline" }, target: "_blank", rel: "noopener noreferrer", children: "Privacy Policy" }), " ", "and", " ", _jsx("a", { href: termsOfUseUrl, style: { color: colors.textPrimary, textDecoration: "underline" }, target: "_blank", rel: "noopener noreferrer", children: "Terms of Use" })] }) }));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { InjectedWalletRegistryItem } from "@ab-org/sdk-core";
|
|
2
|
+
import type { SocialProvider, WalletItem } from "./signInTypes.js";
|
|
3
|
+
export declare const GoogleIcon: () => import("react/jsx-runtime.js").JSX.Element;
|
|
4
|
+
export declare const XIcon: () => import("react/jsx-runtime.js").JSX.Element;
|
|
5
|
+
export declare const ExpandIcon: ({ expanded }: {
|
|
6
|
+
expanded: boolean;
|
|
7
|
+
}) => import("react/jsx-runtime.js").JSX.Element;
|
|
8
|
+
export declare const SpinnerIcon: () => import("react/jsx-runtime.js").JSX.Element;
|
|
9
|
+
export declare const defaultSocialProviders: SocialProvider[];
|
|
10
|
+
export declare function resolveWalletItems(wallets: WalletItem[] | undefined, defaultWalletRegistry: InjectedWalletRegistryItem[]): WalletItem[];
|
|
11
|
+
export declare function resolveSocialProviders(socialProviders: SocialProvider[] | undefined): SocialProvider[];
|
|
12
|
+
export declare const DefaultWalletIcon: ({ walletId, name, }: {
|
|
13
|
+
walletId: string;
|
|
14
|
+
name: string;
|
|
15
|
+
}) => import("react/jsx-runtime.js").JSX.Element;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { colors, fonts } from "./theme.js";
|
|
3
|
+
export const GoogleIcon = () => (_jsxs("svg", { width: "21", height: "21", viewBox: "0 0 21 21", fill: "none", children: [_jsx("path", { d: "M20.3 10.73c0-.79-.07-1.54-.19-2.27H10.5v4.51h5.5a4.69 4.69 0 0 1-2.04 3.09v2.57h3.3c1.93-1.78 3.04-4.4 3.04-7.9Z", fill: "#4285F4" }), _jsx("path", { d: "M10.5 21c2.76 0 5.07-.91 6.76-2.47l-3.3-2.57c-.92.61-2.09.97-3.46.97-2.66 0-4.91-1.8-5.71-4.22H1.39v2.65A10.5 10.5 0 0 0 10.5 21Z", fill: "#34A853" }), _jsx("path", { d: "M4.79 12.71A6.3 6.3 0 0 1 4.46 10.5c0-.77.13-1.51.33-2.21V5.64H1.39A10.5 10.5 0 0 0 0 10.5c0 1.7.41 3.3 1.39 4.86l3.4-2.65Z", fill: "#FBBC05" }), _jsx("path", { d: "M10.5 4.07c1.5 0 2.84.51 3.9 1.52l2.92-2.92C15.56 1.02 13.26 0 10.5 0A10.5 10.5 0 0 0 1.39 5.64l3.4 2.65C5.59 5.87 7.84 4.07 10.5 4.07Z", fill: "#EA4335" })] }));
|
|
4
|
+
export const XIcon = () => (_jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231 5.45-6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117L17.083 19.77Z", fill: "white" }) }));
|
|
5
|
+
export const ExpandIcon = ({ expanded }) => (_jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { transform: expanded ? "rotate(180deg)" : undefined, transition: "transform 0.2s" }, children: [_jsx("path", { d: "M5 9L9 13L13 9", stroke: colors.textSecondary, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M11 9L15 13L19 9", stroke: colors.textSecondary, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] }));
|
|
6
|
+
export const SpinnerIcon = () => (_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", style: { animation: "spin 1s linear infinite" }, children: [_jsx("circle", { cx: "10", cy: "10", r: "8", stroke: "rgba(255,255,255,0.2)", strokeWidth: "2.5" }), _jsx("path", { d: "M10 2a8 8 0 0 1 8 8", stroke: colors.textPrimary, strokeWidth: "2.5", strokeLinecap: "round" }), _jsx("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })] }));
|
|
7
|
+
export const defaultSocialProviders = [
|
|
8
|
+
{ id: "google", label: "Continue with Google", icon: _jsx(GoogleIcon, {}) },
|
|
9
|
+
{ id: "x", label: "Continue with X", icon: _jsx(XIcon, {}) },
|
|
10
|
+
];
|
|
11
|
+
export function resolveWalletItems(wallets, defaultWalletRegistry) {
|
|
12
|
+
const walletMap = new Map(defaultWalletRegistry.map((item) => [
|
|
13
|
+
item.id,
|
|
14
|
+
{
|
|
15
|
+
name: item.title,
|
|
16
|
+
installed: item.installed,
|
|
17
|
+
installUrl: item.installUrl,
|
|
18
|
+
},
|
|
19
|
+
]));
|
|
20
|
+
if (wallets === undefined) {
|
|
21
|
+
return defaultWalletRegistry.map((item) => ({
|
|
22
|
+
id: item.id,
|
|
23
|
+
name: item.title,
|
|
24
|
+
icon: undefined,
|
|
25
|
+
installed: item.installed,
|
|
26
|
+
installUrl: item.installUrl,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
if (wallets.length === 0) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
return wallets.map((wallet) => {
|
|
33
|
+
const fallback = walletMap.get(wallet.id);
|
|
34
|
+
return {
|
|
35
|
+
...wallet,
|
|
36
|
+
name: wallet.name ?? fallback?.name ?? wallet.id,
|
|
37
|
+
installed: wallet.installed ?? fallback?.installed,
|
|
38
|
+
installUrl: wallet.installUrl ?? fallback?.installUrl,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export function resolveSocialProviders(socialProviders) {
|
|
43
|
+
if (socialProviders === undefined) {
|
|
44
|
+
return defaultSocialProviders;
|
|
45
|
+
}
|
|
46
|
+
if (socialProviders.length === 0) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
const defaultProviderMap = new Map(defaultSocialProviders.map((provider) => [provider.id, provider]));
|
|
50
|
+
return socialProviders.map((provider) => {
|
|
51
|
+
const fallback = defaultProviderMap.get(provider.id);
|
|
52
|
+
return {
|
|
53
|
+
...provider,
|
|
54
|
+
label: provider.label ?? fallback?.label ?? provider.id,
|
|
55
|
+
icon: provider.icon ?? fallback?.icon,
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const IconFrame = ({ background, children, }) => (_jsx("div", { style: {
|
|
60
|
+
width: 48,
|
|
61
|
+
height: 48,
|
|
62
|
+
borderRadius: 12,
|
|
63
|
+
background,
|
|
64
|
+
display: "flex",
|
|
65
|
+
alignItems: "center",
|
|
66
|
+
justifyContent: "center",
|
|
67
|
+
overflow: "hidden",
|
|
68
|
+
}, children: children }));
|
|
69
|
+
const walletIconTheme = {
|
|
70
|
+
metamask: "#F6851B",
|
|
71
|
+
okx: "#050608",
|
|
72
|
+
coinbase: "#0052FF",
|
|
73
|
+
trust: "#3375FF",
|
|
74
|
+
phantom: "#6C47FF",
|
|
75
|
+
rabby: "#7084FF",
|
|
76
|
+
rainbow: "#123F99",
|
|
77
|
+
zerion: "#2962EF",
|
|
78
|
+
brave: "#FF452A",
|
|
79
|
+
bitget: "#00F0FF",
|
|
80
|
+
};
|
|
81
|
+
const WalletPlaceholder = ({ walletId, name }) => (_jsx(IconFrame, { background: walletIconTheme[walletId] ?? colors.cardRaised, children: _jsx("span", { style: {
|
|
82
|
+
fontSize: 14,
|
|
83
|
+
fontWeight: 700,
|
|
84
|
+
color: walletIconTheme[walletId] ? "#FFFFFF" : colors.textSecondary,
|
|
85
|
+
fontFamily: fonts.family,
|
|
86
|
+
}, children: name.slice(0, 2).toUpperCase() }) }));
|
|
87
|
+
export const DefaultWalletIcon = ({ walletId, name, }) => _jsx(WalletPlaceholder, { walletId: walletId, name: name });
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface WalletOption {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
description: string;
|
|
6
|
+
category: "social" | "plugin";
|
|
7
|
+
icon?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export interface WalletSelectionModalProps {
|
|
10
|
+
title?: string;
|
|
11
|
+
options: WalletOption[];
|
|
12
|
+
onSelect?: (id: string) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare const WalletSelectionModal: ({ title, options, onSelect, }: WalletSelectionModalProps) => import("react/jsx-runtime.js").JSX.Element;
|