@stableflow/pay-widgets 0.2.0-beta-90dffc3d2f-20261012 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/token-select/index.d.ts +1 -21
- package/dist/token-select/index.js +665 -691
- package/dist/token-select/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -9,11 +9,29 @@ import { useSyncExternalStore } from "react";
|
|
|
9
9
|
var TOKEN_BALANCE_POLL_MS = 6e4;
|
|
10
10
|
var ALL_CHAIN_FILTER = "all";
|
|
11
11
|
var DEFAULT_STABLE_SYMBOLS = ["USDT", "USDC"];
|
|
12
|
-
var POPULAR_SECTION_TITLE = "Popular on your network";
|
|
13
12
|
var TOKEN_SELECT_PREFS_STORAGE_KEY = "stableflow-pay:token-select-prefs:v1";
|
|
14
|
-
var TOKEN_SELECT_PREFS_VERSION =
|
|
13
|
+
var TOKEN_SELECT_PREFS_VERSION = 3;
|
|
15
14
|
var MAX_RECENT_BLOCKCHAINS = 16;
|
|
16
|
-
var
|
|
15
|
+
var MAX_RECENTLY_USED = 5;
|
|
16
|
+
var MAX_RECENT_SEARCHES = 5;
|
|
17
|
+
var MAX_RECENT_HISTORY = 50;
|
|
18
|
+
var YOUR_TOKENS_TITLE = "Your Tokens";
|
|
19
|
+
var RECENT_SEARCHES_TITLE = "Recent Searches";
|
|
20
|
+
var TRENDS_TOKEN_TITLE = "Trends Token";
|
|
21
|
+
var ALL_CHAIN_PREVIEW_BLOCKCHAINS = ["eth", "near", "sol", "tron"];
|
|
22
|
+
var DESKTOP_MEDIA_QUERY = "(min-width: 768px)";
|
|
23
|
+
var TRENDS_TOKENS = [
|
|
24
|
+
{ blockchain: "tron", symbol: "USDT" },
|
|
25
|
+
{ blockchain: "eth", symbol: "USDT" },
|
|
26
|
+
{ blockchain: "eth", symbol: "USDC" },
|
|
27
|
+
{ blockchain: "sol", symbol: "USDC" },
|
|
28
|
+
{ blockchain: "sol", symbol: "USDT" },
|
|
29
|
+
{ blockchain: "pol", symbol: "USDC" },
|
|
30
|
+
{ blockchain: "bsc", symbol: "USDT" },
|
|
31
|
+
{ blockchain: "arb", symbol: "USDT" },
|
|
32
|
+
{ blockchain: "arb", symbol: "USDC" },
|
|
33
|
+
{ blockchain: "near", symbol: "USDT" }
|
|
34
|
+
];
|
|
17
35
|
var CHAIN_KIND_LABELS = {
|
|
18
36
|
evm: "EVM",
|
|
19
37
|
near: "Near",
|
|
@@ -247,7 +265,6 @@ function PayWidgetsProvider(props) {
|
|
|
247
265
|
const {
|
|
248
266
|
tokens,
|
|
249
267
|
loading = false,
|
|
250
|
-
popularTokens = [],
|
|
251
268
|
wallet,
|
|
252
269
|
readBalances,
|
|
253
270
|
getBalance,
|
|
@@ -278,7 +295,6 @@ function PayWidgetsProvider(props) {
|
|
|
278
295
|
tokens,
|
|
279
296
|
loading,
|
|
280
297
|
wallet,
|
|
281
|
-
popularTokens,
|
|
282
298
|
stableSymbols,
|
|
283
299
|
chainKindLabels,
|
|
284
300
|
onCopyAddress,
|
|
@@ -297,17 +313,32 @@ function usePayWidgets() {
|
|
|
297
313
|
}
|
|
298
314
|
|
|
299
315
|
// src/token-select/TokenSelectDialog.tsx
|
|
300
|
-
import { useEffect as
|
|
316
|
+
import { useEffect as useEffect5, useMemo, useRef as useRef3, useState as useState4, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
301
317
|
import { Dialog } from "@stableflow/pay-ui/dialog";
|
|
302
|
-
import { SearchInput } from "@stableflow/pay-ui/search-input";
|
|
318
|
+
import { SearchInput as SearchInput2 } from "@stableflow/pay-ui/search-input";
|
|
303
319
|
|
|
304
|
-
// src/token-select/chain-
|
|
305
|
-
import {
|
|
320
|
+
// src/token-select/chain-select.tsx
|
|
321
|
+
import { useEffect as useEffect3, useRef, useState as useState2 } from "react";
|
|
322
|
+
import { IconCheck } from "@stableflow/pay-ui/icons/outline/check";
|
|
323
|
+
import { IconChevron } from "@stableflow/pay-ui/icons/outline/chevron";
|
|
324
|
+
import { Drawer } from "@stableflow/pay-ui/drawer";
|
|
325
|
+
import { SearchInput } from "@stableflow/pay-ui/search-input";
|
|
306
326
|
import { Tooltip } from "@stableflow/pay-ui/tooltip";
|
|
307
327
|
|
|
308
|
-
// src/token-select/chain-
|
|
309
|
-
import {
|
|
310
|
-
|
|
328
|
+
// src/token-select/chain-stack.tsx
|
|
329
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
330
|
+
function ChainStack(props) {
|
|
331
|
+
const { chains, logoClassName } = props;
|
|
332
|
+
return /* @__PURE__ */ jsx2("span", { className: "grid grid-cols-2 gap-0.5", children: chains.slice(0, 4).map((chain) => /* @__PURE__ */ jsx2(
|
|
333
|
+
"img",
|
|
334
|
+
{
|
|
335
|
+
src: chain.logo,
|
|
336
|
+
alt: "",
|
|
337
|
+
className: logoClassName
|
|
338
|
+
},
|
|
339
|
+
chain.blockchain
|
|
340
|
+
)) });
|
|
341
|
+
}
|
|
311
342
|
|
|
312
343
|
// src/token-select/format.ts
|
|
313
344
|
import { clsx } from "clsx";
|
|
@@ -317,12 +348,6 @@ var thinScrollbar = "[&::-webkit-scrollbar]:w-[4px] [&::-webkit-scrollbar-thumb]
|
|
|
317
348
|
function cx(...inputs) {
|
|
318
349
|
return twMerge(clsx(inputs));
|
|
319
350
|
}
|
|
320
|
-
function formatAddress(address, prefix = 4, suffix = 5) {
|
|
321
|
-
if (!address) return "";
|
|
322
|
-
if (!address.startsWith("0x") && address.length <= 32) return address;
|
|
323
|
-
if (address.length <= prefix + suffix) return address;
|
|
324
|
-
return `${address.slice(0, prefix)}...${address.slice(-suffix)}`;
|
|
325
|
-
}
|
|
326
351
|
function chainKindLabel(kind, labels) {
|
|
327
352
|
return labels?.[kind] ?? CHAIN_KIND_LABELS[kind] ?? kind;
|
|
328
353
|
}
|
|
@@ -346,73 +371,21 @@ function formatDisplayAmount(value, options = {}) {
|
|
|
346
371
|
return `${prefix}${negative ? "-" : ""}${body}`;
|
|
347
372
|
}
|
|
348
373
|
|
|
349
|
-
// src/token-select/
|
|
350
|
-
import {
|
|
351
|
-
function
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
return
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
type: "button",
|
|
365
|
-
onClick: (event) => {
|
|
366
|
-
stop(event);
|
|
367
|
-
void wallet.connect(kind);
|
|
368
|
-
},
|
|
369
|
-
className: cx("shrink-0 cursor-pointer border-0 bg-transparent p-0 text-xs font-medium text-[#3F8AFB] hover:underline", fontSans),
|
|
370
|
-
children: account?.connecting ? "Connecting\u2026" : "Connect"
|
|
371
|
-
}
|
|
372
|
-
);
|
|
373
|
-
}
|
|
374
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1", onClick: stop, children: [
|
|
375
|
-
/* @__PURE__ */ jsx2(
|
|
376
|
-
"button",
|
|
377
|
-
{
|
|
378
|
-
type: "button",
|
|
379
|
-
onClick: async (event) => {
|
|
380
|
-
stop(event);
|
|
381
|
-
if (!onCopyAddress) return;
|
|
382
|
-
onCopyAddress(address);
|
|
383
|
-
},
|
|
384
|
-
className: cx("truncate border-0 bg-transparent p-0 text-xs text-[#606060] hover:text-black", fontSans),
|
|
385
|
-
children: formatAddress(address)
|
|
386
|
-
}
|
|
387
|
-
),
|
|
388
|
-
/* @__PURE__ */ jsx2(
|
|
389
|
-
"button",
|
|
390
|
-
{
|
|
391
|
-
type: "button",
|
|
392
|
-
"aria-label": "Copy address",
|
|
393
|
-
onClick: (event) => {
|
|
394
|
-
stop(event);
|
|
395
|
-
if (!onCopyAddress) return;
|
|
396
|
-
onCopyAddress(address);
|
|
397
|
-
},
|
|
398
|
-
className: "inline-flex shrink-0 cursor-pointer border-0 bg-transparent p-0 text-[#606060] hover:text-black",
|
|
399
|
-
children: /* @__PURE__ */ jsx2(IconCopy, { className: "size-3" })
|
|
400
|
-
}
|
|
401
|
-
),
|
|
402
|
-
hideDisconnect ? null : /* @__PURE__ */ jsx2(
|
|
403
|
-
"button",
|
|
404
|
-
{
|
|
405
|
-
type: "button",
|
|
406
|
-
"aria-label": "Disconnect",
|
|
407
|
-
onClick: (event) => {
|
|
408
|
-
stop(event);
|
|
409
|
-
void wallet.disconnect(kind);
|
|
410
|
-
},
|
|
411
|
-
className: "inline-flex shrink-0 cursor-pointer border-0 bg-transparent p-0 text-[#ff5656]",
|
|
412
|
-
children: /* @__PURE__ */ jsx2(IconLogout, { className: "size-3" })
|
|
413
|
-
}
|
|
414
|
-
)
|
|
415
|
-
] });
|
|
374
|
+
// src/token-select/use-desktop.ts
|
|
375
|
+
import { useEffect as useEffect2, useState } from "react";
|
|
376
|
+
function useDesktop() {
|
|
377
|
+
const [matches, setMatches] = useState(() => {
|
|
378
|
+
if (typeof window === "undefined") return true;
|
|
379
|
+
return window.matchMedia(DESKTOP_MEDIA_QUERY).matches;
|
|
380
|
+
});
|
|
381
|
+
useEffect2(() => {
|
|
382
|
+
const media = window.matchMedia(DESKTOP_MEDIA_QUERY);
|
|
383
|
+
const onChange = () => setMatches(media.matches);
|
|
384
|
+
onChange();
|
|
385
|
+
media.addEventListener("change", onChange);
|
|
386
|
+
return () => media.removeEventListener("change", onChange);
|
|
387
|
+
}, []);
|
|
388
|
+
return matches;
|
|
416
389
|
}
|
|
417
390
|
|
|
418
391
|
// src/token-select/utils.ts
|
|
@@ -439,6 +412,10 @@ function tokenMatchesSearch(token, query) {
|
|
|
439
412
|
if (token.providerSymbol.toLowerCase().includes(q)) return true;
|
|
440
413
|
return Boolean(token.contractAddress?.toLowerCase().includes(q));
|
|
441
414
|
}
|
|
415
|
+
function matchesChainFilter(token, chainFilter) {
|
|
416
|
+
if (chainFilter === ALL_CHAIN_FILTER) return true;
|
|
417
|
+
return token.blockchain === chainFilter;
|
|
418
|
+
}
|
|
442
419
|
function formattedBalancePositive(formatted) {
|
|
443
420
|
if (formatted == null || formatted === "") return false;
|
|
444
421
|
const amount = Number(formatted);
|
|
@@ -458,29 +435,6 @@ function chainBalanceUsd(blockchain, tokens, getBalanceUsd) {
|
|
|
458
435
|
}
|
|
459
436
|
return total;
|
|
460
437
|
}
|
|
461
|
-
function parsePopularTokens(raw) {
|
|
462
|
-
if (!raw?.trim()) return [];
|
|
463
|
-
const refs = [];
|
|
464
|
-
for (const part of raw.split(",")) {
|
|
465
|
-
const trimmed = part.trim();
|
|
466
|
-
const colon = trimmed.indexOf(":");
|
|
467
|
-
if (colon <= 0 || colon >= trimmed.length - 1) continue;
|
|
468
|
-
const blockchain = trimmed.slice(0, colon).trim().toLowerCase();
|
|
469
|
-
const symbol = trimmed.slice(colon + 1).trim();
|
|
470
|
-
if (!blockchain || !symbol || symbol.includes(":")) continue;
|
|
471
|
-
refs.push({ blockchain, symbol: symbol.toUpperCase() });
|
|
472
|
-
}
|
|
473
|
-
return refs;
|
|
474
|
-
}
|
|
475
|
-
function popularTokensForWallets(tokens, configured, isChainConnected) {
|
|
476
|
-
const result = [];
|
|
477
|
-
for (const ref of configured) {
|
|
478
|
-
const token = tokens.find((item) => item.blockchain === ref.blockchain && item.symbol.toUpperCase() === ref.symbol);
|
|
479
|
-
if (!token || !isChainConnected(token.chain.chainKind)) continue;
|
|
480
|
-
result.push(token);
|
|
481
|
-
}
|
|
482
|
-
return result;
|
|
483
|
-
}
|
|
484
438
|
function sortChainsAlpha(chains) {
|
|
485
439
|
return chains.slice().sort((left, right) => left.chainName.localeCompare(right.chainName));
|
|
486
440
|
}
|
|
@@ -540,6 +494,9 @@ function sortTokensByBalance(tokens, getBalanceUsd, isLoading) {
|
|
|
540
494
|
return compareTokensBySymbol(left, right);
|
|
541
495
|
});
|
|
542
496
|
}
|
|
497
|
+
function sortTokensBySymbol(tokens) {
|
|
498
|
+
return tokens.slice().sort(compareTokensBySymbol);
|
|
499
|
+
}
|
|
543
500
|
function positiveBalanceTokens(tokens, getBalanceUsd) {
|
|
544
501
|
return sortTokensByBalance(
|
|
545
502
|
tokens.filter((token) => getBalanceUsd(token) > 0),
|
|
@@ -588,48 +545,54 @@ function sortTokensForChain(tokens, options) {
|
|
|
588
545
|
return compareTokensByPriority(left, right, stableSymbols);
|
|
589
546
|
});
|
|
590
547
|
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
const
|
|
595
|
-
const
|
|
596
|
-
for (const
|
|
597
|
-
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
|
|
548
|
+
function trendTokensIn(tokens, options) {
|
|
549
|
+
const trends = options.trends ?? TRENDS_TOKENS;
|
|
550
|
+
const inScope = tokens.filter((token) => matchesChainFilter(token, options.chainFilter));
|
|
551
|
+
const used = /* @__PURE__ */ new Set();
|
|
552
|
+
const head = [];
|
|
553
|
+
for (const ref of trends) {
|
|
554
|
+
if (options.chainFilter !== ALL_CHAIN_FILTER && ref.blockchain.toLowerCase() !== options.chainFilter.toLowerCase()) continue;
|
|
555
|
+
const match = inScope.find((token) => !used.has(token) && token.blockchain.toLowerCase() === ref.blockchain.toLowerCase() && token.symbol.toLowerCase() === ref.symbol.toLowerCase());
|
|
556
|
+
if (!match) continue;
|
|
557
|
+
used.add(match);
|
|
558
|
+
head.push(match);
|
|
601
559
|
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
return
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
560
|
+
return [...head, ...options.sortRest(inScope.filter((token) => !used.has(token)))];
|
|
561
|
+
}
|
|
562
|
+
function allChainPreview(chains) {
|
|
563
|
+
if (chains.length <= 4) return chains.slice();
|
|
564
|
+
const byCode = new Map(chains.map((chain) => [chain.blockchain.toLowerCase(), chain]));
|
|
565
|
+
const used = /* @__PURE__ */ new Set();
|
|
566
|
+
const picked = [];
|
|
567
|
+
const take = (chain) => {
|
|
568
|
+
if (!chain || picked.length >= 4) return;
|
|
569
|
+
const code = chain.blockchain.toLowerCase();
|
|
570
|
+
if (used.has(code)) return;
|
|
571
|
+
used.add(code);
|
|
572
|
+
picked.push(chain);
|
|
573
|
+
};
|
|
574
|
+
const eth = byCode.get(ALL_CHAIN_PREVIEW_BLOCKCHAINS[0]);
|
|
575
|
+
if (eth) take(eth);
|
|
576
|
+
else take(chains.find((chain) => chain.chainKind === "evm"));
|
|
577
|
+
take(byCode.get("near"));
|
|
578
|
+
take(byCode.get("sol"));
|
|
579
|
+
take(byCode.get("tron"));
|
|
580
|
+
const fill = chains.filter((chain) => chain.chainKind === "evm" && !used.has(chain.blockchain.toLowerCase())).slice().sort((left, right) => left.chainName.localeCompare(right.chainName));
|
|
581
|
+
for (const chain of fill) take(chain);
|
|
582
|
+
return picked;
|
|
583
|
+
}
|
|
584
|
+
function chainMenuOrder(chains, tokens, options) {
|
|
585
|
+
const dotted = chains.filter((chain) => options.dotted.has(chain.blockchain));
|
|
586
|
+
const rest = chains.filter((chain) => !options.dotted.has(chain.blockchain));
|
|
587
|
+
return [
|
|
588
|
+
...sortChainsForSidebar(dotted, [...tokens], options),
|
|
589
|
+
...sortChainsAlpha(rest)
|
|
590
|
+
];
|
|
591
|
+
}
|
|
592
|
+
function searchTokens(tokens, query, options) {
|
|
593
|
+
const matched = tokens.filter((token) => tokenMatchesSearch(token, query));
|
|
594
|
+
if (options.role === "payer") return sortTokensByBalance(matched, options.usdOf, options.loadingOf);
|
|
595
|
+
return sortTokensBySymbol(matched);
|
|
633
596
|
}
|
|
634
597
|
function recentTokensInOrder(tokens, recentAssetIds) {
|
|
635
598
|
const byId = new Map(tokens.map((token) => [token.assetId, token]));
|
|
@@ -641,220 +604,260 @@ function recentTokensInOrder(tokens, recentAssetIds) {
|
|
|
641
604
|
return result;
|
|
642
605
|
}
|
|
643
606
|
|
|
644
|
-
// src/token-select/chain-
|
|
645
|
-
import { jsx as jsx3, jsxs
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
function ChainPane(props) {
|
|
607
|
+
// src/token-select/chain-select.tsx
|
|
608
|
+
import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
609
|
+
var SEARCH_FIELD_CLASS = "h-[42px] rounded-[12px] border-[#e3e3e3] bg-[#f6f6f6] text-sm placeholder:text-black/30";
|
|
610
|
+
var SEARCH_ICON_CLASS = "left-4 size-[19px] text-black";
|
|
611
|
+
function ChainSelect(props) {
|
|
650
612
|
const {
|
|
651
613
|
chains,
|
|
652
|
-
|
|
653
|
-
|
|
614
|
+
previewChains,
|
|
615
|
+
dotted,
|
|
616
|
+
value,
|
|
617
|
+
onChange,
|
|
654
618
|
lockChainKind = null,
|
|
655
619
|
disabledBlockchains = null,
|
|
656
|
-
disabledReason
|
|
657
|
-
scrollRef
|
|
620
|
+
disabledReason
|
|
658
621
|
} = props;
|
|
659
622
|
const { chainKindLabels } = usePayWidgets();
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
623
|
+
const isDesktop = useDesktop();
|
|
624
|
+
const [open, setOpen] = useState2(false);
|
|
625
|
+
const [query, setQuery] = useState2("");
|
|
626
|
+
const rootRef = useRef(null);
|
|
627
|
+
const selected = value === ALL_CHAIN_FILTER ? void 0 : chains.find((chain) => chain.blockchain === value);
|
|
628
|
+
useEffect3(() => {
|
|
629
|
+
if (!open) return;
|
|
630
|
+
setQuery("");
|
|
631
|
+
}, [open]);
|
|
632
|
+
useEffect3(() => {
|
|
633
|
+
if (!open || !isDesktop) return;
|
|
634
|
+
const onPointerDown = (event) => {
|
|
635
|
+
const target = event.target;
|
|
636
|
+
if (!(target instanceof Node) || rootRef.current?.contains(target)) return;
|
|
637
|
+
setOpen(false);
|
|
638
|
+
};
|
|
639
|
+
const onKeyDown = (event) => {
|
|
640
|
+
if (event.key !== "Escape") return;
|
|
641
|
+
event.stopPropagation();
|
|
642
|
+
event.preventDefault();
|
|
643
|
+
setOpen(false);
|
|
644
|
+
};
|
|
645
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
646
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
647
|
+
return () => {
|
|
648
|
+
document.removeEventListener("pointerdown", onPointerDown);
|
|
649
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
650
|
+
};
|
|
651
|
+
}, [open, isDesktop]);
|
|
652
|
+
function reasonFor(chain) {
|
|
653
|
+
if (isBlockchainDisabled(chain.blockchain, disabledBlockchains)) return disabledReason;
|
|
654
|
+
if (isChainKindLocked(chain.chainKind, lockChainKind) && lockChainKind) {
|
|
655
|
+
return `Recipient address is on ${chainKindLabel(lockChainKind, chainKindLabels)}; edit the recipient to change chain`;
|
|
656
|
+
}
|
|
657
|
+
return void 0;
|
|
663
658
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
},
|
|
691
|
-
className: cx(
|
|
692
|
-
"flex min-w-0 flex-1 items-center gap-3 border-0 bg-transparent text-left",
|
|
693
|
-
disabled ? "cursor-not-allowed" : "cursor-pointer"
|
|
694
|
-
),
|
|
695
|
-
children: [
|
|
696
|
-
/* @__PURE__ */ jsx3("img", { src: chain.logo, alt: "", className: "size-8 shrink-0 object-cover" }),
|
|
697
|
-
/* @__PURE__ */ jsx3("span", { className: cx("truncate text-sm font-medium text-black", fontSans), children: chain.chainName })
|
|
698
|
-
]
|
|
699
|
-
}
|
|
700
|
-
)
|
|
701
|
-
),
|
|
702
|
-
showWalletStatus ? /* @__PURE__ */ jsx3(ChainWalletStatus, { kind: chain.chainKind }) : /* @__PURE__ */ jsx3("span", { className: "min-w-0 flex-1" }),
|
|
703
|
-
/* @__PURE__ */ jsx3(
|
|
704
|
-
"button",
|
|
705
|
-
{
|
|
706
|
-
type: "button",
|
|
707
|
-
"aria-label": `Open ${chain.chainName}`,
|
|
708
|
-
disabled,
|
|
709
|
-
onClick: () => {
|
|
710
|
-
if (disabled) return;
|
|
711
|
-
onSelectChain(chain.blockchain);
|
|
712
|
-
},
|
|
713
|
-
className: cx(
|
|
714
|
-
"inline-flex shrink-0 border-0 bg-transparent p-0 text-[#606060]",
|
|
715
|
-
disabled ? "cursor-not-allowed" : "cursor-pointer"
|
|
716
|
-
),
|
|
717
|
-
children: /* @__PURE__ */ jsx3(IconChevron, {})
|
|
718
|
-
}
|
|
719
|
-
)
|
|
720
|
-
]
|
|
721
|
-
},
|
|
722
|
-
chain.blockchain
|
|
723
|
-
);
|
|
724
|
-
}) })
|
|
725
|
-
] }) }) });
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
// src/token-select/network-rail.tsx
|
|
729
|
-
import { IconAllNetworks } from "@stableflow/pay-ui/icons/all-networks";
|
|
730
|
-
import { IconWallet } from "@stableflow/pay-ui/icons/wallet";
|
|
731
|
-
import { Tooltip as Tooltip2 } from "@stableflow/pay-ui/tooltip";
|
|
732
|
-
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
733
|
-
function chipClass(selected, disabled) {
|
|
734
|
-
return cx(
|
|
735
|
-
"relative flex size-[50px] shrink-0 items-center justify-center rounded-[12px] border border-solid",
|
|
736
|
-
selected ? "border-[#06f] bg-[rgba(0,102,255,0.1)]" : "border-transparent bg-transparent",
|
|
737
|
-
disabled ? "cursor-not-allowed opacity-40" : "cursor-pointer hover:bg-black/5"
|
|
659
|
+
const trimmed = query.trim().toLowerCase();
|
|
660
|
+
const showAll = !trimmed || "all".includes(trimmed);
|
|
661
|
+
const visible = chains.filter((chain) => {
|
|
662
|
+
if (!trimmed) return true;
|
|
663
|
+
return chain.chainName.toLowerCase().includes(trimmed) || chain.blockchain.toLowerCase().includes(trimmed);
|
|
664
|
+
});
|
|
665
|
+
const empty = !showAll && visible.length === 0;
|
|
666
|
+
function select(blockchain) {
|
|
667
|
+
onChange(blockchain);
|
|
668
|
+
setOpen(false);
|
|
669
|
+
}
|
|
670
|
+
const menu = /* @__PURE__ */ jsx3(
|
|
671
|
+
ChainMenu,
|
|
672
|
+
{
|
|
673
|
+
showAll,
|
|
674
|
+
chains: visible,
|
|
675
|
+
previewChains,
|
|
676
|
+
dotted,
|
|
677
|
+
value,
|
|
678
|
+
query,
|
|
679
|
+
onQueryChange: setQuery,
|
|
680
|
+
empty,
|
|
681
|
+
isDesktop,
|
|
682
|
+
reasonFor,
|
|
683
|
+
onSelect: select
|
|
684
|
+
}
|
|
738
685
|
);
|
|
686
|
+
return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: "relative shrink-0", children: [
|
|
687
|
+
/* @__PURE__ */ jsxs(
|
|
688
|
+
"button",
|
|
689
|
+
{
|
|
690
|
+
type: "button",
|
|
691
|
+
"aria-haspopup": "listbox",
|
|
692
|
+
"aria-expanded": open,
|
|
693
|
+
onClick: () => setOpen((current) => !current),
|
|
694
|
+
className: "flex h-[50px] w-[70px] cursor-pointer items-center justify-between pl-[9px] pr-[12px] gap-1.5 rounded-[12px] border border-[#e0e0e0] bg-[#fdfdfd] shadow-[0_0_40px_0_rgba(0,0,0,0.06)]",
|
|
695
|
+
children: [
|
|
696
|
+
selected ? /* @__PURE__ */ jsx3("img", { src: selected.logo, alt: "", className: "size-7 rounded-[8px] object-cover" }) : /* @__PURE__ */ jsx3(ChainStack, { chains: previewChains, logoClassName: "size-[12px] rounded-[2px] object-cover" }),
|
|
697
|
+
/* @__PURE__ */ jsx3(IconChevron, { className: cx("size-2.5 text-black duration-150", open ? "-rotate-90" : "rotate-90") })
|
|
698
|
+
]
|
|
699
|
+
}
|
|
700
|
+
),
|
|
701
|
+
open && isDesktop ? /* @__PURE__ */ jsx3(
|
|
702
|
+
"div",
|
|
703
|
+
{
|
|
704
|
+
role: "listbox",
|
|
705
|
+
"aria-label": "Select network",
|
|
706
|
+
onKeyDown: (event) => {
|
|
707
|
+
if (event.key !== "Escape") return;
|
|
708
|
+
event.stopPropagation();
|
|
709
|
+
event.preventDefault();
|
|
710
|
+
setOpen(false);
|
|
711
|
+
},
|
|
712
|
+
className: "absolute top-[59px] right-0 z-20 flex max-h-[483px] w-[302px] flex-col rounded-[12px] border border-[#e0e0e0] bg-[#fdfdfd] p-4 shadow-[0_0_40px_0_rgba(0,0,0,0.06)]",
|
|
713
|
+
children: menu
|
|
714
|
+
}
|
|
715
|
+
) : null,
|
|
716
|
+
!isDesktop ? /* @__PURE__ */ jsx3(
|
|
717
|
+
Drawer,
|
|
718
|
+
{
|
|
719
|
+
open,
|
|
720
|
+
onClose: () => setOpen(false),
|
|
721
|
+
title: "Select Network",
|
|
722
|
+
titleClassName: cx("text-lg font-semibold text-black", fontSans),
|
|
723
|
+
cardClassName: "max-h-[80vh]",
|
|
724
|
+
contentClassName: "overflow-hidden",
|
|
725
|
+
children: /* @__PURE__ */ jsx3("div", { className: "flex h-[min(483px,60vh)] min-h-0 flex-col", children: menu })
|
|
726
|
+
}
|
|
727
|
+
) : null
|
|
728
|
+
] });
|
|
739
729
|
}
|
|
740
|
-
function
|
|
730
|
+
function ChainMenu(props) {
|
|
741
731
|
const {
|
|
742
|
-
|
|
743
|
-
walletConnected,
|
|
744
|
-
selection,
|
|
732
|
+
showAll,
|
|
745
733
|
chains,
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
734
|
+
previewChains,
|
|
735
|
+
dotted,
|
|
736
|
+
value,
|
|
737
|
+
query,
|
|
738
|
+
onQueryChange,
|
|
739
|
+
empty,
|
|
740
|
+
isDesktop,
|
|
741
|
+
reasonFor,
|
|
742
|
+
onSelect
|
|
755
743
|
} = props;
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
const selected = selection.kind === "chain" && selection.blockchain === chain.blockchain;
|
|
771
|
-
return /* @__PURE__ */ jsx4("span", { children: wrapDisabled(
|
|
772
|
-
disabled,
|
|
773
|
-
reason,
|
|
774
|
-
/* @__PURE__ */ jsxs3(
|
|
775
|
-
"button",
|
|
744
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
745
|
+
/* @__PURE__ */ jsx3(
|
|
746
|
+
SearchInput,
|
|
747
|
+
{
|
|
748
|
+
value: query,
|
|
749
|
+
onChange: onQueryChange,
|
|
750
|
+
placeholder: "search network",
|
|
751
|
+
iconClassName: SEARCH_ICON_CLASS,
|
|
752
|
+
inputClassName: cx(SEARCH_FIELD_CLASS, "pl-[43px]")
|
|
753
|
+
}
|
|
754
|
+
),
|
|
755
|
+
/* @__PURE__ */ jsxs("div", { className: cx("mt-2.5 min-h-0 flex-1 overflow-y-auto", thinScrollbar), children: [
|
|
756
|
+
showAll ? /* @__PURE__ */ jsx3(
|
|
757
|
+
ChainOption,
|
|
776
758
|
{
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
if (disabled) return;
|
|
782
|
-
onSelectChain(chain.blockchain);
|
|
783
|
-
},
|
|
784
|
-
className: chipClass(selected, disabled),
|
|
785
|
-
children: [
|
|
786
|
-
/* @__PURE__ */ jsx4("img", { src: chain.logo, alt: "", className: "size-8 object-cover" }),
|
|
787
|
-
fundedBlockchains.has(chain.blockchain) ? /* @__PURE__ */ jsx4("span", { className: "absolute top-1 right-1 size-2.5 rounded-full border border-white bg-[#06f]" }) : null
|
|
788
|
-
]
|
|
759
|
+
selected: value === ALL_CHAIN_FILTER,
|
|
760
|
+
onSelect: () => onSelect(ALL_CHAIN_FILTER),
|
|
761
|
+
label: "All",
|
|
762
|
+
children: /* @__PURE__ */ jsx3(ChainStack, { chains: previewChains, logoClassName: "size-[15px] rounded-[4px] object-cover" })
|
|
789
763
|
}
|
|
790
|
-
)
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
764
|
+
) : null,
|
|
765
|
+
chains.map((chain) => {
|
|
766
|
+
const reason = reasonFor(chain);
|
|
767
|
+
const disabled = Boolean(reason);
|
|
768
|
+
return /* @__PURE__ */ jsx3(
|
|
769
|
+
ChainOption,
|
|
770
|
+
{
|
|
771
|
+
selected: value === chain.blockchain,
|
|
772
|
+
disabled,
|
|
773
|
+
reason,
|
|
774
|
+
showReason: !isDesktop,
|
|
775
|
+
dotted: dotted.has(chain.blockchain),
|
|
776
|
+
onSelect: () => onSelect(chain.blockchain),
|
|
777
|
+
label: chain.chainName,
|
|
778
|
+
children: /* @__PURE__ */ jsx3("img", { src: chain.logo, alt: "", className: "size-8 rounded-[8px] object-cover" })
|
|
779
|
+
},
|
|
780
|
+
chain.blockchain
|
|
781
|
+
);
|
|
782
|
+
}),
|
|
783
|
+
empty ? /* @__PURE__ */ jsx3("p", { className: cx("px-[13px] py-4 text-[13px] text-[#606060]", fontSans), children: "No networks found" }) : null
|
|
784
|
+
] })
|
|
807
785
|
] });
|
|
808
786
|
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
var EASE = [0.32, 0.72, 0, 1];
|
|
814
|
-
var variants = {
|
|
815
|
-
enter: (direction) => ({ x: direction > 0 ? 24 : -24, opacity: 0 }),
|
|
816
|
-
center: { x: 0, opacity: 1 },
|
|
817
|
-
exit: (direction) => ({ x: direction > 0 ? -24 : 24, opacity: 0 })
|
|
818
|
-
};
|
|
819
|
-
function PaneTransition(props) {
|
|
820
|
-
const reduce = useReducedMotion();
|
|
821
|
-
if (reduce) {
|
|
822
|
-
return /* @__PURE__ */ jsx5("div", { className: "relative min-h-0 flex-1 overflow-hidden", children: props.children });
|
|
823
|
-
}
|
|
824
|
-
return /* @__PURE__ */ jsx5("div", { className: "relative min-h-0 flex-1 overflow-hidden", children: /* @__PURE__ */ jsx5(AnimatePresence, { initial: false, custom: props.direction, children: /* @__PURE__ */ jsx5(
|
|
825
|
-
motion.div,
|
|
787
|
+
function ChainOption(props) {
|
|
788
|
+
const { selected, disabled = false, reason, showReason = false, dotted = false, onSelect, label, children } = props;
|
|
789
|
+
const button = /* @__PURE__ */ jsxs(
|
|
790
|
+
"button",
|
|
826
791
|
{
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
className:
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
792
|
+
type: "button",
|
|
793
|
+
"aria-disabled": disabled || void 0,
|
|
794
|
+
onClick: () => {
|
|
795
|
+
if (disabled) return;
|
|
796
|
+
onSelect();
|
|
797
|
+
},
|
|
798
|
+
className: cx(
|
|
799
|
+
"flex w-full cursor-pointer items-center gap-3 rounded-[6px] border-0 bg-transparent px-1.5 py-1.5 text-left",
|
|
800
|
+
selected && "bg-[#f6f6f6]",
|
|
801
|
+
disabled && "cursor-not-allowed"
|
|
802
|
+
),
|
|
803
|
+
children: [
|
|
804
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
805
|
+
/* @__PURE__ */ jsxs("span", { className: cx("flex min-w-0 items-center gap-3", disabled && "opacity-40"), children: [
|
|
806
|
+
/* @__PURE__ */ jsx3("span", { className: "flex size-8 shrink-0 items-center justify-center", children }),
|
|
807
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
808
|
+
/* @__PURE__ */ jsx3("span", { className: cx("truncate text-sm font-medium text-black", fontSans), children: label }),
|
|
809
|
+
dotted ? /* @__PURE__ */ jsx3("span", { className: "size-2 shrink-0 rounded-full bg-[#6284f5]" }) : null
|
|
810
|
+
] })
|
|
811
|
+
] }),
|
|
812
|
+
disabled && showReason && reason ? /* @__PURE__ */ jsx3("span", { className: cx("mt-0.5 block pl-11 text-xs font-normal text-[#606060]", fontSans), children: reason }) : null
|
|
813
|
+
] }),
|
|
814
|
+
selected ? /* @__PURE__ */ jsx3(IconCheck, { className: "mr-1 size-2.5 shrink-0 text-black" }) : null
|
|
815
|
+
]
|
|
816
|
+
}
|
|
817
|
+
);
|
|
818
|
+
if (disabled && reason && !showReason) {
|
|
819
|
+
return /* @__PURE__ */ jsx3(Tooltip, { content: reason, triggerClassName: "flex w-full", children: button });
|
|
820
|
+
}
|
|
821
|
+
return button;
|
|
838
822
|
}
|
|
839
823
|
|
|
840
824
|
// src/token-select/prefs.ts
|
|
841
825
|
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
842
|
-
var EMPTY_PREFS = {
|
|
843
|
-
|
|
826
|
+
var EMPTY_PREFS = {
|
|
827
|
+
recentAssetIds: [],
|
|
828
|
+
recentSearchAssetIds: [],
|
|
829
|
+
recentBlockchains: []
|
|
830
|
+
};
|
|
831
|
+
function rememberId(recent, assetId, max) {
|
|
844
832
|
const id = assetId.trim();
|
|
845
833
|
if (!id) return recent;
|
|
846
|
-
return [id, ...recent.filter((item) => item !== id)].slice(0,
|
|
834
|
+
return [id, ...recent.filter((item) => item !== id)].slice(0, max);
|
|
835
|
+
}
|
|
836
|
+
function rememberRecentAsset(recent, assetId) {
|
|
837
|
+
return rememberId(recent, assetId, MAX_RECENT_HISTORY);
|
|
838
|
+
}
|
|
839
|
+
function rememberRecentSearch(recent, assetId) {
|
|
840
|
+
return rememberId(recent, assetId, MAX_RECENT_HISTORY);
|
|
841
|
+
}
|
|
842
|
+
function withoutAssetIds(recent, assetIds) {
|
|
843
|
+
const drop = new Set(assetIds);
|
|
844
|
+
return recent.filter((id) => !drop.has(id));
|
|
847
845
|
}
|
|
848
846
|
function rememberRecentBlockchain(recent, blockchain) {
|
|
849
847
|
const code = blockchain.trim();
|
|
850
848
|
if (!code) return recent;
|
|
851
849
|
return [code, ...recent.filter((item) => item !== code)].slice(0, MAX_RECENT_BLOCKCHAINS);
|
|
852
850
|
}
|
|
851
|
+
function cleanIds(value, max) {
|
|
852
|
+
if (!Array.isArray(value)) return [];
|
|
853
|
+
return value.filter((id) => typeof id === "string" && id.trim()).slice(0, max);
|
|
854
|
+
}
|
|
853
855
|
function migrateTokenSelectPrefs(persisted, version) {
|
|
854
856
|
const state = persisted ?? {};
|
|
855
|
-
const recentBlockchains = version >= 1 ?
|
|
856
|
-
const recentAssetIds = version >=
|
|
857
|
-
|
|
857
|
+
const recentBlockchains = version >= 1 ? cleanIds(state.recentBlockchains, MAX_RECENT_BLOCKCHAINS) : typeof state.lastBlockchain === "string" && state.lastBlockchain ? [state.lastBlockchain] : [];
|
|
858
|
+
const recentAssetIds = version >= 2 && Array.isArray(state.recentAssetIds) ? cleanIds(state.recentAssetIds, MAX_RECENT_HISTORY) : typeof state.lastAssetId === "string" && state.lastAssetId ? [state.lastAssetId] : [];
|
|
859
|
+
const recentSearchAssetIds = version >= TOKEN_SELECT_PREFS_VERSION ? cleanIds(state.recentSearchAssetIds, MAX_RECENT_HISTORY) : [];
|
|
860
|
+
return { recentAssetIds, recentSearchAssetIds, recentBlockchains };
|
|
858
861
|
}
|
|
859
862
|
function readStorage() {
|
|
860
863
|
if (typeof localStorage === "undefined") return EMPTY_PREFS;
|
|
@@ -892,10 +895,23 @@ function getTokenSelectPrefs() {
|
|
|
892
895
|
}
|
|
893
896
|
function setLastToken(assetId, blockchain) {
|
|
894
897
|
emit2({
|
|
898
|
+
...prefs,
|
|
895
899
|
recentAssetIds: rememberRecentAsset(prefs.recentAssetIds, assetId),
|
|
896
900
|
recentBlockchains: rememberRecentBlockchain(prefs.recentBlockchains, blockchain)
|
|
897
901
|
});
|
|
898
902
|
}
|
|
903
|
+
function setRecentSearch(assetId) {
|
|
904
|
+
emit2({
|
|
905
|
+
...prefs,
|
|
906
|
+
recentSearchAssetIds: rememberRecentSearch(prefs.recentSearchAssetIds, assetId)
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
function removeRecentSearches(assetIds) {
|
|
910
|
+
emit2({
|
|
911
|
+
...prefs,
|
|
912
|
+
recentSearchAssetIds: withoutAssetIds(prefs.recentSearchAssetIds, assetIds)
|
|
913
|
+
});
|
|
914
|
+
}
|
|
899
915
|
function setLastBlockchain(blockchain) {
|
|
900
916
|
emit2({
|
|
901
917
|
...prefs,
|
|
@@ -906,26 +922,25 @@ function useTokenSelectPrefs() {
|
|
|
906
922
|
return useSyncExternalStore2(subscribe2, getTokenSelectPrefs, getTokenSelectPrefs);
|
|
907
923
|
}
|
|
908
924
|
|
|
909
|
-
// src/token-select/
|
|
910
|
-
import { IconChevron as IconChevron2 } from "@stableflow/pay-ui/icons/chevron";
|
|
925
|
+
// src/token-select/recent-tiles.tsx
|
|
911
926
|
import { Skeleton } from "@stableflow/pay-ui/skeleton";
|
|
912
927
|
|
|
913
928
|
// src/token-select/lazy-image.tsx
|
|
914
|
-
import { useEffect as
|
|
929
|
+
import { useEffect as useEffect4, useRef as useRef2, useState as useState3 } from "react";
|
|
915
930
|
import { useInView } from "motion/react";
|
|
916
|
-
import { jsx as
|
|
931
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
917
932
|
function LazyImage(props) {
|
|
918
933
|
const { src, fallbackSrc, alt = "", className } = props;
|
|
919
|
-
const ref =
|
|
934
|
+
const ref = useRef2(null);
|
|
920
935
|
const inView = useInView(ref, { once: true });
|
|
921
|
-
const [failedSrc, setFailedSrc] =
|
|
922
|
-
|
|
936
|
+
const [failedSrc, setFailedSrc] = useState3(null);
|
|
937
|
+
useEffect4(() => {
|
|
923
938
|
setFailedSrc(null);
|
|
924
939
|
}, [src]);
|
|
925
940
|
const requested = src.trim();
|
|
926
941
|
const useFallback = requested.length === 0 || failedSrc === requested;
|
|
927
942
|
const shown = useFallback ? fallbackSrc : requested;
|
|
928
|
-
return /* @__PURE__ */
|
|
943
|
+
return /* @__PURE__ */ jsx4("span", { ref, className: "block size-full", children: inView ? /* @__PURE__ */ jsx4(
|
|
929
944
|
"img",
|
|
930
945
|
{
|
|
931
946
|
src: shown,
|
|
@@ -981,37 +996,94 @@ function tokenLogoUrl(symbol) {
|
|
|
981
996
|
return logoPath(`/stableflow/tokens/${file}.png`);
|
|
982
997
|
}
|
|
983
998
|
|
|
999
|
+
// src/token-select/recent-tiles.tsx
|
|
1000
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1001
|
+
function RecentTiles(props) {
|
|
1002
|
+
const { tokens, onSelect, isTokenDisabled } = props;
|
|
1003
|
+
if (tokens.length === 0) return null;
|
|
1004
|
+
return /* @__PURE__ */ jsx5("div", { className: "grid grid-cols-5 gap-2 px-5 md:gap-3", children: tokens.map((token) => {
|
|
1005
|
+
const disabled = Boolean(isTokenDisabled?.(token));
|
|
1006
|
+
return /* @__PURE__ */ jsxs2(
|
|
1007
|
+
"button",
|
|
1008
|
+
{
|
|
1009
|
+
type: "button",
|
|
1010
|
+
disabled,
|
|
1011
|
+
onClick: () => onSelect(token),
|
|
1012
|
+
className: cx(
|
|
1013
|
+
"flex h-[72px] cursor-pointer flex-col items-center justify-center gap-1 rounded-[12px] border-0 bg-[#f6f6f6] px-1 hover:bg-[#ededed]",
|
|
1014
|
+
disabled && "cursor-not-allowed opacity-40 hover:bg-[#f6f6f6]"
|
|
1015
|
+
),
|
|
1016
|
+
children: [
|
|
1017
|
+
/* @__PURE__ */ jsxs2("span", { className: "relative size-[26px] shrink-0", children: [
|
|
1018
|
+
/* @__PURE__ */ jsx5(
|
|
1019
|
+
LazyImage,
|
|
1020
|
+
{
|
|
1021
|
+
src: token.logo,
|
|
1022
|
+
fallbackSrc: DEFAULT_TOKEN_LOGO,
|
|
1023
|
+
className: "size-[26px] rounded-[12px] object-cover"
|
|
1024
|
+
}
|
|
1025
|
+
),
|
|
1026
|
+
/* @__PURE__ */ jsx5(
|
|
1027
|
+
"img",
|
|
1028
|
+
{
|
|
1029
|
+
src: token.chain.logo,
|
|
1030
|
+
alt: "",
|
|
1031
|
+
className: "absolute -right-1 -bottom-1 size-3 rounded-[4px] border border-white object-cover"
|
|
1032
|
+
}
|
|
1033
|
+
)
|
|
1034
|
+
] }),
|
|
1035
|
+
/* @__PURE__ */ jsx5("span", { className: cx("max-w-full truncate text-sm font-semibold text-black", fontSans), children: token.symbol })
|
|
1036
|
+
]
|
|
1037
|
+
},
|
|
1038
|
+
token.assetId
|
|
1039
|
+
);
|
|
1040
|
+
}) });
|
|
1041
|
+
}
|
|
1042
|
+
function RecentTileSkeletons() {
|
|
1043
|
+
return /* @__PURE__ */ jsx5("div", { className: "grid grid-cols-5 gap-2 px-5 md:gap-3", "aria-hidden": true, children: Array.from({ length: 5 }, (_, index) => /* @__PURE__ */ jsx5(Skeleton, { className: "h-[72px] rounded-[12px]" }, index)) });
|
|
1044
|
+
}
|
|
1045
|
+
|
|
984
1046
|
// src/token-select/token-pane.tsx
|
|
985
|
-
import {
|
|
1047
|
+
import { IconDatabase } from "@stableflow/pay-ui/icons/solid/database";
|
|
1048
|
+
import { IconDuration } from "@stableflow/pay-ui/icons/solid/duration";
|
|
1049
|
+
import { IconTrends } from "@stableflow/pay-ui/icons/outline/trends";
|
|
1050
|
+
import { Skeleton as Skeleton2 } from "@stableflow/pay-ui/skeleton";
|
|
1051
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
986
1052
|
function TokenPane(props) {
|
|
987
1053
|
const {
|
|
988
1054
|
sections,
|
|
989
1055
|
selectedAssetId,
|
|
990
|
-
loading,
|
|
991
1056
|
showBalances = false,
|
|
992
|
-
showWalletStatus = true,
|
|
993
|
-
header = null,
|
|
994
1057
|
getBalance,
|
|
995
1058
|
isBalanceLoading,
|
|
996
1059
|
onSelectToken,
|
|
997
1060
|
isTokenDisabled,
|
|
998
|
-
rowClassName
|
|
1061
|
+
rowClassName,
|
|
1062
|
+
emptyLabel = null
|
|
999
1063
|
} = props;
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1064
|
+
return /* @__PURE__ */ jsx6("div", { className: cx("min-h-0 flex-1 overflow-y-auto", thinScrollbar), children: /* @__PURE__ */ jsxs3("div", { className: "px-3 pt-3 pb-3", children: [
|
|
1065
|
+
sections.map((section) => /* @__PURE__ */ jsxs3("section", { className: "mb-2", children: [
|
|
1066
|
+
section.title ? /* @__PURE__ */ jsxs3("div", { className: "mb-1 flex items-center justify-between gap-2 px-[13px]", children: [
|
|
1067
|
+
/* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center gap-2 text-[#aaa]", children: [
|
|
1068
|
+
/* @__PURE__ */ jsx6(SectionIcon, { icon: section.icon }),
|
|
1069
|
+
/* @__PURE__ */ jsx6("span", { className: cx("truncate text-sm font-medium text-[#aaa]", fontSans), children: section.title })
|
|
1070
|
+
] }),
|
|
1071
|
+
section.action ? /* @__PURE__ */ jsx6(
|
|
1072
|
+
"button",
|
|
1073
|
+
{
|
|
1074
|
+
type: "button",
|
|
1075
|
+
onClick: section.action.onClick,
|
|
1076
|
+
className: cx("cursor-pointer border-0 bg-transparent p-0 text-sm font-medium text-[#aaa]", fontSans),
|
|
1077
|
+
children: section.action.label
|
|
1078
|
+
}
|
|
1079
|
+
) : null
|
|
1008
1080
|
] }) : null,
|
|
1009
|
-
section.
|
|
1081
|
+
section.skeletonRows ? /* @__PURE__ */ jsx6(TokenListSkeleton, { rows: section.skeletonRows }) : null,
|
|
1082
|
+
section.tokens.map((token) => /* @__PURE__ */ jsx6(
|
|
1010
1083
|
TokenRow,
|
|
1011
1084
|
{
|
|
1012
1085
|
token,
|
|
1013
1086
|
selected: token.assetId === selectedAssetId,
|
|
1014
|
-
recent: token.assetId === section.badgeAssetId,
|
|
1015
1087
|
showBalances,
|
|
1016
1088
|
formatted: showBalances ? getBalance(token) : null,
|
|
1017
1089
|
loadingBalance: showBalances && isBalanceLoading(token),
|
|
@@ -1022,57 +1094,43 @@ function TokenPane(props) {
|
|
|
1022
1094
|
`${section.id}-${token.assetId}`
|
|
1023
1095
|
))
|
|
1024
1096
|
] }, section.id)),
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
return /* @__PURE__ */
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
/* @__PURE__ */ jsx7(IconChevron2, { className: "rotate-180 text-[#aaa]" }),
|
|
1041
|
-
/* @__PURE__ */ jsx7("span", { className: "truncate", children: header.title })
|
|
1042
|
-
]
|
|
1043
|
-
}
|
|
1044
|
-
) : /* @__PURE__ */ jsx7("p", { className: cx("min-w-0 truncate text-sm font-medium text-[#aaa]", fontSans), children: header.title }),
|
|
1045
|
-
showWalletStatus && walletKind ? /* @__PURE__ */ jsx7(ChainWalletStatus, { kind: walletKind }) : null
|
|
1046
|
-
] });
|
|
1047
|
-
}
|
|
1048
|
-
function TokenListSkeleton() {
|
|
1049
|
-
return /* @__PURE__ */ jsx7("div", { "aria-hidden": true, children: Array.from({ length: 6 }, (_, index) => /* @__PURE__ */ jsxs4("div", { className: "flex h-[66px] items-center gap-2.5 px-3.5", children: [
|
|
1050
|
-
/* @__PURE__ */ jsx7(Skeleton, { className: "size-8 shrink-0 rounded-full" }),
|
|
1051
|
-
/* @__PURE__ */ jsxs4("span", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [
|
|
1052
|
-
/* @__PURE__ */ jsx7(Skeleton, { className: "h-3.5 w-24" }),
|
|
1053
|
-
/* @__PURE__ */ jsx7(Skeleton, { className: "h-3 w-16" })
|
|
1097
|
+
emptyLabel ? /* @__PURE__ */ jsx6("p", { className: cx("px-[13px] py-4 text-[13px] text-[#606060]", fontSans), children: emptyLabel }) : null
|
|
1098
|
+
] }) });
|
|
1099
|
+
}
|
|
1100
|
+
function SectionIcon(props) {
|
|
1101
|
+
const className = "size-3.5 text-[#aaa]";
|
|
1102
|
+
if (props.icon === "database") return /* @__PURE__ */ jsx6(IconDatabase, { className });
|
|
1103
|
+
if (props.icon === "duration") return /* @__PURE__ */ jsx6(IconDuration, { className });
|
|
1104
|
+
return /* @__PURE__ */ jsx6(IconTrends, { className });
|
|
1105
|
+
}
|
|
1106
|
+
function TokenListSkeleton(props) {
|
|
1107
|
+
return /* @__PURE__ */ jsx6("div", { "aria-hidden": true, children: Array.from({ length: props.rows }, (_, index) => /* @__PURE__ */ jsxs3("div", { className: "flex h-[66px] items-center gap-2.5 px-[13px]", children: [
|
|
1108
|
+
/* @__PURE__ */ jsx6(Skeleton2, { className: "size-8 shrink-0 rounded-full" }),
|
|
1109
|
+
/* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [
|
|
1110
|
+
/* @__PURE__ */ jsx6(Skeleton2, { className: "h-3.5 w-24" }),
|
|
1111
|
+
/* @__PURE__ */ jsx6(Skeleton2, { className: "h-3 w-16" })
|
|
1054
1112
|
] })
|
|
1055
1113
|
] }, index)) });
|
|
1056
1114
|
}
|
|
1057
1115
|
function TokenRow(props) {
|
|
1058
|
-
const { token, selected,
|
|
1116
|
+
const { token, selected, showBalances, formatted, loadingBalance, disabled, onSelect, className } = props;
|
|
1059
1117
|
const usd = showBalances && !loadingBalance && formatted != null ? tokenBalanceUsd(token, formatted) : -1;
|
|
1060
|
-
return /* @__PURE__ */
|
|
1118
|
+
return /* @__PURE__ */ jsxs3(
|
|
1061
1119
|
"button",
|
|
1062
1120
|
{
|
|
1063
1121
|
type: "button",
|
|
1064
1122
|
disabled,
|
|
1065
1123
|
onClick: onSelect,
|
|
1066
1124
|
className: cx(
|
|
1067
|
-
"flex h-[66px] w-full cursor-pointer items-center justify-between gap-2 rounded-[12px] border-0 bg-transparent px-
|
|
1125
|
+
"flex h-[66px] w-full cursor-pointer items-center justify-between gap-2 rounded-[12px] border-0 bg-transparent px-[13px] text-left hover:bg-[#f6f6f6]",
|
|
1068
1126
|
selected && "bg-[#f6f6f6]",
|
|
1069
1127
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent",
|
|
1070
1128
|
className
|
|
1071
1129
|
),
|
|
1072
1130
|
children: [
|
|
1073
|
-
/* @__PURE__ */
|
|
1074
|
-
/* @__PURE__ */
|
|
1075
|
-
/* @__PURE__ */
|
|
1131
|
+
/* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
1132
|
+
/* @__PURE__ */ jsxs3("span", { className: "relative size-8 shrink-0", children: [
|
|
1133
|
+
/* @__PURE__ */ jsx6(
|
|
1076
1134
|
LazyImage,
|
|
1077
1135
|
{
|
|
1078
1136
|
src: token.logo,
|
|
@@ -1080,7 +1138,7 @@ function TokenRow(props) {
|
|
|
1080
1138
|
className: "size-8 rounded-[12px] object-cover"
|
|
1081
1139
|
}
|
|
1082
1140
|
),
|
|
1083
|
-
/* @__PURE__ */
|
|
1141
|
+
/* @__PURE__ */ jsx6(
|
|
1084
1142
|
"img",
|
|
1085
1143
|
{
|
|
1086
1144
|
src: token.chain.logo,
|
|
@@ -1089,69 +1147,58 @@ function TokenRow(props) {
|
|
|
1089
1147
|
}
|
|
1090
1148
|
)
|
|
1091
1149
|
] }),
|
|
1092
|
-
/* @__PURE__ */
|
|
1093
|
-
/* @__PURE__ */
|
|
1094
|
-
|
|
1095
|
-
recent ? /* @__PURE__ */ jsx7("span", { className: cx("shrink-0 rounded-[9px] bg-[#06f]/10 px-1.5 text-[10px] font-medium leading-[18px] text-[#06f]", fontSans), children: "Recently Used" }) : null
|
|
1096
|
-
] }),
|
|
1097
|
-
/* @__PURE__ */ jsx7("span", { className: cx("mt-0.5 block truncate text-xs text-[#606060]", fontSans), children: token.chain.chainName })
|
|
1150
|
+
/* @__PURE__ */ jsxs3("span", { className: "min-w-0", children: [
|
|
1151
|
+
/* @__PURE__ */ jsx6("span", { className: cx("block truncate text-sm font-semibold text-black", fontSans), children: token.symbol }),
|
|
1152
|
+
/* @__PURE__ */ jsx6("span", { className: cx("mt-0.5 block truncate text-xs text-[#606060]", fontSans), children: token.chain.chainName })
|
|
1098
1153
|
] })
|
|
1099
1154
|
] }),
|
|
1100
|
-
showBalances ? /* @__PURE__ */
|
|
1155
|
+
showBalances ? /* @__PURE__ */ jsx6("span", { className: "shrink-0 text-right", children: loadingBalance ? /* @__PURE__ */ jsx6(
|
|
1101
1156
|
"span",
|
|
1102
1157
|
{
|
|
1103
1158
|
className: "inline-block size-3.5 animate-spin rounded-full border-2 border-[#606060] border-r-transparent",
|
|
1104
1159
|
"aria-label": "Loading balance"
|
|
1105
1160
|
}
|
|
1106
|
-
) : formatted != null ? /* @__PURE__ */
|
|
1107
|
-
/* @__PURE__ */
|
|
1108
|
-
usd >= 0 ? /* @__PURE__ */
|
|
1109
|
-
] }) : /* @__PURE__ */
|
|
1161
|
+
) : formatted != null ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1162
|
+
/* @__PURE__ */ jsx6("span", { className: cx("block text-sm font-medium text-black", fontSans), children: formatDisplayAmount(formatted, { prefix: "", maxDecimals: 4 }) }),
|
|
1163
|
+
usd >= 0 ? /* @__PURE__ */ jsx6("span", { className: cx("block text-xs text-[#606060]", fontSans), children: formatDisplayAmount(usd, { prefix: "$", showDust: true }) }) : null
|
|
1164
|
+
] }) : /* @__PURE__ */ jsx6("span", { className: cx("text-sm font-medium text-black", fontSans), children: "-" }) }) : null
|
|
1110
1165
|
]
|
|
1111
1166
|
}
|
|
1112
1167
|
);
|
|
1113
1168
|
}
|
|
1114
1169
|
|
|
1115
1170
|
// src/token-select/search-results.tsx
|
|
1116
|
-
import { jsx as
|
|
1171
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1117
1172
|
function SearchResults(props) {
|
|
1118
1173
|
const {
|
|
1119
|
-
|
|
1174
|
+
tokens,
|
|
1120
1175
|
selectedAssetId,
|
|
1121
1176
|
loading,
|
|
1122
1177
|
showBalances = false,
|
|
1123
|
-
showWalletStatus = true,
|
|
1124
1178
|
getBalance,
|
|
1125
1179
|
isBalanceLoading,
|
|
1126
1180
|
onSelectToken,
|
|
1127
1181
|
isTokenDisabled,
|
|
1128
1182
|
rowClassName
|
|
1129
1183
|
} = props;
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
className: rowClassName
|
|
1149
|
-
},
|
|
1150
|
-
token.assetId
|
|
1151
|
-
))
|
|
1152
|
-
] }, group.blockchain)),
|
|
1153
|
-
!loading && !hasTokens ? /* @__PURE__ */ jsx8("p", { className: cx("px-3.5 py-4 text-[13px] text-[#606060]", fontSans), children: "No tokens found" }) : null
|
|
1154
|
-
] }) }) });
|
|
1184
|
+
return /* @__PURE__ */ jsx7("div", { className: cx("min-h-0 flex-1 overflow-y-auto", thinScrollbar), children: /* @__PURE__ */ jsxs4("div", { className: "px-3 pt-3 pb-3", children: [
|
|
1185
|
+
loading && tokens.length === 0 ? /* @__PURE__ */ jsx7(TokenListSkeleton, { rows: 6 }) : null,
|
|
1186
|
+
tokens.map((token) => /* @__PURE__ */ jsx7(
|
|
1187
|
+
TokenRow,
|
|
1188
|
+
{
|
|
1189
|
+
token,
|
|
1190
|
+
selected: token.assetId === selectedAssetId,
|
|
1191
|
+
showBalances,
|
|
1192
|
+
formatted: showBalances ? getBalance(token) : null,
|
|
1193
|
+
loadingBalance: showBalances && isBalanceLoading(token),
|
|
1194
|
+
disabled: Boolean(isTokenDisabled?.(token)),
|
|
1195
|
+
onSelect: () => onSelectToken(token),
|
|
1196
|
+
className: rowClassName
|
|
1197
|
+
},
|
|
1198
|
+
token.assetId
|
|
1199
|
+
)),
|
|
1200
|
+
!loading && tokens.length === 0 ? /* @__PURE__ */ jsx7("p", { className: cx("px-[13px] py-4 text-[13px] text-[#606060]", fontSans), children: "No tokens found" }) : null
|
|
1201
|
+
] }) });
|
|
1155
1202
|
}
|
|
1156
1203
|
|
|
1157
1204
|
// src/token-select/types.ts
|
|
@@ -1161,8 +1208,9 @@ function ownerKey2(owners) {
|
|
|
1161
1208
|
}
|
|
1162
1209
|
|
|
1163
1210
|
// src/token-select/TokenSelectDialog.tsx
|
|
1164
|
-
import { jsx as
|
|
1165
|
-
var
|
|
1211
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1212
|
+
var TOKEN_SEARCH_CLASS = "h-[50px] rounded-[12px] border-[#e3e3e3] bg-[#f6f6f6] pl-[43px] text-sm placeholder:text-black/30";
|
|
1213
|
+
var TOKEN_SEARCH_ICON_CLASS = "left-4 size-[19px] text-black";
|
|
1166
1214
|
function ownerForToken(owners, token) {
|
|
1167
1215
|
return owners[token.chain.chainKind] ?? null;
|
|
1168
1216
|
}
|
|
@@ -1173,15 +1221,6 @@ function isNativeToken(token) {
|
|
|
1173
1221
|
const addr = String(token.contractAddress || "").trim().toLowerCase();
|
|
1174
1222
|
return !addr || addr === "native" || addr === "0x0000000000000000000000000000000000000000";
|
|
1175
1223
|
}
|
|
1176
|
-
function railSelection(view) {
|
|
1177
|
-
if (view.kind === "wallet") return { kind: "wallet" };
|
|
1178
|
-
if (view.kind === "all") return { kind: "all" };
|
|
1179
|
-
if (view.kind === "rail-chain") return { kind: "chain", blockchain: view.blockchain };
|
|
1180
|
-
return { kind: "networks" };
|
|
1181
|
-
}
|
|
1182
|
-
function chainByCode(chains, blockchain) {
|
|
1183
|
-
return chains.find((chain) => chain.blockchain === blockchain);
|
|
1184
|
-
}
|
|
1185
1224
|
function TokenSelectDialog(props) {
|
|
1186
1225
|
const {
|
|
1187
1226
|
open,
|
|
@@ -1202,14 +1241,12 @@ function TokenSelectDialog(props) {
|
|
|
1202
1241
|
closeClassName,
|
|
1203
1242
|
contentClassName,
|
|
1204
1243
|
searchClassName,
|
|
1205
|
-
railClassName,
|
|
1206
1244
|
rowClassName
|
|
1207
1245
|
} = props;
|
|
1208
1246
|
const payer = role === "payer";
|
|
1209
1247
|
const showBalances = payer;
|
|
1210
1248
|
const {
|
|
1211
1249
|
wallet,
|
|
1212
|
-
popularTokens: popularRefs,
|
|
1213
1250
|
tokens,
|
|
1214
1251
|
loading,
|
|
1215
1252
|
stableSymbols,
|
|
@@ -1231,47 +1268,26 @@ function TokenSelectDialog(props) {
|
|
|
1231
1268
|
() => showBalances ? { ...connectedOwners, ...balanceOwners } : {},
|
|
1232
1269
|
[showBalances, connectedOwners, balanceOwners]
|
|
1233
1270
|
);
|
|
1234
|
-
const
|
|
1235
|
-
const [
|
|
1236
|
-
const
|
|
1237
|
-
const
|
|
1238
|
-
const
|
|
1239
|
-
const savedNetworksScroll = useRef2(0);
|
|
1240
|
-
const walletConnectedRef = useRef2(walletConnected);
|
|
1241
|
-
const payerRef = useRef2(payer);
|
|
1242
|
-
const lockRef = useRef2(lockChainKind);
|
|
1243
|
-
const tokensRef = useRef2(tokens);
|
|
1244
|
-
walletConnectedRef.current = walletConnected;
|
|
1245
|
-
payerRef.current = payer;
|
|
1271
|
+
const [search, setSearch] = useState4("");
|
|
1272
|
+
const [chainFilter, setChainFilter] = useState4(ALL_CHAIN_FILTER);
|
|
1273
|
+
const userPickedChain = useRef3(false);
|
|
1274
|
+
const lockRef = useRef3(lockChainKind);
|
|
1275
|
+
const tokensRef = useRef3(tokens);
|
|
1246
1276
|
lockRef.current = lockChainKind;
|
|
1247
1277
|
tokensRef.current = tokens;
|
|
1248
|
-
|
|
1278
|
+
useEffect5(() => {
|
|
1249
1279
|
if (!open) return;
|
|
1280
|
+
userPickedChain.current = false;
|
|
1250
1281
|
setSearch("");
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
chainsFromTokens(tokensRef.current)
|
|
1257
|
-
);
|
|
1258
|
-
if (filter !== ALL_CHAIN_FILTER) {
|
|
1259
|
-
setView({ kind: "rail-chain", blockchain: filter });
|
|
1260
|
-
return;
|
|
1261
|
-
}
|
|
1262
|
-
return;
|
|
1263
|
-
}
|
|
1264
|
-
if (!payerRef.current) {
|
|
1265
|
-
setView({ kind: "all" });
|
|
1266
|
-
return;
|
|
1267
|
-
}
|
|
1268
|
-
setView(walletConnectedRef.current ? { kind: "wallet" } : { kind: "networks" });
|
|
1282
|
+
setChainFilter(initialChainFilter(
|
|
1283
|
+
lockRef.current,
|
|
1284
|
+
getTokenSelectPrefs().recentBlockchains,
|
|
1285
|
+
chainsFromTokens(tokensRef.current)
|
|
1286
|
+
));
|
|
1269
1287
|
}, [open]);
|
|
1270
|
-
|
|
1271
|
-
if (!open || !lockChainKind) return;
|
|
1272
|
-
|
|
1273
|
-
if (filter === ALL_CHAIN_FILTER) return;
|
|
1274
|
-
setView((current) => current.kind === "rail-chain" ? current : { kind: "rail-chain", blockchain: filter });
|
|
1288
|
+
useEffect5(() => {
|
|
1289
|
+
if (!open || !lockChainKind || userPickedChain.current) return;
|
|
1290
|
+
setChainFilter(initialChainFilter(lockChainKind, getTokenSelectPrefs().recentBlockchains, chainsFromTokens(tokens)));
|
|
1275
1291
|
}, [open, lockChainKind, tokens]);
|
|
1276
1292
|
const allowed = useMemo(() => {
|
|
1277
1293
|
if (!allowedBlockchains || allowedBlockchains.length === 0) return null;
|
|
@@ -1288,11 +1304,11 @@ function TokenSelectDialog(props) {
|
|
|
1288
1304
|
}, [tokens, allowed, excludeNative, payer]);
|
|
1289
1305
|
const ownersKey = ownerKey2(owners);
|
|
1290
1306
|
const tokenKey = useMemo(() => scopedTokens.map((token) => token.assetId).join("|"), [scopedTokens]);
|
|
1291
|
-
const ownersRef =
|
|
1292
|
-
const scopedRef =
|
|
1307
|
+
const ownersRef = useRef3(owners);
|
|
1308
|
+
const scopedRef = useRef3(scopedTokens);
|
|
1293
1309
|
ownersRef.current = owners;
|
|
1294
1310
|
scopedRef.current = scopedTokens;
|
|
1295
|
-
|
|
1311
|
+
useEffect5(() => {
|
|
1296
1312
|
if (balanceMode !== "async" || !showBalances || !open || !hasAnyOwner(ownersRef.current) || !tokenKey) return;
|
|
1297
1313
|
void ensurePayTokenBalances(ownersRef.current, scopedRef.current);
|
|
1298
1314
|
const id = window.setInterval(() => {
|
|
@@ -1321,6 +1337,10 @@ function TokenSelectDialog(props) {
|
|
|
1321
1337
|
return !entry || entry.status === "loading";
|
|
1322
1338
|
}
|
|
1323
1339
|
const availableChains = useMemo(() => chainsFromTokens(scopedTokens), [scopedTokens]);
|
|
1340
|
+
const rangeTokens = useMemo(
|
|
1341
|
+
() => scopedTokens.filter((token) => matchesChainFilter(token, chainFilter)),
|
|
1342
|
+
[scopedTokens, chainFilter]
|
|
1343
|
+
);
|
|
1324
1344
|
const fundedBlockchains = useMemo(() => {
|
|
1325
1345
|
const funded = /* @__PURE__ */ new Set();
|
|
1326
1346
|
if (!showBalances) return funded;
|
|
@@ -1331,253 +1351,208 @@ function TokenSelectDialog(props) {
|
|
|
1331
1351
|
}
|
|
1332
1352
|
return funded;
|
|
1333
1353
|
}, [availableChains, owners, scopedTokens, showBalances, balanceEntries, balanceMode, syncGetBalance, syncIsBalanceLoading]);
|
|
1334
|
-
const
|
|
1335
|
-
if (!payer) return
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
setView((current) => {
|
|
1346
|
-
if (current.kind === "wallet" && !walletConnected) return { kind: "networks" };
|
|
1347
|
-
if (current.kind === "rail-chain" && !railChains.some((chain) => chain.blockchain === current.blockchain)) {
|
|
1348
|
-
return walletConnected ? { kind: "wallet" } : { kind: "networks" };
|
|
1349
|
-
}
|
|
1350
|
-
return current;
|
|
1351
|
-
});
|
|
1352
|
-
}, [open, payer, lockChainKind, walletConnected, railChains]);
|
|
1353
|
-
const popularTokens = useMemo(
|
|
1354
|
-
() => popularTokensForWallets(scopedTokens, popularRefs, (kind) => Boolean(connectedOwners[kind])),
|
|
1355
|
-
[scopedTokens, popularRefs, connectedOwners]
|
|
1356
|
-
);
|
|
1357
|
-
const newestAssetId = showBalances ? prefs2.recentAssetIds[0] ?? null : null;
|
|
1354
|
+
const dottedChains = useMemo(() => {
|
|
1355
|
+
if (!payer) return [];
|
|
1356
|
+
return payerRailChains(availableChains, owners, fundedBlockchains);
|
|
1357
|
+
}, [payer, availableChains, owners, fundedBlockchains]);
|
|
1358
|
+
const dottedSet = useMemo(() => new Set(dottedChains.map((chain) => chain.blockchain)), [dottedChains]);
|
|
1359
|
+
const menuChains = useMemo(() => chainMenuOrder(availableChains, scopedTokens, {
|
|
1360
|
+
dotted: dottedSet,
|
|
1361
|
+
showBalances,
|
|
1362
|
+
getBalanceUsd: (token) => tokenBalanceUsd(token, balanceOf(token))
|
|
1363
|
+
}), [availableChains, scopedTokens, dottedSet, showBalances, balanceEntries, owners, balanceMode, syncGetBalance, syncIsBalanceLoading]);
|
|
1364
|
+
const previewChains = useMemo(() => allChainPreview(availableChains), [availableChains]);
|
|
1358
1365
|
const searching = search.trim().length > 0;
|
|
1359
|
-
const
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
if (
|
|
1376
|
-
|
|
1377
|
-
}
|
|
1378
|
-
return next;
|
|
1379
|
-
}
|
|
1380
|
-
if (view.kind === "all") {
|
|
1381
|
-
const next = [];
|
|
1382
|
-
if (popularTokens.length > 0) {
|
|
1383
|
-
next.push({ id: "popular", title: POPULAR_SECTION_TITLE, tokens: popularTokens });
|
|
1384
|
-
}
|
|
1385
|
-
const sorted = scopedTokens.slice().sort((left, right) => compareTokensByPriority(left, right, stableSymbols));
|
|
1386
|
-
next.push({ id: "all", tokens: sorted });
|
|
1387
|
-
return next;
|
|
1388
|
-
}
|
|
1389
|
-
if (view.kind === "rail-chain" || view.kind === "network-chain") {
|
|
1390
|
-
const matched = scopedTokens.filter((token) => token.blockchain === view.blockchain);
|
|
1391
|
-
if (!payer) {
|
|
1392
|
-
const next = [];
|
|
1393
|
-
const popular = popularTokens.filter((token) => token.blockchain === view.blockchain);
|
|
1394
|
-
if (popular.length > 0) {
|
|
1395
|
-
next.push({ id: "popular", title: POPULAR_SECTION_TITLE, tokens: popular });
|
|
1396
|
-
}
|
|
1397
|
-
next.push({
|
|
1398
|
-
id: view.blockchain,
|
|
1399
|
-
tokens: matched.slice().sort((left, right) => compareTokensByPriority(left, right, stableSymbols))
|
|
1400
|
-
});
|
|
1401
|
-
return next;
|
|
1366
|
+
const rangeWalletConnected = rangeTokens.some((token) => Boolean(owners[token.chain.chainKind]));
|
|
1367
|
+
const recentTokens = useMemo(
|
|
1368
|
+
() => recentTokensInOrder(rangeTokens, prefs2.recentAssetIds).slice(0, MAX_RECENTLY_USED),
|
|
1369
|
+
[rangeTokens, prefs2.recentAssetIds]
|
|
1370
|
+
);
|
|
1371
|
+
const recentSearches = useMemo(
|
|
1372
|
+
() => recentTokensInOrder(rangeTokens, prefs2.recentSearchAssetIds).slice(0, MAX_RECENT_SEARCHES),
|
|
1373
|
+
[rangeTokens, prefs2.recentSearchAssetIds]
|
|
1374
|
+
);
|
|
1375
|
+
const yours = useMemo(() => {
|
|
1376
|
+
if (!payer || !rangeWalletConnected) return [];
|
|
1377
|
+
return positiveBalanceTokens(rangeTokens, usdOf);
|
|
1378
|
+
}, [payer, rangeWalletConnected, rangeTokens, owners, balanceEntries, balanceMode, syncGetBalance, syncIsBalanceLoading]);
|
|
1379
|
+
const trends = useMemo(() => trendTokensIn(rangeTokens, {
|
|
1380
|
+
chainFilter,
|
|
1381
|
+
sortRest: (rest) => {
|
|
1382
|
+
if (chainFilter === ALL_CHAIN_FILTER) {
|
|
1383
|
+
return rest.slice().sort((left, right) => compareTokensByPriority(left, right, stableSymbols));
|
|
1402
1384
|
}
|
|
1403
|
-
const chain =
|
|
1404
|
-
return
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
stableSymbols
|
|
1411
|
-
}),
|
|
1412
|
-
badgeAssetId: newestAssetId
|
|
1413
|
-
}];
|
|
1385
|
+
const chain = availableChains.find((item) => item.blockchain === chainFilter);
|
|
1386
|
+
return sortTokensForChain(rest, {
|
|
1387
|
+
withBalances: Boolean(chain && owners[chain.chainKind]),
|
|
1388
|
+
usdOf,
|
|
1389
|
+
loadingOf,
|
|
1390
|
+
stableSymbols
|
|
1391
|
+
});
|
|
1414
1392
|
}
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
newestAssetId,
|
|
1422
|
-
balanceEntries,
|
|
1423
|
-
owners,
|
|
1424
|
-
popularTokens,
|
|
1425
|
-
availableChains,
|
|
1426
|
-
stableSymbols,
|
|
1427
|
-
balanceMode,
|
|
1428
|
-
syncGetBalance,
|
|
1429
|
-
syncIsBalanceLoading
|
|
1430
|
-
]);
|
|
1431
|
-
const searchGroups = useMemo(() => {
|
|
1393
|
+
}), [rangeTokens, chainFilter, availableChains, owners, stableSymbols, balanceEntries, balanceMode, syncGetBalance, syncIsBalanceLoading]);
|
|
1394
|
+
const receiverTokens = useMemo(
|
|
1395
|
+
() => rangeTokens.slice().sort((left, right) => compareTokensByPriority(left, right, stableSymbols)),
|
|
1396
|
+
[rangeTokens, stableSymbols]
|
|
1397
|
+
);
|
|
1398
|
+
const results = useMemo(() => {
|
|
1432
1399
|
if (!searching) return [];
|
|
1433
|
-
return
|
|
1400
|
+
return searchTokens(rangeTokens, search, {
|
|
1434
1401
|
role: payer ? "payer" : "receiver",
|
|
1435
1402
|
usdOf,
|
|
1436
|
-
loadingOf
|
|
1437
|
-
hasOwner: (kind) => Boolean(owners[kind]),
|
|
1438
|
-
stableSymbols
|
|
1403
|
+
loadingOf
|
|
1439
1404
|
});
|
|
1440
|
-
}, [searching,
|
|
1441
|
-
function
|
|
1442
|
-
setLastBlockchain(blockchain);
|
|
1443
|
-
if (fromNetworks) {
|
|
1444
|
-
savedNetworksScroll.current = networksScrollRef.current?.scrollTop ?? 0;
|
|
1445
|
-
setSlideDirection(1);
|
|
1446
|
-
setView({ kind: "network-chain", blockchain });
|
|
1447
|
-
return;
|
|
1448
|
-
}
|
|
1449
|
-
setView({ kind: "rail-chain", blockchain });
|
|
1450
|
-
}
|
|
1451
|
-
function handleBackToNetworks() {
|
|
1452
|
-
setSlideDirection(-1);
|
|
1453
|
-
setView({ kind: "networks" });
|
|
1454
|
-
}
|
|
1455
|
-
useLayoutEffect(() => {
|
|
1456
|
-
if (view.kind !== "networks" || slideDirection !== -1) return;
|
|
1457
|
-
const node = networksScrollRef.current;
|
|
1458
|
-
if (!node) return;
|
|
1459
|
-
node.scrollTop = savedNetworksScroll.current;
|
|
1460
|
-
}, [view, slideDirection]);
|
|
1461
|
-
function handleSelectToken(token) {
|
|
1405
|
+
}, [searching, rangeTokens, search, payer, owners, balanceEntries, balanceMode, syncGetBalance, syncIsBalanceLoading]);
|
|
1406
|
+
function handleSelectToken(token, fromSearch) {
|
|
1462
1407
|
if (isBlockchainDisabled(token.blockchain, disabledBlockchains)) return;
|
|
1463
1408
|
if (isChainKindLocked(token.chain.chainKind, lockChainKind)) return;
|
|
1464
1409
|
if (payer) setLastToken(token.assetId, token.blockchain);
|
|
1465
1410
|
else setLastBlockchain(token.blockchain);
|
|
1411
|
+
if (fromSearch && search.trim()) setRecentSearch(token.assetId);
|
|
1466
1412
|
onSelect({ token });
|
|
1467
1413
|
onClose();
|
|
1468
1414
|
}
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1415
|
+
function clearVisibleSearches() {
|
|
1416
|
+
if (chainFilter === ALL_CHAIN_FILTER) {
|
|
1417
|
+
removeRecentSearches(prefs2.recentSearchAssetIds);
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
1420
|
+
const byId = new Map(scopedTokens.map((token) => [token.assetId, token]));
|
|
1421
|
+
removeRecentSearches(prefs2.recentSearchAssetIds.filter((assetId) => byId.get(assetId)?.blockchain === chainFilter));
|
|
1422
|
+
}
|
|
1472
1423
|
const tokenDisabled = (token) => isBlockchainDisabled(token.blockchain, disabledBlockchains) || isChainKindLocked(token.chain.chainKind, lockChainKind);
|
|
1473
|
-
const
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1424
|
+
const sections = useMemo(() => {
|
|
1425
|
+
if (loading) {
|
|
1426
|
+
const next2 = [];
|
|
1427
|
+
if (payer && rangeWalletConnected) {
|
|
1428
|
+
next2.push({ id: "yours", title: YOUR_TOKENS_TITLE, icon: "database", tokens: [], skeletonRows: 2 });
|
|
1429
|
+
}
|
|
1430
|
+
if (payer && recentSearches.length > 0) {
|
|
1431
|
+
next2.push({
|
|
1432
|
+
id: "searches",
|
|
1433
|
+
title: RECENT_SEARCHES_TITLE,
|
|
1434
|
+
icon: "duration",
|
|
1435
|
+
tokens: [],
|
|
1436
|
+
skeletonRows: 2,
|
|
1437
|
+
action: { label: "Clear", onClick: clearVisibleSearches }
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1440
|
+
if (payer) {
|
|
1441
|
+
next2.push({ id: "trends", title: TRENDS_TOKEN_TITLE, icon: "trends", tokens: [], skeletonRows: 6 });
|
|
1442
|
+
}
|
|
1443
|
+
return next2;
|
|
1488
1444
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1445
|
+
if (!payer) return [];
|
|
1446
|
+
const next = [];
|
|
1447
|
+
if (yours.length > 0) {
|
|
1448
|
+
next.push({ id: "yours", title: YOUR_TOKENS_TITLE, icon: "database", tokens: yours });
|
|
1449
|
+
}
|
|
1450
|
+
if (recentSearches.length > 0) {
|
|
1451
|
+
next.push({
|
|
1452
|
+
id: "searches",
|
|
1453
|
+
title: RECENT_SEARCHES_TITLE,
|
|
1454
|
+
icon: "duration",
|
|
1455
|
+
tokens: recentSearches,
|
|
1456
|
+
action: { label: "Clear", onClick: clearVisibleSearches }
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
if (trends.length > 0) {
|
|
1460
|
+
next.push({ id: "trends", title: TRENDS_TOKEN_TITLE, icon: "trends", tokens: trends });
|
|
1461
|
+
}
|
|
1462
|
+
return next;
|
|
1463
|
+
}, [loading, payer, rangeWalletConnected, recentSearches, yours, trends, chainFilter, prefs2.recentSearchAssetIds, scopedTokens]);
|
|
1464
|
+
return /* @__PURE__ */ jsx8(
|
|
1491
1465
|
Dialog,
|
|
1492
1466
|
{
|
|
1493
1467
|
open,
|
|
1494
1468
|
onClose,
|
|
1495
1469
|
title,
|
|
1496
|
-
titleClassName: cx(
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
titleClassName
|
|
1500
|
-
),
|
|
1501
|
-
headerClassName: cx("h-14 border-b border-[#e3e3e3] px-[22px] pr-4", headerClassName),
|
|
1502
|
-
closeClassName: cx("md:ml-0", closeClassName),
|
|
1470
|
+
titleClassName: cx("text-[18px] font-semibold text-black", fontSans, titleClassName),
|
|
1471
|
+
headerClassName: cx("border-0 px-6 pt-[25px] pb-0", headerClassName),
|
|
1472
|
+
closeClassName,
|
|
1503
1473
|
contentClassName: cx("overflow-hidden", contentClassName),
|
|
1504
|
-
headerAction: /* @__PURE__ */ jsx9(
|
|
1505
|
-
SearchInput,
|
|
1506
|
-
{
|
|
1507
|
-
value: search,
|
|
1508
|
-
onChange: setSearch,
|
|
1509
|
-
placeholder: "search or paste address",
|
|
1510
|
-
className: "ml-auto hidden w-[215px] shrink-0 md:block",
|
|
1511
|
-
inputClassName: cx(SEARCH_INPUT_CLASS, searchClassName)
|
|
1512
|
-
}
|
|
1513
|
-
),
|
|
1514
1474
|
cardClassName: cx(
|
|
1515
|
-
"w-full max-h-[90vh] gap-
|
|
1475
|
+
"w-full max-h-[90vh] gap-3 rounded-[12px] border border-[#e0e0e0] bg-[#fdfdfd] p-0 shadow-[0_0_40px_0_rgba(0,0,0,0.06)] md:w-[448px] md:rounded-[12px] md:p-0",
|
|
1516
1476
|
className
|
|
1517
1477
|
),
|
|
1518
|
-
children: /* @__PURE__ */
|
|
1519
|
-
/* @__PURE__ */
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
value: search,
|
|
1523
|
-
onChange: setSearch,
|
|
1524
|
-
placeholder: "search or paste address",
|
|
1525
|
-
className: "mb-3 shrink-0 px-[22px] md:hidden",
|
|
1526
|
-
inputClassName: cx(SEARCH_INPUT_CLASS, searchClassName)
|
|
1527
|
-
}
|
|
1528
|
-
),
|
|
1529
|
-
/* @__PURE__ */ jsxs6("div", { className: "flex min-h-0 flex-1", children: [
|
|
1530
|
-
/* @__PURE__ */ jsx9(
|
|
1531
|
-
NetworkRail,
|
|
1478
|
+
children: /* @__PURE__ */ jsxs5("div", { className: "flex h-[min(620px,70vh)] min-h-0 flex-col gap-2.5", children: [
|
|
1479
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex shrink-0 items-center gap-3.5 px-5", children: [
|
|
1480
|
+
/* @__PURE__ */ jsx8(
|
|
1481
|
+
SearchInput2,
|
|
1532
1482
|
{
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1483
|
+
value: search,
|
|
1484
|
+
onChange: setSearch,
|
|
1485
|
+
placeholder: "search or paste address",
|
|
1486
|
+
className: "min-w-0 flex-1",
|
|
1487
|
+
iconClassName: TOKEN_SEARCH_ICON_CLASS,
|
|
1488
|
+
inputClassName: cx(TOKEN_SEARCH_CLASS, searchClassName)
|
|
1489
|
+
}
|
|
1490
|
+
),
|
|
1491
|
+
/* @__PURE__ */ jsx8(
|
|
1492
|
+
ChainSelect,
|
|
1493
|
+
{
|
|
1494
|
+
chains: menuChains,
|
|
1495
|
+
previewChains,
|
|
1496
|
+
dotted: dottedSet,
|
|
1497
|
+
value: chainFilter,
|
|
1498
|
+
onChange: (blockchain) => {
|
|
1499
|
+
userPickedChain.current = true;
|
|
1500
|
+
setChainFilter(blockchain);
|
|
1501
|
+
},
|
|
1538
1502
|
lockChainKind,
|
|
1539
1503
|
disabledBlockchains,
|
|
1540
|
-
disabledReason
|
|
1541
|
-
onSelectWallet: () => setView({ kind: "wallet" }),
|
|
1542
|
-
onSelectAll: () => setView({ kind: "all" }),
|
|
1543
|
-
onSelectNetworks: () => setView({ kind: "networks" }),
|
|
1544
|
-
onSelectChain: (blockchain) => handleSelectChain(blockchain, false),
|
|
1545
|
-
className: railClassName
|
|
1504
|
+
disabledReason
|
|
1546
1505
|
}
|
|
1547
|
-
)
|
|
1548
|
-
|
|
1506
|
+
)
|
|
1507
|
+
] }),
|
|
1508
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex min-h-0 flex-1 flex-col gap-2.5", children: [
|
|
1509
|
+
payer && loading && recentTokens.length > 0 ? /* @__PURE__ */ jsx8(RecentTileSkeletons, {}) : null,
|
|
1510
|
+
payer && !loading ? /* @__PURE__ */ jsx8(RecentTiles, { tokens: recentTokens, onSelect: (token) => handleSelectToken(token, false), isTokenDisabled: tokenDisabled }) : null,
|
|
1511
|
+
searching ? /* @__PURE__ */ jsx8(
|
|
1549
1512
|
SearchResults,
|
|
1550
1513
|
{
|
|
1551
|
-
|
|
1514
|
+
tokens: results,
|
|
1552
1515
|
selectedAssetId,
|
|
1553
1516
|
loading,
|
|
1554
1517
|
showBalances,
|
|
1555
|
-
showWalletStatus: payer,
|
|
1556
1518
|
getBalance: balanceOf,
|
|
1557
1519
|
isBalanceLoading: loadingOf,
|
|
1558
|
-
onSelectToken: handleSelectToken,
|
|
1520
|
+
onSelectToken: (token) => handleSelectToken(token, true),
|
|
1559
1521
|
isTokenDisabled: tokenDisabled,
|
|
1560
1522
|
rowClassName
|
|
1561
1523
|
}
|
|
1562
|
-
) :
|
|
1563
|
-
|
|
1524
|
+
) : payer ? /* @__PURE__ */ jsx8(
|
|
1525
|
+
TokenPane,
|
|
1526
|
+
{
|
|
1527
|
+
sections,
|
|
1528
|
+
selectedAssetId,
|
|
1529
|
+
showBalances,
|
|
1530
|
+
getBalance: balanceOf,
|
|
1531
|
+
isBalanceLoading: loadingOf,
|
|
1532
|
+
onSelectToken: (token) => handleSelectToken(token, false),
|
|
1533
|
+
isTokenDisabled: tokenDisabled,
|
|
1534
|
+
rowClassName,
|
|
1535
|
+
emptyLabel: recentTokens.length === 0 && sections.every((section) => section.tokens.length === 0 && !section.skeletonRows) ? "No tokens found" : null
|
|
1536
|
+
}
|
|
1537
|
+
) : loading ? /* @__PURE__ */ jsx8("div", { className: "min-h-0 flex-1 overflow-y-auto px-3", children: /* @__PURE__ */ jsx8(TokenListSkeleton, { rows: 6 }) }) : /* @__PURE__ */ jsx8(
|
|
1538
|
+
TokenPane,
|
|
1564
1539
|
{
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1540
|
+
sections: [{
|
|
1541
|
+
id: "all",
|
|
1542
|
+
title: "",
|
|
1543
|
+
icon: "trends",
|
|
1544
|
+
tokens: receiverTokens
|
|
1545
|
+
}],
|
|
1546
|
+
selectedAssetId,
|
|
1547
|
+
showBalances: false,
|
|
1548
|
+
getBalance: balanceOf,
|
|
1549
|
+
isBalanceLoading: loadingOf,
|
|
1550
|
+
onSelectToken: (token) => handleSelectToken(token, false),
|
|
1551
|
+
isTokenDisabled: tokenDisabled,
|
|
1552
|
+
rowClassName,
|
|
1553
|
+
emptyLabel: receiverTokens.length === 0 ? "No tokens found" : null
|
|
1579
1554
|
}
|
|
1580
|
-
)
|
|
1555
|
+
)
|
|
1581
1556
|
] })
|
|
1582
1557
|
] })
|
|
1583
1558
|
}
|
|
@@ -1684,10 +1659,10 @@ function normalizePayConfig(source, options) {
|
|
|
1684
1659
|
explorer: chain.explorer
|
|
1685
1660
|
});
|
|
1686
1661
|
}
|
|
1687
|
-
const
|
|
1662
|
+
const chainByCode = new Map(chains.map((chain) => [chain.blockchain, chain]));
|
|
1688
1663
|
const tokens = [];
|
|
1689
1664
|
for (const token of source.tokens) {
|
|
1690
|
-
const chain =
|
|
1665
|
+
const chain = chainByCode.get(token.network);
|
|
1691
1666
|
if (!chain) continue;
|
|
1692
1667
|
const symbol = normalizeSymbol(token.symbol);
|
|
1693
1668
|
if (!symbol) continue;
|
|
@@ -1720,7 +1695,6 @@ export {
|
|
|
1720
1695
|
mapPayConfigSource,
|
|
1721
1696
|
normalizePayConfig,
|
|
1722
1697
|
ownerKey2 as ownerKey,
|
|
1723
|
-
parsePopularTokens,
|
|
1724
1698
|
refreshPayTokenBalance,
|
|
1725
1699
|
tokenAssetId,
|
|
1726
1700
|
usePayTokenBalance
|