@rhinestone/deposit-modal 0.10.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{DepositModalReown-MTWT6Y66.mjs → DepositModalReown-MO5QDLIT.mjs} +96 -26
- package/dist/{DepositModalReown-S3DSFXTX.cjs → DepositModalReown-YGB73NMW.cjs} +97 -27
- package/dist/caip-D8aRWdEY.d.cts +40 -0
- package/dist/caip-D8aRWdEY.d.ts +40 -0
- package/dist/{chunk-NF4NBRUP.cjs → chunk-4FTI3GTB.cjs} +1 -1
- package/dist/{chunk-A223BLVC.mjs → chunk-53IFZGSF.mjs} +177 -21
- package/dist/{chunk-VDGT6NZQ.mjs → chunk-5746YXKC.mjs} +14 -31
- package/dist/{chunk-7TV7GLJB.mjs → chunk-CWGUBFJL.mjs} +763 -169
- package/dist/{chunk-LR7MKHYV.mjs → chunk-EIWOVX53.mjs} +27 -25
- package/dist/{chunk-VTVOHNXM.cjs → chunk-FVUXJ3RP.cjs} +3 -3
- package/dist/{chunk-A42XAHIB.cjs → chunk-HUHBNYD3.cjs} +84 -101
- package/dist/{chunk-YEBXUUH3.cjs → chunk-JPRV36DT.cjs} +2 -2
- package/dist/{chunk-UMCDZJMG.cjs → chunk-LQGYPM5B.cjs} +96 -94
- package/dist/{chunk-ILT2PITN.mjs → chunk-MZ53PDIX.mjs} +1 -1
- package/dist/{chunk-5NJYW5FT.mjs → chunk-OWYPKCYD.mjs} +12 -9
- package/dist/{chunk-W4YAOJPG.cjs → chunk-SSQ27YFB.cjs} +625 -568
- package/dist/{chunk-H577RJN5.cjs → chunk-TENL4H64.cjs} +186 -30
- package/dist/{chunk-5OEWGJR4.mjs → chunk-URFSTNRS.mjs} +1 -1
- package/dist/{chunk-KW32UBUQ.mjs → chunk-V6T7LORJ.mjs} +1 -1
- package/dist/{chunk-MHIOMTMM.mjs → chunk-YELNYILK.mjs} +391 -334
- package/dist/{chunk-PUJHXHRA.cjs → chunk-ZQR36NCV.cjs} +845 -251
- package/dist/{chunk-DEF767BA.cjs → chunk-ZRIRCIQM.cjs} +66 -63
- package/dist/claim.cjs +6 -6
- package/dist/claim.d.cts +3 -2
- package/dist/claim.d.ts +3 -2
- package/dist/claim.mjs +5 -5
- package/dist/{caip-523Zrc3r.d.cts → constants-FuzG3h4m.d.cts} +1 -18
- package/dist/{caip-523Zrc3r.d.ts → constants-FuzG3h4m.d.ts} +1 -18
- package/dist/constants.cjs +5 -3
- package/dist/constants.d.cts +3 -2
- package/dist/constants.d.ts +3 -2
- package/dist/constants.mjs +4 -2
- package/dist/deposit.cjs +8 -8
- package/dist/deposit.d.cts +3 -2
- package/dist/deposit.d.ts +3 -2
- package/dist/deposit.mjs +7 -7
- package/dist/index.cjs +12 -10
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.mjs +11 -9
- package/dist/polymarket.cjs +5 -5
- package/dist/polymarket.mjs +2 -2
- package/dist/{types-C0SGf-21.d.cts → types-CsGa-HxD.d.cts} +10 -3
- package/dist/{types-C0SGf-21.d.ts → types-DdS8OySJ.d.ts} +10 -3
- package/dist/withdraw.cjs +6 -6
- package/dist/withdraw.d.cts +3 -2
- package/dist/withdraw.d.ts +3 -2
- package/dist/withdraw.mjs +5 -5
- package/package.json +1 -1
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SERVICE_HEADERS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-URFSTNRS.mjs";
|
|
4
4
|
import {
|
|
5
|
+
CHAIN_BY_ID,
|
|
6
|
+
CHAIN_DISPLAY_ORDER,
|
|
5
7
|
HYPERCORE_CHAIN_ID,
|
|
6
8
|
HYPERCORE_MAINNET_CAIP2,
|
|
7
9
|
HYPERCORE_SOURCE_TOKENS,
|
|
8
10
|
ICON_CDN,
|
|
9
11
|
NATIVE_TOKEN_ADDRESS,
|
|
12
|
+
SOLANA_MAINNET_CAIP2,
|
|
13
|
+
SOURCE_CHAINS,
|
|
10
14
|
findTokenDecimals,
|
|
15
|
+
getBundledTargetTokens,
|
|
16
|
+
getChainName,
|
|
17
|
+
getExplorerTxUrl,
|
|
11
18
|
getSolanaTokenByMint,
|
|
19
|
+
getSupportedChainIds,
|
|
20
|
+
getSupportedTargetTokens,
|
|
12
21
|
getTokenAddress,
|
|
13
22
|
getTokenDecimalsByAddress,
|
|
14
23
|
getTokenSymbol,
|
|
@@ -16,8 +25,12 @@ import {
|
|
|
16
25
|
isRegistryTokenOnChain,
|
|
17
26
|
isSolanaCaip2,
|
|
18
27
|
parseEvmChainId,
|
|
28
|
+
publishShortlistTokens,
|
|
29
|
+
setRuntimeChainMeta,
|
|
30
|
+
setRuntimeTokens,
|
|
31
|
+
toEvmCaip2,
|
|
19
32
|
tokenIconUrl
|
|
20
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-53IFZGSF.mjs";
|
|
21
34
|
|
|
22
35
|
// src/components/ui/Modal.tsx
|
|
23
36
|
import {
|
|
@@ -433,140 +446,6 @@ function PoweredBy() {
|
|
|
433
446
|
}
|
|
434
447
|
PoweredBy.displayName = "PoweredBy";
|
|
435
448
|
|
|
436
|
-
// src/core/useLatestRef.ts
|
|
437
|
-
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
438
|
-
function useLatestRef(value) {
|
|
439
|
-
const ref = useRef2(value);
|
|
440
|
-
useEffect2(() => {
|
|
441
|
-
ref.current = value;
|
|
442
|
-
}, [value]);
|
|
443
|
-
return ref;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// src/components/ui/Spinner.tsx
|
|
447
|
-
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
448
|
-
function Spinner({ className }) {
|
|
449
|
-
return /* @__PURE__ */ jsxs4(
|
|
450
|
-
"svg",
|
|
451
|
-
{
|
|
452
|
-
className: `rs-spinner ${className || ""}`,
|
|
453
|
-
fill: "none",
|
|
454
|
-
viewBox: "0 0 20 21",
|
|
455
|
-
children: [
|
|
456
|
-
/* @__PURE__ */ jsx6(
|
|
457
|
-
"path",
|
|
458
|
-
{
|
|
459
|
-
d: "M10 0.5C8.02 0.5 6.08 1.08 4.44 2.18C2.79 3.28 1.51 4.84 0.76 6.67C0.00 8.50 -0.19 10.51 0.19 12.45C0.57 14.39 1.53 16.17 2.92 17.57C4.32 18.96 6.10 19.92 8.04 20.30C9.98 20.69 11.99 20.49 13.82 19.73C15.65 18.98 17.21 17.70 18.31 16.05C19.41 14.41 20 12.47 20 10.5C20 7.84 18.94 5.30 17.07 3.42C15.19 1.55 12.65 0.5 10 0.5ZM10 17.77C8.56 17.77 7.15 17.34 5.95 16.54C4.76 15.74 3.83 14.61 3.28 13.28C2.73 11.95 2.58 10.49 2.86 9.08C3.14 7.67 3.84 6.37 4.85 5.35C5.87 4.34 7.17 3.64 8.58 3.36C9.99 3.08 11.45 3.23 12.78 3.78C14.11 4.33 15.24 5.26 16.04 6.45C16.84 7.65 17.27 9.06 17.27 10.5C17.27 12.42 16.50 14.27 15.14 15.64C13.77 17.00 11.92 17.77 10 17.77Z",
|
|
460
|
-
fill: "currentColor",
|
|
461
|
-
opacity: 0.3
|
|
462
|
-
}
|
|
463
|
-
),
|
|
464
|
-
/* @__PURE__ */ jsx6(
|
|
465
|
-
"path",
|
|
466
|
-
{
|
|
467
|
-
d: "M10 3.22C11.74 3.22 13.42 3.84 14.75 4.95C16.08 6.07 16.96 7.61 17.25 9.31C17.30 9.64 17.46 9.94 17.71 10.15C17.96 10.37 18.28 10.49 18.62 10.5C18.82 10.50 19.01 10.45 19.20 10.37C19.38 10.29 19.54 10.16 19.67 10.01C19.80 9.86 19.89 9.68 19.95 9.49C20.00 9.30 20.01 9.10 19.98 8.90C19.59 6.56 18.38 4.42 16.55 2.88C14.72 1.34 12.40 0.5 10 0.5C7.59 0.5 5.27 1.34 3.44 2.88C1.61 4.42 0.40 6.56 0.01 8.90C-0.01 9.10 -0.00 9.30 0.04 9.49C0.10 9.68 0.19 9.86 0.32 10.01C0.45 10.16 0.61 10.29 0.79 10.37C0.98 10.45 1.17 10.50 1.37 10.5C1.71 10.49 2.03 10.37 2.28 10.15C2.53 9.94 2.69 9.64 2.74 9.31C3.03 7.61 3.91 6.07 5.24 4.95C6.57 3.84 8.25 3.22 10 3.22Z",
|
|
468
|
-
fill: "currentColor"
|
|
469
|
-
}
|
|
470
|
-
)
|
|
471
|
-
]
|
|
472
|
-
}
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// src/components/ui/Button.tsx
|
|
477
|
-
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
478
|
-
function Button({
|
|
479
|
-
children,
|
|
480
|
-
variant = "accent",
|
|
481
|
-
size = "default",
|
|
482
|
-
loading = false,
|
|
483
|
-
loadingText,
|
|
484
|
-
fullWidth = false,
|
|
485
|
-
disabled,
|
|
486
|
-
className = "",
|
|
487
|
-
...props
|
|
488
|
-
}) {
|
|
489
|
-
const classes = [
|
|
490
|
-
"rs-button",
|
|
491
|
-
`rs-button--${variant}`,
|
|
492
|
-
`rs-button--size-${size}`,
|
|
493
|
-
fullWidth ? "rs-button--full-width" : "",
|
|
494
|
-
className
|
|
495
|
-
].filter(Boolean).join(" ");
|
|
496
|
-
const showInlineLoadingText = loading && loadingText !== void 0;
|
|
497
|
-
return /* @__PURE__ */ jsx7(
|
|
498
|
-
"button",
|
|
499
|
-
{
|
|
500
|
-
className: classes,
|
|
501
|
-
disabled: disabled || loading,
|
|
502
|
-
"aria-busy": loading || void 0,
|
|
503
|
-
...props,
|
|
504
|
-
children: showInlineLoadingText ? /* @__PURE__ */ jsxs5("span", { className: "rs-button__loading-row", children: [
|
|
505
|
-
/* @__PURE__ */ jsx7(Spinner, { className: "rs-spinner--sm" }),
|
|
506
|
-
/* @__PURE__ */ jsx7("span", { children: loadingText })
|
|
507
|
-
] }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
508
|
-
/* @__PURE__ */ jsx7("span", { className: loading ? "rs-button__content--hidden" : "", children }),
|
|
509
|
-
loading && /* @__PURE__ */ jsx7("span", { className: "rs-button__spinner", children: /* @__PURE__ */ jsx7(Spinner, { className: "rs-spinner--sm" }) })
|
|
510
|
-
] })
|
|
511
|
-
}
|
|
512
|
-
);
|
|
513
|
-
}
|
|
514
|
-
Button.displayName = "Button";
|
|
515
|
-
|
|
516
|
-
// src/components/ui/Callout.tsx
|
|
517
|
-
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
518
|
-
function CircleAlertIcon() {
|
|
519
|
-
return /* @__PURE__ */ jsx8(
|
|
520
|
-
"svg",
|
|
521
|
-
{
|
|
522
|
-
width: "16",
|
|
523
|
-
height: "16",
|
|
524
|
-
viewBox: "0 0 16 16",
|
|
525
|
-
fill: "none",
|
|
526
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
527
|
-
"aria-hidden": "true",
|
|
528
|
-
children: /* @__PURE__ */ jsx8(
|
|
529
|
-
"path",
|
|
530
|
-
{
|
|
531
|
-
d: "M10 5.99L6 9.99M6 5.99L10 9.99M14.66 7.99C14.66 11.68 11.68 14.66 8 14.66C4.31 14.66 1.33 11.68 1.33 7.99C1.33 4.31 4.31 1.33 8 1.33C11.68 1.33 14.66 4.31 14.66 7.99Z",
|
|
532
|
-
stroke: "currentColor",
|
|
533
|
-
strokeWidth: "1.33",
|
|
534
|
-
strokeLinecap: "round",
|
|
535
|
-
strokeLinejoin: "round"
|
|
536
|
-
}
|
|
537
|
-
)
|
|
538
|
-
}
|
|
539
|
-
);
|
|
540
|
-
}
|
|
541
|
-
function Callout({ variant = "error", children, role }) {
|
|
542
|
-
return /* @__PURE__ */ jsxs6(
|
|
543
|
-
"div",
|
|
544
|
-
{
|
|
545
|
-
className: `rs-callout rs-callout--${variant}`,
|
|
546
|
-
role: role ?? (variant === "error" ? "alert" : "status"),
|
|
547
|
-
children: [
|
|
548
|
-
/* @__PURE__ */ jsx8("span", { className: "rs-callout-icon", children: variant === "error" ? /* @__PURE__ */ jsx8(CircleAlertIcon, {}) : /* @__PURE__ */ jsx8(AlertTriangleIcon, {}) }),
|
|
549
|
-
/* @__PURE__ */ jsx8("span", { className: "rs-callout-text", children })
|
|
550
|
-
]
|
|
551
|
-
}
|
|
552
|
-
);
|
|
553
|
-
}
|
|
554
|
-
Callout.displayName = "Callout";
|
|
555
|
-
|
|
556
|
-
// src/components/ui/TokenIcon.tsx
|
|
557
|
-
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
558
|
-
function TokenIcon({ symbol, className, fallback }) {
|
|
559
|
-
return /* @__PURE__ */ jsx9(
|
|
560
|
-
CdnIcon,
|
|
561
|
-
{
|
|
562
|
-
src: tokenIconUrl(symbol),
|
|
563
|
-
className: `rs-token-icon ${className ?? ""}`.trimEnd(),
|
|
564
|
-
fallback
|
|
565
|
-
}
|
|
566
|
-
);
|
|
567
|
-
}
|
|
568
|
-
TokenIcon.displayName = "TokenIcon";
|
|
569
|
-
|
|
570
449
|
// src/core/deposit-service.ts
|
|
571
450
|
import { getAddress } from "viem";
|
|
572
451
|
|
|
@@ -623,6 +502,101 @@ function debugError(enabled, scope, message, error, data) {
|
|
|
623
502
|
console.error(`[deposit-modal:${scope}] ${message}`, payload);
|
|
624
503
|
}
|
|
625
504
|
|
|
505
|
+
// src/core/chain-catalog.ts
|
|
506
|
+
function parseToken(value) {
|
|
507
|
+
if (typeof value !== "object" || value === null) return null;
|
|
508
|
+
const { symbol, address, decimals } = value;
|
|
509
|
+
if (typeof symbol !== "string" || typeof address !== "string" || typeof decimals !== "number") {
|
|
510
|
+
return null;
|
|
511
|
+
}
|
|
512
|
+
return { symbol, address, decimals };
|
|
513
|
+
}
|
|
514
|
+
function parseExplorer(value) {
|
|
515
|
+
if (typeof value !== "object" || value === null) return null;
|
|
516
|
+
const { url, addressPath, txPath } = value;
|
|
517
|
+
if (typeof url !== "string" || typeof addressPath !== "string" || typeof txPath !== "string") {
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
return { url, addressPath, txPath };
|
|
521
|
+
}
|
|
522
|
+
function parseVmType(value) {
|
|
523
|
+
return value === "evm" || value === "svm" || value === "tvm" ? value : null;
|
|
524
|
+
}
|
|
525
|
+
function parseOptionalString(value) {
|
|
526
|
+
return typeof value === "string" && value.trim() !== "" ? value.trim() : null;
|
|
527
|
+
}
|
|
528
|
+
function parseChain(caip2, value) {
|
|
529
|
+
if (typeof value !== "object" || value === null) return null;
|
|
530
|
+
const raw = value;
|
|
531
|
+
const { name, testnet, deposit, destination, refund } = raw;
|
|
532
|
+
if (typeof name !== "string" || typeof testnet !== "boolean" || typeof deposit !== "boolean" || typeof destination !== "boolean" || typeof refund !== "boolean") {
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
const vmType = parseVmType(raw.vmType);
|
|
536
|
+
const nativeToken = parseToken(raw.nativeToken);
|
|
537
|
+
if (!vmType || !nativeToken) return null;
|
|
538
|
+
let supportedTokens;
|
|
539
|
+
if (raw.supportedTokens === "all") {
|
|
540
|
+
supportedTokens = "all";
|
|
541
|
+
} else if (Array.isArray(raw.supportedTokens)) {
|
|
542
|
+
const tokens = [];
|
|
543
|
+
for (const entry of raw.supportedTokens) {
|
|
544
|
+
const token = parseToken(entry);
|
|
545
|
+
if (!token) return null;
|
|
546
|
+
tokens.push(token);
|
|
547
|
+
}
|
|
548
|
+
supportedTokens = tokens;
|
|
549
|
+
} else {
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
return {
|
|
553
|
+
caip2,
|
|
554
|
+
// `parseEvmChainId` returns null for `solana:`/`tron:`/`hypercore:` keys,
|
|
555
|
+
// which is the intended answer — those chains have no numeric id, and the
|
|
556
|
+
// modal addresses them by their CAIP-2 string or a sentinel.
|
|
557
|
+
chainId: parseEvmChainId(caip2),
|
|
558
|
+
name,
|
|
559
|
+
testnet,
|
|
560
|
+
deposit,
|
|
561
|
+
destination,
|
|
562
|
+
refund,
|
|
563
|
+
vmType,
|
|
564
|
+
nativeToken,
|
|
565
|
+
explorer: parseExplorer(raw.explorer),
|
|
566
|
+
supportedTokens,
|
|
567
|
+
publicRpcUrl: parseOptionalString(raw.publicRpcUrl),
|
|
568
|
+
iconUrl: parseOptionalString(raw.iconUrl)
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
function parseChainCatalog(body) {
|
|
572
|
+
if (typeof body !== "object" || body === null || Array.isArray(body)) {
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
const all = [];
|
|
576
|
+
const byCaip2 = /* @__PURE__ */ new Map();
|
|
577
|
+
const byChainId = /* @__PURE__ */ new Map();
|
|
578
|
+
for (const [caip2, value] of Object.entries(body)) {
|
|
579
|
+
const chain = parseChain(caip2, value);
|
|
580
|
+
if (!chain) continue;
|
|
581
|
+
all.push(chain);
|
|
582
|
+
byCaip2.set(chain.caip2, chain);
|
|
583
|
+
if (chain.chainId !== null) byChainId.set(chain.chainId, chain);
|
|
584
|
+
}
|
|
585
|
+
if (all.length === 0) return null;
|
|
586
|
+
return { all, byCaip2, byChainId };
|
|
587
|
+
}
|
|
588
|
+
function catalogKeyForChain(chainId) {
|
|
589
|
+
if (chainId === "solana") return SOLANA_MAINNET_CAIP2;
|
|
590
|
+
if (chainId === "hypercore" || chainId === HYPERCORE_CHAIN_ID) {
|
|
591
|
+
return HYPERCORE_MAINNET_CAIP2;
|
|
592
|
+
}
|
|
593
|
+
return chainId;
|
|
594
|
+
}
|
|
595
|
+
function catalogExplorerTxUrl(chain, txHash) {
|
|
596
|
+
if (!chain?.explorer) return void 0;
|
|
597
|
+
return `${chain.explorer.url}${chain.explorer.txPath}${txHash}`;
|
|
598
|
+
}
|
|
599
|
+
|
|
626
600
|
// src/core/deposit-asset-helpers.ts
|
|
627
601
|
function getAssetId(asset) {
|
|
628
602
|
return `${asset.chainId}:${asset.token.toLowerCase()}`;
|
|
@@ -869,6 +843,11 @@ var SwappedConnectFeeChangedError = class extends Error {
|
|
|
869
843
|
function parseExchangeFeeBps(value) {
|
|
870
844
|
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 1e4 ? value : void 0;
|
|
871
845
|
}
|
|
846
|
+
var UNSUPPORTED_CONNECT_EXCHANGES = /* @__PURE__ */ new Set(["kraken", "htx"]);
|
|
847
|
+
var SUPPORTED_CONNECT_EXCHANGE_COUNT = 7;
|
|
848
|
+
function isSupportedConnectExchange(exchange) {
|
|
849
|
+
return !UNSUPPORTED_CONNECT_EXCHANGES.has(exchange.connection.toLowerCase());
|
|
850
|
+
}
|
|
872
851
|
function resolveAppFeeBps(appFees, sourceChainCaip2, sourceToken) {
|
|
873
852
|
const override = appFees?.tokens?.[sourceChainCaip2]?.[sourceToken.toLowerCase()];
|
|
874
853
|
const bps = override ?? appFees?.feeBps ?? 0;
|
|
@@ -889,6 +868,7 @@ function createDepositService(baseUrl, options) {
|
|
|
889
868
|
const PORTFOLIO_CACHE_TTL_MS = 3e4;
|
|
890
869
|
const portfolioCache = /* @__PURE__ */ new Map();
|
|
891
870
|
let topTokensPromise = null;
|
|
871
|
+
let chainsPromise = null;
|
|
892
872
|
function parseTopTokens(value) {
|
|
893
873
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
894
874
|
return null;
|
|
@@ -936,6 +916,32 @@ function createDepositService(baseUrl, options) {
|
|
|
936
916
|
return null;
|
|
937
917
|
}
|
|
938
918
|
}
|
|
919
|
+
async function requestChains() {
|
|
920
|
+
try {
|
|
921
|
+
const response = await fetch(apiUrl("/chains"), {
|
|
922
|
+
method: "GET",
|
|
923
|
+
headers: SERVICE_HEADERS
|
|
924
|
+
});
|
|
925
|
+
if (!response.ok) {
|
|
926
|
+
debugLog(debug, scope, "getChains:unavailable", {
|
|
927
|
+
status: response.status
|
|
928
|
+
});
|
|
929
|
+
return null;
|
|
930
|
+
}
|
|
931
|
+
const catalog = parseChainCatalog(await response.json());
|
|
932
|
+
if (!catalog) {
|
|
933
|
+
debugLog(debug, scope, "getChains:malformed");
|
|
934
|
+
return null;
|
|
935
|
+
}
|
|
936
|
+
debugLog(debug, scope, "getChains:success", {
|
|
937
|
+
chains: catalog.all.length
|
|
938
|
+
});
|
|
939
|
+
return catalog;
|
|
940
|
+
} catch (error) {
|
|
941
|
+
debugError(debug, scope, "getChains:error", error);
|
|
942
|
+
return null;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
939
945
|
function cachedPortfolio(key, fetcher, forceRefresh = false) {
|
|
940
946
|
const now = Date.now();
|
|
941
947
|
const entry = portfolioCache.get(key);
|
|
@@ -1326,7 +1332,7 @@ function createDepositService(baseUrl, options) {
|
|
|
1326
1332
|
return { deposits, nextCursor };
|
|
1327
1333
|
},
|
|
1328
1334
|
async checkLiquidity(params) {
|
|
1329
|
-
if (params.destinationChainId === "solana") {
|
|
1335
|
+
if (isSolanaCaip2(params.destinationChainId) || params.destinationChainId === "solana") {
|
|
1330
1336
|
const token = getSolanaTokenByMint(params.destinationToken);
|
|
1331
1337
|
return {
|
|
1332
1338
|
hasLiquidity: true,
|
|
@@ -1337,9 +1343,9 @@ function createDepositService(baseUrl, options) {
|
|
|
1337
1343
|
};
|
|
1338
1344
|
}
|
|
1339
1345
|
const searchParams = new URLSearchParams({
|
|
1340
|
-
sourceChainId:
|
|
1346
|
+
sourceChainId: toEvmCaip2(params.sourceChainId),
|
|
1341
1347
|
sourceToken: params.sourceToken,
|
|
1342
|
-
destinationChainId:
|
|
1348
|
+
destinationChainId: params.destinationChainId,
|
|
1343
1349
|
destinationToken: params.destinationToken,
|
|
1344
1350
|
amount: params.amount
|
|
1345
1351
|
});
|
|
@@ -1593,7 +1599,7 @@ function createDepositService(baseUrl, options) {
|
|
|
1593
1599
|
throw new Error("Swapped Connect exchanges: malformed response");
|
|
1594
1600
|
}
|
|
1595
1601
|
return {
|
|
1596
|
-
exchanges,
|
|
1602
|
+
exchanges: exchanges.filter(isSupportedConnectExchange),
|
|
1597
1603
|
fetchedAt: body.fetchedAt,
|
|
1598
1604
|
expiresAt: body.expiresAt,
|
|
1599
1605
|
stale: body.stale === true ? true : void 0,
|
|
@@ -1682,6 +1688,16 @@ function createDepositService(baseUrl, options) {
|
|
|
1682
1688
|
}
|
|
1683
1689
|
return topTokensPromise;
|
|
1684
1690
|
},
|
|
1691
|
+
getChains() {
|
|
1692
|
+
if (!chainsPromise) {
|
|
1693
|
+
const attempt = requestChains().then((catalog) => {
|
|
1694
|
+
if (!catalog && chainsPromise === attempt) chainsPromise = null;
|
|
1695
|
+
return catalog;
|
|
1696
|
+
});
|
|
1697
|
+
chainsPromise = attempt;
|
|
1698
|
+
}
|
|
1699
|
+
return chainsPromise;
|
|
1700
|
+
},
|
|
1685
1701
|
async getSetup() {
|
|
1686
1702
|
const url = apiUrl("/setup");
|
|
1687
1703
|
try {
|
|
@@ -1866,6 +1882,558 @@ function extractNumericString(data, key) {
|
|
|
1866
1882
|
return Number.isFinite(parsed) ? parsed : null;
|
|
1867
1883
|
}
|
|
1868
1884
|
|
|
1885
|
+
// src/core/rpc.ts
|
|
1886
|
+
import { createContext, useContext, useMemo } from "react";
|
|
1887
|
+
function rpcUrlFor(rpcUrls, chain) {
|
|
1888
|
+
const url = rpcUrls?.[chain]?.trim();
|
|
1889
|
+
return url ? url : void 0;
|
|
1890
|
+
}
|
|
1891
|
+
var RpcUrlsContext = createContext(void 0);
|
|
1892
|
+
var RpcUrlsProvider = RpcUrlsContext.Provider;
|
|
1893
|
+
function useRpcUrls() {
|
|
1894
|
+
return useContext(RpcUrlsContext);
|
|
1895
|
+
}
|
|
1896
|
+
function rpcUrlsKey(rpcUrls) {
|
|
1897
|
+
if (!rpcUrls) return "";
|
|
1898
|
+
return Object.entries(rpcUrls).map(([chain, url]) => [chain, url?.trim() ?? ""]).filter(([, url]) => url !== "").map(([chain, url]) => `${chain}=${url}`).sort().join("|");
|
|
1899
|
+
}
|
|
1900
|
+
function useStableRpcUrls(rpcUrls) {
|
|
1901
|
+
const key = rpcUrlsKey(rpcUrls);
|
|
1902
|
+
return useMemo(() => rpcUrls, [key]);
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
// src/core/chain-catalog-context.tsx
|
|
1906
|
+
import {
|
|
1907
|
+
createContext as createContext2,
|
|
1908
|
+
useContext as useContext2,
|
|
1909
|
+
useEffect as useEffect2,
|
|
1910
|
+
useMemo as useMemo2,
|
|
1911
|
+
useState as useState2
|
|
1912
|
+
} from "react";
|
|
1913
|
+
|
|
1914
|
+
// src/core/public-client.ts
|
|
1915
|
+
import { createPublicClient, http } from "viem";
|
|
1916
|
+
var clientCache = /* @__PURE__ */ new Map();
|
|
1917
|
+
var runtimeChainById = /* @__PURE__ */ new Map();
|
|
1918
|
+
function setRuntimeChains(chains) {
|
|
1919
|
+
for (const chain of chains) {
|
|
1920
|
+
const known = runtimeChainById.get(chain.id);
|
|
1921
|
+
if (known === chain) continue;
|
|
1922
|
+
runtimeChainById.set(chain.id, chain);
|
|
1923
|
+
for (const key of clientCache.keys()) {
|
|
1924
|
+
if (key.startsWith(`${chain.id}|`)) clientCache.delete(key);
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
function getPublicClient(chainId, rpcUrls) {
|
|
1929
|
+
const url = rpcUrlFor(rpcUrls, chainId);
|
|
1930
|
+
const cacheKey = `${chainId}|${url ?? ""}`;
|
|
1931
|
+
let client = clientCache.get(cacheKey);
|
|
1932
|
+
if (!client) {
|
|
1933
|
+
const chain = CHAIN_BY_ID[chainId] ?? runtimeChainById.get(chainId);
|
|
1934
|
+
client = createPublicClient({
|
|
1935
|
+
chain,
|
|
1936
|
+
transport: http(url)
|
|
1937
|
+
});
|
|
1938
|
+
clientCache.set(cacheKey, client);
|
|
1939
|
+
}
|
|
1940
|
+
return client;
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
// src/core/chain-objects.ts
|
|
1944
|
+
import { defineChain } from "viem";
|
|
1945
|
+
var viemChainsById = null;
|
|
1946
|
+
var viemChainsPromise = null;
|
|
1947
|
+
async function loadViemChains() {
|
|
1948
|
+
if (viemChainsById) return viemChainsById;
|
|
1949
|
+
if (!viemChainsPromise) {
|
|
1950
|
+
viemChainsPromise = import("viem/chains").then((module) => {
|
|
1951
|
+
const map = /* @__PURE__ */ new Map();
|
|
1952
|
+
for (const value of Object.values(module)) {
|
|
1953
|
+
if (value && typeof value === "object" && typeof value.id === "number" && value.rpcUrls?.default?.http?.length) {
|
|
1954
|
+
const chain = value;
|
|
1955
|
+
const existing = map.get(chain.id);
|
|
1956
|
+
if (existing) existing.push(chain);
|
|
1957
|
+
else map.set(chain.id, [chain]);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
viemChainsById = map;
|
|
1961
|
+
return map;
|
|
1962
|
+
});
|
|
1963
|
+
}
|
|
1964
|
+
return viemChainsPromise;
|
|
1965
|
+
}
|
|
1966
|
+
function pickViemChain(candidates, chain) {
|
|
1967
|
+
if (!candidates?.length) return void 0;
|
|
1968
|
+
if (candidates.length === 1) return candidates[0];
|
|
1969
|
+
const sameNetworkClass = candidates.filter(
|
|
1970
|
+
(candidate) => Boolean(candidate.testnet) === chain.testnet
|
|
1971
|
+
);
|
|
1972
|
+
if (sameNetworkClass.length === 1) return sameNetworkClass[0];
|
|
1973
|
+
const pool = sameNetworkClass.length > 0 ? sameNetworkClass : candidates;
|
|
1974
|
+
const normalized = chain.name.toLowerCase().replace(/\s+/g, "");
|
|
1975
|
+
const byName = pool.find(
|
|
1976
|
+
(candidate) => candidate.name.toLowerCase().replace(/\s+/g, "") === normalized
|
|
1977
|
+
);
|
|
1978
|
+
if (byName) return byName;
|
|
1979
|
+
return void 0;
|
|
1980
|
+
}
|
|
1981
|
+
function resolveRpcUrls(chain, override, viemChains) {
|
|
1982
|
+
const urls = [];
|
|
1983
|
+
if (override?.trim()) urls.push(override.trim());
|
|
1984
|
+
if (chain.publicRpcUrl) urls.push(chain.publicRpcUrl);
|
|
1985
|
+
if (chain.chainId !== null && chain.vmType === "evm") {
|
|
1986
|
+
const http2 = pickViemChain(viemChains?.get(chain.chainId), chain)?.rpcUrls?.default?.http;
|
|
1987
|
+
if (http2) urls.push(...http2);
|
|
1988
|
+
}
|
|
1989
|
+
return [...new Set(urls)];
|
|
1990
|
+
}
|
|
1991
|
+
function toViemChain(chain, override, viemChains) {
|
|
1992
|
+
if (chain.vmType !== "evm" || chain.chainId === null) return null;
|
|
1993
|
+
const rpcUrls = resolveRpcUrls(chain, override, viemChains);
|
|
1994
|
+
if (rpcUrls.length === 0) return null;
|
|
1995
|
+
const bundled = pickViemChain(viemChains?.get(chain.chainId), chain);
|
|
1996
|
+
if (bundled) {
|
|
1997
|
+
if (rpcUrls[0] === bundled.rpcUrls.default.http[0]) return bundled;
|
|
1998
|
+
return defineChain({
|
|
1999
|
+
...bundled,
|
|
2000
|
+
rpcUrls: { ...bundled.rpcUrls, default: { http: rpcUrls } }
|
|
2001
|
+
});
|
|
2002
|
+
}
|
|
2003
|
+
return defineChain({
|
|
2004
|
+
id: chain.chainId,
|
|
2005
|
+
name: chain.name,
|
|
2006
|
+
nativeCurrency: {
|
|
2007
|
+
name: chain.nativeToken.symbol,
|
|
2008
|
+
symbol: chain.nativeToken.symbol,
|
|
2009
|
+
decimals: chain.nativeToken.decimals
|
|
2010
|
+
},
|
|
2011
|
+
rpcUrls: { default: { http: rpcUrls } },
|
|
2012
|
+
blockExplorers: chain.explorer ? {
|
|
2013
|
+
default: {
|
|
2014
|
+
name: "Explorer",
|
|
2015
|
+
url: chain.explorer.url
|
|
2016
|
+
}
|
|
2017
|
+
} : void 0,
|
|
2018
|
+
testnet: chain.testnet
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
2021
|
+
function toViemChains(catalog, overrides, viemChains) {
|
|
2022
|
+
const chains = [];
|
|
2023
|
+
for (const entry of catalog.all) {
|
|
2024
|
+
const chain = toViemChain(
|
|
2025
|
+
entry,
|
|
2026
|
+
entry.chainId === null ? void 0 : overrides?.[entry.chainId],
|
|
2027
|
+
viemChains
|
|
2028
|
+
);
|
|
2029
|
+
if (chain) chains.push(chain);
|
|
2030
|
+
}
|
|
2031
|
+
return chains;
|
|
2032
|
+
}
|
|
2033
|
+
function needsViemChains(catalog, overrides) {
|
|
2034
|
+
return catalog.all.some(
|
|
2035
|
+
(chain) => chain.vmType === "evm" && chain.chainId !== null && !chain.publicRpcUrl && !overrides?.[chain.chainId]?.trim()
|
|
2036
|
+
);
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
// src/core/chain-catalog-context.tsx
|
|
2040
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
2041
|
+
var EMPTY = {
|
|
2042
|
+
catalog: null,
|
|
2043
|
+
viemChains: null,
|
|
2044
|
+
isLoading: true,
|
|
2045
|
+
shortlist: null,
|
|
2046
|
+
clientCapableChainIds: null
|
|
2047
|
+
};
|
|
2048
|
+
var ChainCatalogContext = createContext2(EMPTY);
|
|
2049
|
+
var resolvedChainsByKey = /* @__PURE__ */ new Map();
|
|
2050
|
+
function overridesKey(overrides) {
|
|
2051
|
+
return Object.entries(overrides ?? {}).map(([id, override]) => `${id}=${override ?? ""}`).sort().join("|");
|
|
2052
|
+
}
|
|
2053
|
+
function runtimeChainsKey(backendUrl, overrides) {
|
|
2054
|
+
return [backendUrl.replace(/\/$/, ""), overridesKey(overrides)].join("#");
|
|
2055
|
+
}
|
|
2056
|
+
var catalogByBackend = /* @__PURE__ */ new Map();
|
|
2057
|
+
function primeChainCatalog(backendUrl, debug = false) {
|
|
2058
|
+
const key = backendUrl.replace(/\/$/, "");
|
|
2059
|
+
let promise = catalogByBackend.get(key);
|
|
2060
|
+
if (!promise) {
|
|
2061
|
+
promise = createDepositService(key, {
|
|
2062
|
+
debug,
|
|
2063
|
+
debugScope: "service:chains"
|
|
2064
|
+
}).getChains();
|
|
2065
|
+
catalogByBackend.set(key, promise);
|
|
2066
|
+
promise.then((catalog) => {
|
|
2067
|
+
if (!catalog) catalogByBackend.delete(key);
|
|
2068
|
+
});
|
|
2069
|
+
}
|
|
2070
|
+
return promise;
|
|
2071
|
+
}
|
|
2072
|
+
function peekRuntimeChains(backendUrl, overrides) {
|
|
2073
|
+
return resolvedChainsByKey.get(runtimeChainsKey(backendUrl, overrides)) ?? null;
|
|
2074
|
+
}
|
|
2075
|
+
function publishCatalogTokens(catalog) {
|
|
2076
|
+
setRuntimeTokens(
|
|
2077
|
+
catalog.all.flatMap(
|
|
2078
|
+
(chain) => chain.chainId === null || !Array.isArray(chain.supportedTokens) ? [] : chain.supportedTokens.map((token) => ({
|
|
2079
|
+
chainId: chain.chainId,
|
|
2080
|
+
symbol: token.symbol,
|
|
2081
|
+
address: token.address,
|
|
2082
|
+
decimals: token.decimals
|
|
2083
|
+
}))
|
|
2084
|
+
)
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
function publishRuntimeChainMeta(catalog) {
|
|
2088
|
+
setRuntimeChainMeta(
|
|
2089
|
+
catalog.all.flatMap((chain) => {
|
|
2090
|
+
const ids = [];
|
|
2091
|
+
if (chain.chainId !== null) ids.push(chain.chainId);
|
|
2092
|
+
if (chain.caip2 === HYPERCORE_MAINNET_CAIP2) ids.push(HYPERCORE_CHAIN_ID);
|
|
2093
|
+
return ids.map((chainId) => ({
|
|
2094
|
+
chainId,
|
|
2095
|
+
name: chain.name,
|
|
2096
|
+
iconUrl: chain.iconUrl ?? void 0,
|
|
2097
|
+
nativeSymbol: chain.nativeToken.symbol
|
|
2098
|
+
}));
|
|
2099
|
+
})
|
|
2100
|
+
);
|
|
2101
|
+
}
|
|
2102
|
+
var runtimeChainsByBackend = /* @__PURE__ */ new Map();
|
|
2103
|
+
function primeRuntimeChains(backendUrl, overrides, debug = false) {
|
|
2104
|
+
const url = backendUrl.replace(/\/$/, "");
|
|
2105
|
+
const key = runtimeChainsKey(url, overrides);
|
|
2106
|
+
let promise = runtimeChainsByBackend.get(key);
|
|
2107
|
+
if (!promise) {
|
|
2108
|
+
promise = primeChainCatalog(url, debug).then(async (catalog) => {
|
|
2109
|
+
if (!catalog) return [];
|
|
2110
|
+
publishRuntimeChainMeta(catalog);
|
|
2111
|
+
publishCatalogTokens(catalog);
|
|
2112
|
+
const viemChains = needsViemChains(catalog, overrides) ? await loadViemChains() : null;
|
|
2113
|
+
const chains = toViemChains(catalog, overrides, viemChains);
|
|
2114
|
+
if (chains.length > 0) {
|
|
2115
|
+
setRuntimeChains(chains);
|
|
2116
|
+
resolvedChainsByKey.set(key, chains);
|
|
2117
|
+
}
|
|
2118
|
+
return chains;
|
|
2119
|
+
}).catch(() => []);
|
|
2120
|
+
runtimeChainsByBackend.set(key, promise);
|
|
2121
|
+
promise.then((chains) => {
|
|
2122
|
+
if (chains.length === 0) runtimeChainsByBackend.delete(key);
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
return promise;
|
|
2126
|
+
}
|
|
2127
|
+
function useChainCatalog() {
|
|
2128
|
+
return useContext2(ChainCatalogContext);
|
|
2129
|
+
}
|
|
2130
|
+
function useCatalogChain(chainId) {
|
|
2131
|
+
const { catalog } = useChainCatalog();
|
|
2132
|
+
if (!catalog || chainId == null) return void 0;
|
|
2133
|
+
return typeof chainId === "number" ? catalog.byChainId.get(chainId) : catalog.byCaip2.get(chainId);
|
|
2134
|
+
}
|
|
2135
|
+
function useDepositChainIds() {
|
|
2136
|
+
const { catalog } = useChainCatalog();
|
|
2137
|
+
return useMemo2(() => {
|
|
2138
|
+
if (!catalog) return getSupportedChainIds();
|
|
2139
|
+
const ids = catalog.all.filter(
|
|
2140
|
+
(c) => c.deposit && c.vmType === "evm" && c.chainId !== null && // `/chains` enumerates testnets; the bundled list never did, and a
|
|
2141
|
+
// production picker offering Sepolia next to Ethereum is a way to
|
|
2142
|
+
// lose funds. Reading the set at runtime must not quietly widen it
|
|
2143
|
+
// to a different KIND of chain.
|
|
2144
|
+
!c.testnet
|
|
2145
|
+
).map((c) => c.chainId);
|
|
2146
|
+
const rank = (id) => {
|
|
2147
|
+
const i = CHAIN_DISPLAY_ORDER.indexOf(id);
|
|
2148
|
+
return i === -1 ? CHAIN_DISPLAY_ORDER.length : i;
|
|
2149
|
+
};
|
|
2150
|
+
return ids.map((id, i) => ({ id, i })).sort((a, b) => rank(a.id) - rank(b.id) || a.i - b.i).map(({ id }) => id);
|
|
2151
|
+
}, [catalog]);
|
|
2152
|
+
}
|
|
2153
|
+
function useDestinationChains() {
|
|
2154
|
+
const { catalog } = useChainCatalog();
|
|
2155
|
+
return useMemo2(() => {
|
|
2156
|
+
if (!catalog) {
|
|
2157
|
+
return SOURCE_CHAINS.filter(
|
|
2158
|
+
(chain) => getSupportedTargetTokens(chain.id).length > 0
|
|
2159
|
+
).map((chain) => ({ id: chain.id, name: chain.name }));
|
|
2160
|
+
}
|
|
2161
|
+
const rank = (id) => {
|
|
2162
|
+
const i = CHAIN_DISPLAY_ORDER.indexOf(id);
|
|
2163
|
+
return i === -1 ? CHAIN_DISPLAY_ORDER.length : i;
|
|
2164
|
+
};
|
|
2165
|
+
return catalog.all.filter(
|
|
2166
|
+
(c) => c.destination && c.vmType === "evm" && c.chainId !== null && !c.testnet
|
|
2167
|
+
).map((c, i) => ({ id: c.chainId, name: c.name, i })).sort((a, b) => rank(a.id) - rank(b.id) || a.i - b.i).map(({ id, name }) => ({ id, name }));
|
|
2168
|
+
}, [catalog]);
|
|
2169
|
+
}
|
|
2170
|
+
function useTargetTokens() {
|
|
2171
|
+
const { catalog, shortlist } = useChainCatalog();
|
|
2172
|
+
return useMemo2(() => {
|
|
2173
|
+
return (chainId) => {
|
|
2174
|
+
const bundled = getBundledTargetTokens(chainId);
|
|
2175
|
+
if (bundled.length > 0) return bundled;
|
|
2176
|
+
const fromShortlist = shortlist?.[String(chainId)];
|
|
2177
|
+
if (fromShortlist?.length) {
|
|
2178
|
+
return fromShortlist.map((token) => ({
|
|
2179
|
+
symbol: token.symbol,
|
|
2180
|
+
address: token.address,
|
|
2181
|
+
decimals: token.decimals
|
|
2182
|
+
}));
|
|
2183
|
+
}
|
|
2184
|
+
const entry = catalog?.byChainId.get(chainId);
|
|
2185
|
+
return Array.isArray(entry?.supportedTokens) ? entry.supportedTokens.map((token) => ({
|
|
2186
|
+
symbol: token.symbol,
|
|
2187
|
+
address: token.address,
|
|
2188
|
+
decimals: token.decimals
|
|
2189
|
+
})) : [];
|
|
2190
|
+
};
|
|
2191
|
+
}, [catalog, shortlist]);
|
|
2192
|
+
}
|
|
2193
|
+
function useIsDepositChain() {
|
|
2194
|
+
const ids = useDepositChainIds();
|
|
2195
|
+
const { clientCapableChainIds } = useChainCatalog();
|
|
2196
|
+
return useMemo2(() => {
|
|
2197
|
+
const set = new Set(ids);
|
|
2198
|
+
return (chainId) => set.has(chainId) && (clientCapableChainIds === null || clientCapableChainIds.has(chainId));
|
|
2199
|
+
}, [ids, clientCapableChainIds]);
|
|
2200
|
+
}
|
|
2201
|
+
function useChainName() {
|
|
2202
|
+
const { catalog } = useChainCatalog();
|
|
2203
|
+
return useMemo2(() => {
|
|
2204
|
+
return (chainId) => {
|
|
2205
|
+
if (!catalog) return getChainName(chainId);
|
|
2206
|
+
const key = catalogKeyForChain(chainId);
|
|
2207
|
+
const entry = typeof key === "number" ? catalog.byChainId.get(key) : catalog.byCaip2.get(key);
|
|
2208
|
+
return entry?.name ?? getChainName(chainId);
|
|
2209
|
+
};
|
|
2210
|
+
}, [catalog]);
|
|
2211
|
+
}
|
|
2212
|
+
function useExplorerTxUrl() {
|
|
2213
|
+
const { catalog } = useChainCatalog();
|
|
2214
|
+
return useMemo2(() => {
|
|
2215
|
+
return (chainId, txHash) => {
|
|
2216
|
+
if (chainId === "hypercore") return getExplorerTxUrl(chainId, txHash);
|
|
2217
|
+
const key = catalog ? catalogKeyForChain(chainId) : void 0;
|
|
2218
|
+
const entry = key === void 0 ? void 0 : typeof key === "number" ? catalog?.byChainId.get(key) : catalog?.byCaip2.get(key);
|
|
2219
|
+
return catalogExplorerTxUrl(entry, txHash) ?? getExplorerTxUrl(chainId, txHash);
|
|
2220
|
+
};
|
|
2221
|
+
}, [catalog]);
|
|
2222
|
+
}
|
|
2223
|
+
function ChainCatalogProvider({
|
|
2224
|
+
service,
|
|
2225
|
+
rpcUrls,
|
|
2226
|
+
children
|
|
2227
|
+
}) {
|
|
2228
|
+
const [catalog, setCatalog] = useState2(null);
|
|
2229
|
+
const [viemChains, setViemChains] = useState2(null);
|
|
2230
|
+
const [isLoading, setIsLoading] = useState2(true);
|
|
2231
|
+
useEffect2(() => {
|
|
2232
|
+
let active = true;
|
|
2233
|
+
setIsLoading(true);
|
|
2234
|
+
service.getChains().then((next) => {
|
|
2235
|
+
if (!active) return;
|
|
2236
|
+
setCatalog(next);
|
|
2237
|
+
setIsLoading(false);
|
|
2238
|
+
});
|
|
2239
|
+
return () => {
|
|
2240
|
+
active = false;
|
|
2241
|
+
};
|
|
2242
|
+
}, [service]);
|
|
2243
|
+
const overrides = useMemo2(() => {
|
|
2244
|
+
if (!rpcUrls) return void 0;
|
|
2245
|
+
const out = {};
|
|
2246
|
+
for (const [key, url] of Object.entries(rpcUrls)) {
|
|
2247
|
+
const id = Number(key);
|
|
2248
|
+
if (Number.isFinite(id) && typeof url === "string") out[id] = url;
|
|
2249
|
+
}
|
|
2250
|
+
return out;
|
|
2251
|
+
}, [rpcUrls]);
|
|
2252
|
+
const overrideKey = overridesKey(overrides);
|
|
2253
|
+
useEffect2(() => {
|
|
2254
|
+
if (!catalog || viemChains) return;
|
|
2255
|
+
if (!needsViemChains(catalog, overrides)) return;
|
|
2256
|
+
let active = true;
|
|
2257
|
+
loadViemChains().then((chains) => {
|
|
2258
|
+
if (active) setViemChains(chains);
|
|
2259
|
+
});
|
|
2260
|
+
return () => {
|
|
2261
|
+
active = false;
|
|
2262
|
+
};
|
|
2263
|
+
}, [catalog, viemChains, overrideKey]);
|
|
2264
|
+
useEffect2(() => {
|
|
2265
|
+
if (!catalog) return;
|
|
2266
|
+
publishRuntimeChainMeta(catalog);
|
|
2267
|
+
publishCatalogTokens(catalog);
|
|
2268
|
+
const chains = toViemChains(catalog, overrides, viemChains);
|
|
2269
|
+
if (chains.length > 0) setRuntimeChains(chains);
|
|
2270
|
+
}, [catalog, viemChains, overrides]);
|
|
2271
|
+
const [shortlist, setShortlist] = useState2(null);
|
|
2272
|
+
useEffect2(() => {
|
|
2273
|
+
let active = true;
|
|
2274
|
+
setShortlist(null);
|
|
2275
|
+
service.getTopTokens().then((tokens) => {
|
|
2276
|
+
if (!active || !tokens) return;
|
|
2277
|
+
publishShortlistTokens(tokens);
|
|
2278
|
+
setShortlist(tokens);
|
|
2279
|
+
});
|
|
2280
|
+
return () => {
|
|
2281
|
+
active = false;
|
|
2282
|
+
};
|
|
2283
|
+
}, [service]);
|
|
2284
|
+
const clientCapableChainIds = useMemo2(() => {
|
|
2285
|
+
if (!catalog) return null;
|
|
2286
|
+
return new Set(
|
|
2287
|
+
toViemChains(catalog, overrides, viemChains).map((c) => c.id)
|
|
2288
|
+
);
|
|
2289
|
+
}, [catalog, viemChains, overrideKey]);
|
|
2290
|
+
const value = useMemo2(
|
|
2291
|
+
() => ({
|
|
2292
|
+
catalog,
|
|
2293
|
+
viemChains,
|
|
2294
|
+
isLoading,
|
|
2295
|
+
shortlist,
|
|
2296
|
+
clientCapableChainIds
|
|
2297
|
+
}),
|
|
2298
|
+
[catalog, viemChains, isLoading, shortlist, clientCapableChainIds]
|
|
2299
|
+
);
|
|
2300
|
+
return /* @__PURE__ */ jsx6(ChainCatalogContext.Provider, { value, children });
|
|
2301
|
+
}
|
|
2302
|
+
|
|
2303
|
+
// src/core/useLatestRef.ts
|
|
2304
|
+
import { useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
2305
|
+
function useLatestRef(value) {
|
|
2306
|
+
const ref = useRef2(value);
|
|
2307
|
+
useEffect3(() => {
|
|
2308
|
+
ref.current = value;
|
|
2309
|
+
}, [value]);
|
|
2310
|
+
return ref;
|
|
2311
|
+
}
|
|
2312
|
+
|
|
2313
|
+
// src/components/ui/Spinner.tsx
|
|
2314
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2315
|
+
function Spinner({ className }) {
|
|
2316
|
+
return /* @__PURE__ */ jsxs4(
|
|
2317
|
+
"svg",
|
|
2318
|
+
{
|
|
2319
|
+
className: `rs-spinner ${className || ""}`,
|
|
2320
|
+
fill: "none",
|
|
2321
|
+
viewBox: "0 0 20 21",
|
|
2322
|
+
children: [
|
|
2323
|
+
/* @__PURE__ */ jsx7(
|
|
2324
|
+
"path",
|
|
2325
|
+
{
|
|
2326
|
+
d: "M10 0.5C8.02 0.5 6.08 1.08 4.44 2.18C2.79 3.28 1.51 4.84 0.76 6.67C0.00 8.50 -0.19 10.51 0.19 12.45C0.57 14.39 1.53 16.17 2.92 17.57C4.32 18.96 6.10 19.92 8.04 20.30C9.98 20.69 11.99 20.49 13.82 19.73C15.65 18.98 17.21 17.70 18.31 16.05C19.41 14.41 20 12.47 20 10.5C20 7.84 18.94 5.30 17.07 3.42C15.19 1.55 12.65 0.5 10 0.5ZM10 17.77C8.56 17.77 7.15 17.34 5.95 16.54C4.76 15.74 3.83 14.61 3.28 13.28C2.73 11.95 2.58 10.49 2.86 9.08C3.14 7.67 3.84 6.37 4.85 5.35C5.87 4.34 7.17 3.64 8.58 3.36C9.99 3.08 11.45 3.23 12.78 3.78C14.11 4.33 15.24 5.26 16.04 6.45C16.84 7.65 17.27 9.06 17.27 10.5C17.27 12.42 16.50 14.27 15.14 15.64C13.77 17.00 11.92 17.77 10 17.77Z",
|
|
2327
|
+
fill: "currentColor",
|
|
2328
|
+
opacity: 0.3
|
|
2329
|
+
}
|
|
2330
|
+
),
|
|
2331
|
+
/* @__PURE__ */ jsx7(
|
|
2332
|
+
"path",
|
|
2333
|
+
{
|
|
2334
|
+
d: "M10 3.22C11.74 3.22 13.42 3.84 14.75 4.95C16.08 6.07 16.96 7.61 17.25 9.31C17.30 9.64 17.46 9.94 17.71 10.15C17.96 10.37 18.28 10.49 18.62 10.5C18.82 10.50 19.01 10.45 19.20 10.37C19.38 10.29 19.54 10.16 19.67 10.01C19.80 9.86 19.89 9.68 19.95 9.49C20.00 9.30 20.01 9.10 19.98 8.90C19.59 6.56 18.38 4.42 16.55 2.88C14.72 1.34 12.40 0.5 10 0.5C7.59 0.5 5.27 1.34 3.44 2.88C1.61 4.42 0.40 6.56 0.01 8.90C-0.01 9.10 -0.00 9.30 0.04 9.49C0.10 9.68 0.19 9.86 0.32 10.01C0.45 10.16 0.61 10.29 0.79 10.37C0.98 10.45 1.17 10.50 1.37 10.5C1.71 10.49 2.03 10.37 2.28 10.15C2.53 9.94 2.69 9.64 2.74 9.31C3.03 7.61 3.91 6.07 5.24 4.95C6.57 3.84 8.25 3.22 10 3.22Z",
|
|
2335
|
+
fill: "currentColor"
|
|
2336
|
+
}
|
|
2337
|
+
)
|
|
2338
|
+
]
|
|
2339
|
+
}
|
|
2340
|
+
);
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
// src/components/ui/Button.tsx
|
|
2344
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2345
|
+
function Button({
|
|
2346
|
+
children,
|
|
2347
|
+
variant = "accent",
|
|
2348
|
+
size = "default",
|
|
2349
|
+
loading = false,
|
|
2350
|
+
loadingText,
|
|
2351
|
+
fullWidth = false,
|
|
2352
|
+
disabled,
|
|
2353
|
+
className = "",
|
|
2354
|
+
...props
|
|
2355
|
+
}) {
|
|
2356
|
+
const classes = [
|
|
2357
|
+
"rs-button",
|
|
2358
|
+
`rs-button--${variant}`,
|
|
2359
|
+
`rs-button--size-${size}`,
|
|
2360
|
+
fullWidth ? "rs-button--full-width" : "",
|
|
2361
|
+
className
|
|
2362
|
+
].filter(Boolean).join(" ");
|
|
2363
|
+
const showInlineLoadingText = loading && loadingText !== void 0;
|
|
2364
|
+
return /* @__PURE__ */ jsx8(
|
|
2365
|
+
"button",
|
|
2366
|
+
{
|
|
2367
|
+
className: classes,
|
|
2368
|
+
disabled: disabled || loading,
|
|
2369
|
+
"aria-busy": loading || void 0,
|
|
2370
|
+
...props,
|
|
2371
|
+
children: showInlineLoadingText ? /* @__PURE__ */ jsxs5("span", { className: "rs-button__loading-row", children: [
|
|
2372
|
+
/* @__PURE__ */ jsx8(Spinner, { className: "rs-spinner--sm" }),
|
|
2373
|
+
/* @__PURE__ */ jsx8("span", { children: loadingText })
|
|
2374
|
+
] }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2375
|
+
/* @__PURE__ */ jsx8("span", { className: loading ? "rs-button__content--hidden" : "", children }),
|
|
2376
|
+
loading && /* @__PURE__ */ jsx8("span", { className: "rs-button__spinner", children: /* @__PURE__ */ jsx8(Spinner, { className: "rs-spinner--sm" }) })
|
|
2377
|
+
] })
|
|
2378
|
+
}
|
|
2379
|
+
);
|
|
2380
|
+
}
|
|
2381
|
+
Button.displayName = "Button";
|
|
2382
|
+
|
|
2383
|
+
// src/components/ui/Callout.tsx
|
|
2384
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2385
|
+
function CircleAlertIcon() {
|
|
2386
|
+
return /* @__PURE__ */ jsx9(
|
|
2387
|
+
"svg",
|
|
2388
|
+
{
|
|
2389
|
+
width: "16",
|
|
2390
|
+
height: "16",
|
|
2391
|
+
viewBox: "0 0 16 16",
|
|
2392
|
+
fill: "none",
|
|
2393
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2394
|
+
"aria-hidden": "true",
|
|
2395
|
+
children: /* @__PURE__ */ jsx9(
|
|
2396
|
+
"path",
|
|
2397
|
+
{
|
|
2398
|
+
d: "M10 5.99L6 9.99M6 5.99L10 9.99M14.66 7.99C14.66 11.68 11.68 14.66 8 14.66C4.31 14.66 1.33 11.68 1.33 7.99C1.33 4.31 4.31 1.33 8 1.33C11.68 1.33 14.66 4.31 14.66 7.99Z",
|
|
2399
|
+
stroke: "currentColor",
|
|
2400
|
+
strokeWidth: "1.33",
|
|
2401
|
+
strokeLinecap: "round",
|
|
2402
|
+
strokeLinejoin: "round"
|
|
2403
|
+
}
|
|
2404
|
+
)
|
|
2405
|
+
}
|
|
2406
|
+
);
|
|
2407
|
+
}
|
|
2408
|
+
function Callout({ variant = "error", children, role }) {
|
|
2409
|
+
return /* @__PURE__ */ jsxs6(
|
|
2410
|
+
"div",
|
|
2411
|
+
{
|
|
2412
|
+
className: `rs-callout rs-callout--${variant}`,
|
|
2413
|
+
role: role ?? (variant === "error" ? "alert" : "status"),
|
|
2414
|
+
children: [
|
|
2415
|
+
/* @__PURE__ */ jsx9("span", { className: "rs-callout-icon", children: variant === "error" ? /* @__PURE__ */ jsx9(CircleAlertIcon, {}) : /* @__PURE__ */ jsx9(AlertTriangleIcon, {}) }),
|
|
2416
|
+
/* @__PURE__ */ jsx9("span", { className: "rs-callout-text", children })
|
|
2417
|
+
]
|
|
2418
|
+
}
|
|
2419
|
+
);
|
|
2420
|
+
}
|
|
2421
|
+
Callout.displayName = "Callout";
|
|
2422
|
+
|
|
2423
|
+
// src/components/ui/TokenIcon.tsx
|
|
2424
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
2425
|
+
function TokenIcon({ symbol, className, fallback }) {
|
|
2426
|
+
return /* @__PURE__ */ jsx10(
|
|
2427
|
+
CdnIcon,
|
|
2428
|
+
{
|
|
2429
|
+
src: tokenIconUrl(symbol),
|
|
2430
|
+
className: `rs-token-icon ${className ?? ""}`.trimEnd(),
|
|
2431
|
+
fallback
|
|
2432
|
+
}
|
|
2433
|
+
);
|
|
2434
|
+
}
|
|
2435
|
+
TokenIcon.displayName = "TokenIcon";
|
|
2436
|
+
|
|
1869
2437
|
// src/core/formatters.ts
|
|
1870
2438
|
var currencyFormatter = new Intl.NumberFormat("en-US", {
|
|
1871
2439
|
style: "currency",
|
|
@@ -1882,6 +2450,22 @@ function isUnsupportedChainSwitchError(error) {
|
|
|
1882
2450
|
const message = (error instanceof Error ? error.message : String(error)).toLowerCase();
|
|
1883
2451
|
return name === "SwitchChainNotSupportedError" || message.includes("does not support programmatic chain switching") || message.includes("switch chain not supported") || message.includes("method not found") || message.includes("does not exist") || message.includes("is not available");
|
|
1884
2452
|
}
|
|
2453
|
+
var OPAQUE_REVERT_REASONS = [
|
|
2454
|
+
"unexpected error",
|
|
2455
|
+
"internal error",
|
|
2456
|
+
"unknown error",
|
|
2457
|
+
"internal json-rpc error"
|
|
2458
|
+
];
|
|
2459
|
+
var DETAIL_SECTION_HEADINGS = [
|
|
2460
|
+
"Request Arguments:",
|
|
2461
|
+
"Raw Call Arguments:",
|
|
2462
|
+
"Request body:",
|
|
2463
|
+
"Contract Call:",
|
|
2464
|
+
"Docs:",
|
|
2465
|
+
"Details:",
|
|
2466
|
+
"Version:",
|
|
2467
|
+
"URL:"
|
|
2468
|
+
];
|
|
1885
2469
|
function formatUserError(raw) {
|
|
1886
2470
|
const lower = raw.toLowerCase();
|
|
1887
2471
|
if (lower.includes("user rejected") || lower.includes("user denied")) {
|
|
@@ -1893,6 +2477,22 @@ function formatUserError(raw) {
|
|
|
1893
2477
|
if (lower.includes("nonce too low") || lower.includes("nonce too high")) {
|
|
1894
2478
|
return "Transaction conflict \u2014 please try again";
|
|
1895
2479
|
}
|
|
2480
|
+
const revertMarker = "reverted with the following reason:";
|
|
2481
|
+
const revertIdx = lower.indexOf(revertMarker);
|
|
2482
|
+
const revertReason = revertIdx === -1 ? null : raw.slice(revertIdx + revertMarker.length).split(/\n[^\S\n]*\n/)[0].split("\n").map((line) => line.trim()).find(
|
|
2483
|
+
(line) => line.length > 0 && !DETAIL_SECTION_HEADINGS.some(
|
|
2484
|
+
(heading) => line.startsWith(heading)
|
|
2485
|
+
)
|
|
2486
|
+
) ?? "";
|
|
2487
|
+
if (revertReason !== null) {
|
|
2488
|
+
const reasonLower = revertReason.toLowerCase();
|
|
2489
|
+
if (reasonLower.includes("execution reverted")) {
|
|
2490
|
+
return "Transaction would fail on-chain";
|
|
2491
|
+
}
|
|
2492
|
+
if (revertReason === "" || revertReason === "0x" || OPAQUE_REVERT_REASONS.some((opaque) => reasonLower.includes(opaque))) {
|
|
2493
|
+
return "Your wallet couldn't send the transaction \u2014 please try again";
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
1896
2496
|
if (lower.includes("execution reverted")) {
|
|
1897
2497
|
return "Transaction would fail on-chain";
|
|
1898
2498
|
}
|
|
@@ -1911,7 +2511,7 @@ function formatUserError(raw) {
|
|
|
1911
2511
|
if (lower.includes("rate limit") || lower.includes("429")) {
|
|
1912
2512
|
return "Rate limited \u2014 please try again shortly";
|
|
1913
2513
|
}
|
|
1914
|
-
let cleaned = raw;
|
|
2514
|
+
let cleaned = revertReason || raw;
|
|
1915
2515
|
const stripMarkers = [
|
|
1916
2516
|
"\n\nRequest Arguments:",
|
|
1917
2517
|
"\nRaw Call Arguments:",
|
|
@@ -2076,26 +2676,6 @@ function formatReceiveEstimate(params) {
|
|
|
2076
2676
|
return sameSymbol ? `${formatted} ${params.targetSymbol}` : `~${formatted} ${params.targetSymbol}`;
|
|
2077
2677
|
}
|
|
2078
2678
|
|
|
2079
|
-
// src/core/rpc.ts
|
|
2080
|
-
import { createContext, useContext, useMemo } from "react";
|
|
2081
|
-
function rpcUrlFor(rpcUrls, chain) {
|
|
2082
|
-
const url = rpcUrls?.[chain]?.trim();
|
|
2083
|
-
return url ? url : void 0;
|
|
2084
|
-
}
|
|
2085
|
-
var RpcUrlsContext = createContext(void 0);
|
|
2086
|
-
var RpcUrlsProvider = RpcUrlsContext.Provider;
|
|
2087
|
-
function useRpcUrls() {
|
|
2088
|
-
return useContext(RpcUrlsContext);
|
|
2089
|
-
}
|
|
2090
|
-
function rpcUrlsKey(rpcUrls) {
|
|
2091
|
-
if (!rpcUrls) return "";
|
|
2092
|
-
return Object.entries(rpcUrls).map(([chain, url]) => [chain, url?.trim() ?? ""]).filter(([, url]) => url !== "").map(([chain, url]) => `${chain}=${url}`).sort().join("|");
|
|
2093
|
-
}
|
|
2094
|
-
function useStableRpcUrls(rpcUrls) {
|
|
2095
|
-
const key = rpcUrlsKey(rpcUrls);
|
|
2096
|
-
return useMemo(() => rpcUrls, [key]);
|
|
2097
|
-
}
|
|
2098
|
-
|
|
2099
2679
|
// src/core/theme.ts
|
|
2100
2680
|
var RADIUS_SCALE = {
|
|
2101
2681
|
none: { sm: "0", md: "0", lg: "0" },
|
|
@@ -2296,10 +2876,7 @@ export {
|
|
|
2296
2876
|
CdnIcon,
|
|
2297
2877
|
PoweredBy,
|
|
2298
2878
|
Spinner,
|
|
2299
|
-
|
|
2300
|
-
Button,
|
|
2301
|
-
Callout,
|
|
2302
|
-
TokenIcon,
|
|
2879
|
+
catalogKeyForChain,
|
|
2303
2880
|
debugLog,
|
|
2304
2881
|
debugError,
|
|
2305
2882
|
getAssetId,
|
|
@@ -2310,8 +2887,29 @@ export {
|
|
|
2310
2887
|
quoteFeeRow,
|
|
2311
2888
|
quoteFeeGroups,
|
|
2312
2889
|
SwappedConnectFeeChangedError,
|
|
2890
|
+
SUPPORTED_CONNECT_EXCHANGE_COUNT,
|
|
2313
2891
|
resolveAppFeeBps,
|
|
2314
2892
|
createDepositService,
|
|
2893
|
+
rpcUrlFor,
|
|
2894
|
+
RpcUrlsProvider,
|
|
2895
|
+
useRpcUrls,
|
|
2896
|
+
useStableRpcUrls,
|
|
2897
|
+
getPublicClient,
|
|
2898
|
+
peekRuntimeChains,
|
|
2899
|
+
primeRuntimeChains,
|
|
2900
|
+
useChainCatalog,
|
|
2901
|
+
useCatalogChain,
|
|
2902
|
+
useDepositChainIds,
|
|
2903
|
+
useDestinationChains,
|
|
2904
|
+
useTargetTokens,
|
|
2905
|
+
useIsDepositChain,
|
|
2906
|
+
useChainName,
|
|
2907
|
+
useExplorerTxUrl,
|
|
2908
|
+
ChainCatalogProvider,
|
|
2909
|
+
useLatestRef,
|
|
2910
|
+
Button,
|
|
2911
|
+
Callout,
|
|
2912
|
+
TokenIcon,
|
|
2315
2913
|
currencyFormatter,
|
|
2316
2914
|
tokenFormatter,
|
|
2317
2915
|
isUnsupportedChainSwitchError,
|
|
@@ -2325,10 +2923,6 @@ export {
|
|
|
2325
2923
|
estimateReceiveAmount,
|
|
2326
2924
|
formatQuotedReceive,
|
|
2327
2925
|
formatReceiveEstimate,
|
|
2328
|
-
rpcUrlFor,
|
|
2329
|
-
RpcUrlsProvider,
|
|
2330
|
-
useRpcUrls,
|
|
2331
|
-
useStableRpcUrls,
|
|
2332
2926
|
applyTheme,
|
|
2333
2927
|
checkBackendUrl
|
|
2334
2928
|
};
|