@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.
Files changed (86) hide show
  1. package/README.md +246 -0
  2. package/dist/auth/autoReconnect.d.ts +11 -0
  3. package/dist/auth/autoReconnect.js +36 -0
  4. package/dist/auth/bundledConfig.d.ts +2 -0
  5. package/dist/auth/bundledConfig.js +19 -0
  6. package/dist/auth/config.d.ts +29 -0
  7. package/dist/auth/config.js +53 -0
  8. package/dist/auth/google.d.ts +43 -0
  9. package/dist/auth/google.js +147 -0
  10. package/dist/auth/twitter.d.ts +7 -0
  11. package/dist/auth/twitter.js +94 -0
  12. package/dist/constants/chains.d.ts +22 -0
  13. package/dist/constants/chains.js +23 -0
  14. package/dist/index.d.ts +19 -0
  15. package/dist/index.js +19 -0
  16. package/dist/modules/api.d.ts +144 -0
  17. package/dist/modules/api.js +93 -0
  18. package/dist/modules/balanceQuery.d.ts +20 -0
  19. package/dist/modules/balanceQuery.js +58 -0
  20. package/dist/modules/deposit.d.ts +31 -0
  21. package/dist/modules/deposit.js +57 -0
  22. package/dist/modules/marketData.d.ts +8 -0
  23. package/dist/modules/marketData.js +113 -0
  24. package/dist/modules/withdraw.d.ts +31 -0
  25. package/dist/modules/withdraw.js +60 -0
  26. package/dist/modules/withdrawExecutor.d.ts +47 -0
  27. package/dist/modules/withdrawExecutor.js +208 -0
  28. package/dist/policyAdapter.d.ts +11 -0
  29. package/dist/policyAdapter.js +38 -0
  30. package/dist/types.d.ts +62 -0
  31. package/dist/types.js +1 -0
  32. package/dist/ui/DepositModal.d.ts +36 -0
  33. package/dist/ui/DepositModal.js +326 -0
  34. package/dist/ui/SignInModal.d.ts +22 -0
  35. package/dist/ui/SignInModal.js +74 -0
  36. package/dist/ui/SignInModal.sections.d.ts +33 -0
  37. package/dist/ui/SignInModal.sections.js +45 -0
  38. package/dist/ui/SignInModal.shared.d.ts +15 -0
  39. package/dist/ui/SignInModal.shared.js +87 -0
  40. package/dist/ui/WalletSelectionModal.d.ts +14 -0
  41. package/dist/ui/WalletSelectionModal.js +54 -0
  42. package/dist/ui/WithdrawModal.d.ts +47 -0
  43. package/dist/ui/WithdrawModal.js +528 -0
  44. package/dist/ui/components/CloseButton.d.ts +4 -0
  45. package/dist/ui/components/CloseButton.js +15 -0
  46. package/dist/ui/components/Countdown.d.ts +16 -0
  47. package/dist/ui/components/Countdown.js +42 -0
  48. package/dist/ui/components/DepositDetailsPanel.d.ts +8 -0
  49. package/dist/ui/components/DepositDetailsPanel.js +117 -0
  50. package/dist/ui/components/DropdownField.d.ts +19 -0
  51. package/dist/ui/components/DropdownField.js +81 -0
  52. package/dist/ui/components/Field.d.ts +10 -0
  53. package/dist/ui/components/Field.js +21 -0
  54. package/dist/ui/components/LoginRequiredOverlay.d.ts +6 -0
  55. package/dist/ui/components/LoginRequiredOverlay.js +31 -0
  56. package/dist/ui/components/ModalCard.d.ts +9 -0
  57. package/dist/ui/components/ModalCard.js +14 -0
  58. package/dist/ui/components/ModalFrame.d.ts +9 -0
  59. package/dist/ui/components/ModalFrame.js +18 -0
  60. package/dist/ui/components/PrimaryButton.d.ts +2 -0
  61. package/dist/ui/components/PrimaryButton.js +14 -0
  62. package/dist/ui/components/QRCodePanel.d.ts +4 -0
  63. package/dist/ui/components/QRCodePanel.js +43 -0
  64. package/dist/ui/components/Select.d.ts +12 -0
  65. package/dist/ui/components/Select.js +29 -0
  66. package/dist/ui/components/StepIndicator.d.ts +7 -0
  67. package/dist/ui/components/StepIndicator.js +35 -0
  68. package/dist/ui/components/Success.d.ts +1 -0
  69. package/dist/ui/components/Success.js +4 -0
  70. package/dist/ui/components/Toast.d.ts +8 -0
  71. package/dist/ui/components/Toast.js +51 -0
  72. package/dist/ui/hooks/useSession.d.ts +2 -0
  73. package/dist/ui/hooks/useSession.js +10 -0
  74. package/dist/ui/signInTypes.d.ts +25 -0
  75. package/dist/ui/signInTypes.js +1 -0
  76. package/dist/ui/theme.d.ts +31 -0
  77. package/dist/ui/theme.js +31 -0
  78. package/dist/ui/useSignInModalController.d.ts +25 -0
  79. package/dist/ui/useSignInModalController.js +173 -0
  80. package/dist/utils/env.d.ts +1 -0
  81. package/dist/utils/env.js +61 -0
  82. package/dist/utils/explorer.d.ts +3 -0
  83. package/dist/utils/explorer.js +47 -0
  84. package/dist/walletUtils.d.ts +3 -0
  85. package/dist/walletUtils.js +3 -0
  86. 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;