@rash2x/bridge-widget 0.1.4 → 0.1.6
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/evaa-bridge.cjs +697 -389
- package/dist/evaa-bridge.cjs.map +1 -1
- package/dist/evaa-bridge.mjs +703 -395
- package/dist/evaa-bridge.mjs.map +1 -1
- package/dist/index.d.ts +8 -3
- package/package.json +7 -11
package/dist/evaa-bridge.mjs
CHANGED
|
@@ -4,7 +4,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
4
4
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
6
|
import * as require$$0 from "react";
|
|
7
|
-
import require$$0__default, { useState, useCallback,
|
|
7
|
+
import require$$0__default, { useState, useCallback, createContext, useContext, useRef, useEffect, useMemo, memo, forwardRef } from "react";
|
|
8
8
|
import { create as create$1 } from "zustand";
|
|
9
9
|
import { Slot } from "@radix-ui/react-slot";
|
|
10
10
|
import { cva } from "class-variance-authority";
|
|
@@ -13,19 +13,20 @@ import { twMerge } from "tailwind-merge";
|
|
|
13
13
|
import { createPortal } from "react-dom";
|
|
14
14
|
import { AnimatePresence, motion } from "framer-motion";
|
|
15
15
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
16
|
-
import { useAccount, useDisconnect, useWalletClient } from "wagmi";
|
|
16
|
+
import { useAccount, useConnect, useDisconnect, useWalletClient, usePublicClient } from "wagmi";
|
|
17
17
|
import { useWallet } from "@tronweb3/tronwallet-adapter-react-hooks";
|
|
18
18
|
import { useTonAddress, useTonConnectUI } from "@tonconnect/ui-react";
|
|
19
19
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
20
|
-
import { Address, Cell } from "@ton/core";
|
|
20
|
+
import { Address, beginCell as beginCell$1, storeMessage, loadMessage, Cell } from "@ton/core";
|
|
21
21
|
import { VariableSizeList } from "react-window";
|
|
22
22
|
import * as SwitchPrimitive from "@radix-ui/react-switch";
|
|
23
23
|
import { X, ChevronDownIcon } from "lucide-react";
|
|
24
24
|
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
|
25
|
-
import { ConnectKitButton } from "connectkit";
|
|
26
25
|
import { t } from "i18next";
|
|
27
26
|
import { toast, Toaster } from "sonner";
|
|
28
|
-
import {
|
|
27
|
+
import { BrowserProvider, Contract, parseUnits } from "ethers";
|
|
28
|
+
import { isAddress, formatUnits } from "viem";
|
|
29
|
+
import { TonClient, Address as Address$1, beginCell } from "@ton/ton";
|
|
29
30
|
import { TronLinkAdapterName } from "@tronweb3/tronwallet-adapters";
|
|
30
31
|
const norm = (s) => (s ?? "").toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
|
|
31
32
|
const POPULAR_ORDER = [
|
|
@@ -509,7 +510,7 @@ function cn(...inputs) {
|
|
|
509
510
|
return twMerge(clsx(inputs));
|
|
510
511
|
}
|
|
511
512
|
const buttonVariants = cva(
|
|
512
|
-
"inline-flex items-center rounded-full justify-center gap-2 whitespace-nowrap text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
513
|
+
"inline-flex items-center rounded-full text-lg justify-center gap-2 whitespace-nowrap text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
513
514
|
{
|
|
514
515
|
variants: {
|
|
515
516
|
variant: {
|
|
@@ -549,6 +550,23 @@ const Button = require$$0.forwardRef(
|
|
|
549
550
|
}
|
|
550
551
|
);
|
|
551
552
|
Button.displayName = "Button";
|
|
553
|
+
const ModalContainerContext = createContext(void 0);
|
|
554
|
+
const ModalContainerProvider = ({
|
|
555
|
+
containerId,
|
|
556
|
+
children
|
|
557
|
+
}) => {
|
|
558
|
+
return /* @__PURE__ */ jsx(ModalContainerContext.Provider, { value: containerId, children });
|
|
559
|
+
};
|
|
560
|
+
const useModalContainer = () => {
|
|
561
|
+
const containerId = useContext(ModalContainerContext);
|
|
562
|
+
if (typeof document === "undefined") {
|
|
563
|
+
return null;
|
|
564
|
+
}
|
|
565
|
+
if (!containerId) {
|
|
566
|
+
return document.body;
|
|
567
|
+
}
|
|
568
|
+
return document.getElementById(containerId) || document.body;
|
|
569
|
+
};
|
|
552
570
|
const ModalContent = ({ children, className }) => {
|
|
553
571
|
return /* @__PURE__ */ jsx("div", { className: cn("p-5 flex flex-col h-full", className), children });
|
|
554
572
|
};
|
|
@@ -602,11 +620,11 @@ const Modal = ({
|
|
|
602
620
|
isOpen,
|
|
603
621
|
onClose,
|
|
604
622
|
children,
|
|
605
|
-
className
|
|
606
|
-
modalContainer
|
|
623
|
+
className
|
|
607
624
|
}) => {
|
|
608
625
|
const panelRef = useRef(null);
|
|
609
626
|
const lastActiveRef = useRef(null);
|
|
627
|
+
const container = useModalContainer();
|
|
610
628
|
useEffect(() => {
|
|
611
629
|
if (!isOpen) return;
|
|
612
630
|
lastActiveRef.current = document.activeElement;
|
|
@@ -628,7 +646,6 @@ const Modal = ({
|
|
|
628
646
|
return () => window.removeEventListener("keydown", onKey);
|
|
629
647
|
}, [isOpen, onClose]);
|
|
630
648
|
if (typeof document === "undefined") return null;
|
|
631
|
-
const container = modalContainer || document.body;
|
|
632
649
|
return createPortal(
|
|
633
650
|
/* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(
|
|
634
651
|
motion.div,
|
|
@@ -782,19 +799,6 @@ const Tip = (props) => {
|
|
|
782
799
|
/* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: text }) })
|
|
783
800
|
] });
|
|
784
801
|
};
|
|
785
|
-
function toLD(human, decimals) {
|
|
786
|
-
const [i = "0", f = ""] = human.replace(",", ".").split(".");
|
|
787
|
-
const frac = (f + "0".repeat(decimals)).slice(0, decimals);
|
|
788
|
-
return BigInt(i + frac).toString();
|
|
789
|
-
}
|
|
790
|
-
function fromLD(ld, decimals) {
|
|
791
|
-
const bi = BigInt(ld || "0");
|
|
792
|
-
if (decimals === 0) return Number(bi);
|
|
793
|
-
const base = BigInt(10) ** BigInt(decimals);
|
|
794
|
-
const int = bi / base;
|
|
795
|
-
const frac = Number(bi % base) / Number(base);
|
|
796
|
-
return Number(int) + frac;
|
|
797
|
-
}
|
|
798
802
|
async function getChains() {
|
|
799
803
|
const res = await fetch("https://stargate.finance/api/v1/chains", {
|
|
800
804
|
credentials: "same-origin"
|
|
@@ -842,49 +846,16 @@ async function getDestTokens(srcChainKey, srcTokenAddr) {
|
|
|
842
846
|
});
|
|
843
847
|
return unique;
|
|
844
848
|
}
|
|
845
|
-
|
|
846
|
-
function normalizeTickerSymbol(s) {
|
|
849
|
+
function normalizeTickerSymbol$1(s) {
|
|
847
850
|
return s.toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
|
|
848
851
|
}
|
|
849
|
-
async function getSwapBalances(accountFriendly) {
|
|
850
|
-
if (!isTonFriendly(accountFriendly)) throw new Error("Invalid TON address");
|
|
851
|
-
const accRes = await fetch(
|
|
852
|
-
`https://tonapi.io/v2/accounts/${accountFriendly}`
|
|
853
|
-
);
|
|
854
|
-
if (!accRes.ok) throw new Error(`TON account fetch failed: ${accRes.status}`);
|
|
855
|
-
const acc = await accRes.json();
|
|
856
|
-
const ton = fromLD(String(acc?.balance ?? "0"), 9);
|
|
857
|
-
const result = {
|
|
858
|
-
TON: { balance: ton, address: "ton-native" }
|
|
859
|
-
};
|
|
860
|
-
const jetsRes = await fetch(
|
|
861
|
-
`https://tonapi.io/v2/accounts/${accountFriendly}/jettons?limit=200`
|
|
862
|
-
);
|
|
863
|
-
if (!jetsRes.ok) return result;
|
|
864
|
-
const jets = await jetsRes.json();
|
|
865
|
-
const items = jets?.balances ?? jets?.jettons ?? jets?.items ?? [];
|
|
866
|
-
for (const it of items) {
|
|
867
|
-
const rawSym = (it?.jetton?.symbol ?? it?.symbol ?? "").toString();
|
|
868
|
-
if (!rawSym) continue;
|
|
869
|
-
const symUpper = rawSym.toUpperCase();
|
|
870
|
-
const symNorm = normalizeTickerSymbol(symUpper);
|
|
871
|
-
const master = (it?.jetton?.address ?? it?.address ?? "").toString();
|
|
872
|
-
const decimals = Number(it?.jetton?.decimals ?? it?.decimals ?? 9) || 9;
|
|
873
|
-
const raw = (it?.balance ?? "0").toString();
|
|
874
|
-
const human = fromLD(raw, decimals);
|
|
875
|
-
const entry = { balance: human, address: master };
|
|
876
|
-
result[symUpper] = entry;
|
|
877
|
-
if (symNorm !== symUpper) result[symNorm] = entry;
|
|
878
|
-
}
|
|
879
|
-
return result;
|
|
880
|
-
}
|
|
881
852
|
const BASE_URL$1 = "https://icons-ckg.pages.dev/stargate-light/tokens";
|
|
882
853
|
const TokenSymbol = ({
|
|
883
854
|
symbol,
|
|
884
855
|
className = "w-4 h-4",
|
|
885
856
|
alt
|
|
886
857
|
}) => {
|
|
887
|
-
const normalizedSymbol = normalizeTickerSymbol(symbol).toLowerCase();
|
|
858
|
+
const normalizedSymbol = normalizeTickerSymbol$1(symbol).toLowerCase();
|
|
888
859
|
const src = `${BASE_URL$1}/${normalizedSymbol}.svg`;
|
|
889
860
|
return /* @__PURE__ */ jsx("img", { src, alt: alt ?? symbol, className });
|
|
890
861
|
};
|
|
@@ -1094,8 +1065,7 @@ const routePresets = [
|
|
|
1094
1065
|
];
|
|
1095
1066
|
const SettingModal = ({
|
|
1096
1067
|
isOpen,
|
|
1097
|
-
onClose
|
|
1098
|
-
modalContainer
|
|
1068
|
+
onClose
|
|
1099
1069
|
}) => {
|
|
1100
1070
|
const { t: t2 } = useTranslation();
|
|
1101
1071
|
const { toChain } = useChainsStore();
|
|
@@ -1129,7 +1099,7 @@ const SettingModal = ({
|
|
|
1129
1099
|
);
|
|
1130
1100
|
const activeBtn = "bg-settings-active hover:bg-settings-active/80 text-settings-active-foreground";
|
|
1131
1101
|
const notActiveBtn = "bg-settings-button hover:bg-settings-button/80 text-settings-button-foreground";
|
|
1132
|
-
return /* @__PURE__ */ jsx(Modal, { isOpen, onClose,
|
|
1102
|
+
return /* @__PURE__ */ jsx(Modal, { isOpen, onClose, children: /* @__PURE__ */ jsxs(ModalContent, { children: [
|
|
1133
1103
|
/* @__PURE__ */ jsxs(ModalHeader, { children: [
|
|
1134
1104
|
/* @__PURE__ */ jsx(ModalTitle, { children: t2("settings.title", { defaultValue: "Settings" }) }),
|
|
1135
1105
|
/* @__PURE__ */ jsx(ModalClose, { className: "", onClick: onClose, children: /* @__PURE__ */ jsx(CloseIcon, { className: "size-6 p-0 [&>rect]:fill-modal-x [&>path]:stroke-modal-x-foreground" }) })
|
|
@@ -1298,6 +1268,19 @@ function useChainStrategies() {
|
|
|
1298
1268
|
}
|
|
1299
1269
|
return context;
|
|
1300
1270
|
}
|
|
1271
|
+
function toLD(human, decimals) {
|
|
1272
|
+
const [i = "0", f = ""] = human.replace(",", ".").split(".");
|
|
1273
|
+
const frac = (f + "0".repeat(decimals)).slice(0, decimals);
|
|
1274
|
+
return BigInt(i + frac).toString();
|
|
1275
|
+
}
|
|
1276
|
+
function fromLD(ld, decimals) {
|
|
1277
|
+
const bi = BigInt(ld || "0");
|
|
1278
|
+
if (decimals === 0) return Number(bi);
|
|
1279
|
+
const base = BigInt(10) ** BigInt(decimals);
|
|
1280
|
+
const int = bi / base;
|
|
1281
|
+
const frac = Number(bi % base) / Number(base);
|
|
1282
|
+
return Number(int) + frac;
|
|
1283
|
+
}
|
|
1301
1284
|
function resolveTokenOnChainFromMatrix$2(assetMatrix, assetSymbol, chainKey) {
|
|
1302
1285
|
if (!assetMatrix || !assetSymbol || !chainKey) return void 0;
|
|
1303
1286
|
const byChain = assetMatrix[assetSymbol.toUpperCase()];
|
|
@@ -1479,20 +1462,17 @@ function useBalances(chainKey, address) {
|
|
|
1479
1462
|
const data = query.data;
|
|
1480
1463
|
if (data) {
|
|
1481
1464
|
for (const [sum, v] of Object.entries(data)) {
|
|
1482
|
-
map.set(normalizeTickerSymbol(sum), Number(v.balance ?? 0));
|
|
1465
|
+
map.set(normalizeTickerSymbol$1(sum), Number(v.balance ?? 0));
|
|
1483
1466
|
}
|
|
1484
1467
|
}
|
|
1485
1468
|
return map;
|
|
1486
1469
|
}, [query.data]);
|
|
1487
1470
|
const getBalance = useCallback(
|
|
1488
|
-
(symbol) => balanceBySymbol.get(normalizeTickerSymbol(symbol)) ?? 0,
|
|
1471
|
+
(symbol) => balanceBySymbol.get(normalizeTickerSymbol$1(symbol)) ?? 0,
|
|
1489
1472
|
[balanceBySymbol]
|
|
1490
1473
|
);
|
|
1491
1474
|
const isLoading = query.isLoading || query.isFetching;
|
|
1492
|
-
const balances = useMemo(
|
|
1493
|
-
() => query.data || {},
|
|
1494
|
-
[query.data]
|
|
1495
|
-
);
|
|
1475
|
+
const balances = useMemo(() => query.data || {}, [query.data]);
|
|
1496
1476
|
return {
|
|
1497
1477
|
balances,
|
|
1498
1478
|
getBalance,
|
|
@@ -1722,8 +1702,7 @@ const TokenSelectModal = ({
|
|
|
1722
1702
|
isOpen,
|
|
1723
1703
|
onClose,
|
|
1724
1704
|
items,
|
|
1725
|
-
onChangeAsset
|
|
1726
|
-
modalContainer
|
|
1705
|
+
onChangeAsset
|
|
1727
1706
|
}) => {
|
|
1728
1707
|
const { t: t2 } = useTranslation();
|
|
1729
1708
|
const {
|
|
@@ -1808,7 +1787,6 @@ const TokenSelectModal = ({
|
|
|
1808
1787
|
{
|
|
1809
1788
|
isOpen,
|
|
1810
1789
|
onClose: handleClose,
|
|
1811
|
-
modalContainer,
|
|
1812
1790
|
children: /* @__PURE__ */ jsxs(ModalContent, { children: [
|
|
1813
1791
|
/* @__PURE__ */ jsxs(ModalHeader, { children: [
|
|
1814
1792
|
/* @__PURE__ */ jsx(ModalTitle, { children: t2("bridge.selectToken") }),
|
|
@@ -1948,17 +1926,17 @@ const RefreshButton = () => {
|
|
|
1948
1926
|
return /* @__PURE__ */ jsx(
|
|
1949
1927
|
Button,
|
|
1950
1928
|
{
|
|
1951
|
-
className: `cursor-pointer py-1.5 h-8.5 hover:scale-110 shadow-none px-8.5 hover:bg-secondary bg-secondary !rounded-40 ${spinning ? "opacity-70" : ""}`,
|
|
1952
1929
|
onClick: handleRefresh,
|
|
1953
1930
|
disabled: spinning,
|
|
1931
|
+
variant: "secondary",
|
|
1932
|
+
size: "sm",
|
|
1954
1933
|
children: /* @__PURE__ */ jsx(
|
|
1955
1934
|
ReloadIcon,
|
|
1956
1935
|
{
|
|
1957
1936
|
style: {
|
|
1958
1937
|
transform: `rotate(${turns * 180}deg)`,
|
|
1959
1938
|
transition: "transform 300ms linear"
|
|
1960
|
-
}
|
|
1961
|
-
className: "size-4 text-foreground m-1 will-change-transform"
|
|
1939
|
+
}
|
|
1962
1940
|
}
|
|
1963
1941
|
)
|
|
1964
1942
|
}
|
|
@@ -1966,7 +1944,6 @@ const RefreshButton = () => {
|
|
|
1966
1944
|
};
|
|
1967
1945
|
const SelectTokenButton = ({
|
|
1968
1946
|
onClick,
|
|
1969
|
-
className,
|
|
1970
1947
|
token
|
|
1971
1948
|
}) => {
|
|
1972
1949
|
const { t: t2 } = useTranslation();
|
|
@@ -1977,7 +1954,8 @@ const SelectTokenButton = ({
|
|
|
1977
1954
|
Button,
|
|
1978
1955
|
{
|
|
1979
1956
|
onClick,
|
|
1980
|
-
|
|
1957
|
+
size: "sm",
|
|
1958
|
+
variant: "secondary",
|
|
1981
1959
|
type: "button",
|
|
1982
1960
|
"aria-label": label,
|
|
1983
1961
|
children: [
|
|
@@ -1997,7 +1975,76 @@ const SelectTokenButton = ({
|
|
|
1997
1975
|
}
|
|
1998
1976
|
);
|
|
1999
1977
|
};
|
|
2000
|
-
|
|
1978
|
+
function Card({ className, ...props }) {
|
|
1979
|
+
return /* @__PURE__ */ jsx(
|
|
1980
|
+
"div",
|
|
1981
|
+
{
|
|
1982
|
+
"data-slot": "card",
|
|
1983
|
+
className: cn(
|
|
1984
|
+
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
|
1985
|
+
className
|
|
1986
|
+
),
|
|
1987
|
+
...props
|
|
1988
|
+
}
|
|
1989
|
+
);
|
|
1990
|
+
}
|
|
1991
|
+
function CardHeader({ className, ...props }) {
|
|
1992
|
+
return /* @__PURE__ */ jsx(
|
|
1993
|
+
"div",
|
|
1994
|
+
{
|
|
1995
|
+
"data-slot": "card-header",
|
|
1996
|
+
className: cn(
|
|
1997
|
+
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
1998
|
+
className
|
|
1999
|
+
),
|
|
2000
|
+
...props
|
|
2001
|
+
}
|
|
2002
|
+
);
|
|
2003
|
+
}
|
|
2004
|
+
function CardTitle({ className, ...props }) {
|
|
2005
|
+
return /* @__PURE__ */ jsx(
|
|
2006
|
+
"div",
|
|
2007
|
+
{
|
|
2008
|
+
"data-slot": "card-title",
|
|
2009
|
+
className: cn("leading-none font-semibold", className),
|
|
2010
|
+
...props
|
|
2011
|
+
}
|
|
2012
|
+
);
|
|
2013
|
+
}
|
|
2014
|
+
function CardAction({ className, ...props }) {
|
|
2015
|
+
return /* @__PURE__ */ jsx(
|
|
2016
|
+
"div",
|
|
2017
|
+
{
|
|
2018
|
+
"data-slot": "card-action",
|
|
2019
|
+
className: cn(
|
|
2020
|
+
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
|
2021
|
+
className
|
|
2022
|
+
),
|
|
2023
|
+
...props
|
|
2024
|
+
}
|
|
2025
|
+
);
|
|
2026
|
+
}
|
|
2027
|
+
function CardContent({ className, ...props }) {
|
|
2028
|
+
return /* @__PURE__ */ jsx(
|
|
2029
|
+
"div",
|
|
2030
|
+
{
|
|
2031
|
+
"data-slot": "card-content",
|
|
2032
|
+
className: cn("px-6", className),
|
|
2033
|
+
...props
|
|
2034
|
+
}
|
|
2035
|
+
);
|
|
2036
|
+
}
|
|
2037
|
+
function CardFooter({ className, ...props }) {
|
|
2038
|
+
return /* @__PURE__ */ jsx(
|
|
2039
|
+
"div",
|
|
2040
|
+
{
|
|
2041
|
+
"data-slot": "card-footer",
|
|
2042
|
+
className: cn("flex items-center px-6 [.border-t]:pt-6", className),
|
|
2043
|
+
...props
|
|
2044
|
+
}
|
|
2045
|
+
);
|
|
2046
|
+
}
|
|
2047
|
+
const FormHeaderComponent = () => {
|
|
2001
2048
|
const { t: t2 } = useTranslation();
|
|
2002
2049
|
const { isOpen, onClose, onOpen } = useModal();
|
|
2003
2050
|
const {
|
|
@@ -2013,29 +2060,14 @@ const FormHeaderComponent = ({ modalContainer }) => {
|
|
|
2013
2060
|
const sum = selectedAssetSymbol.toUpperCase();
|
|
2014
2061
|
return assets.find((a) => a.symbol.toUpperCase() === sum) ?? assets[0];
|
|
2015
2062
|
}, [assets, selectedAssetSymbol]);
|
|
2016
|
-
return /* @__PURE__ */ jsxs(
|
|
2017
|
-
/* @__PURE__ */ jsxs(
|
|
2018
|
-
/* @__PURE__ */
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
/* @__PURE__ */
|
|
2023
|
-
|
|
2024
|
-
/* @__PURE__ */ jsx(
|
|
2025
|
-
Button,
|
|
2026
|
-
{
|
|
2027
|
-
className: "cursor-pointer py-1.5 h-8.5 hover:scale-110 shadow-none px-8.5 hover:bg-secondary bg-secondary !rounded-40",
|
|
2028
|
-
onClick: onOpenSettings,
|
|
2029
|
-
children: /* @__PURE__ */ jsx(
|
|
2030
|
-
BoltIcon,
|
|
2031
|
-
{
|
|
2032
|
-
className: "size-4 text-foreground m-1",
|
|
2033
|
-
stroke: "currentColor"
|
|
2034
|
-
}
|
|
2035
|
-
)
|
|
2036
|
-
}
|
|
2037
|
-
)
|
|
2038
|
-
] })
|
|
2063
|
+
return /* @__PURE__ */ jsxs(CardHeader, { className: "gap-y-0 flex justify-between items-center", children: [
|
|
2064
|
+
/* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2.5", children: [
|
|
2065
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-normal leading-3.5 text-muted-foreground", children: t2("bridge.selectToken") }),
|
|
2066
|
+
/* @__PURE__ */ jsx(SelectTokenButton, { token: current, onClick: onOpen })
|
|
2067
|
+
] }),
|
|
2068
|
+
/* @__PURE__ */ jsxs(CardAction, { className: "flex items-center gap-2.5", children: [
|
|
2069
|
+
/* @__PURE__ */ jsx(RefreshButton, {}),
|
|
2070
|
+
/* @__PURE__ */ jsx(Button, { onClick: onOpenSettings, size: "sm", variant: "secondary", children: /* @__PURE__ */ jsx(BoltIcon, { stroke: "currentColor" }) })
|
|
2039
2071
|
] }),
|
|
2040
2072
|
/* @__PURE__ */ jsx(
|
|
2041
2073
|
TokenSelectModal,
|
|
@@ -2046,24 +2078,19 @@ const FormHeaderComponent = ({ modalContainer }) => {
|
|
|
2046
2078
|
onChangeAsset: (symbol) => {
|
|
2047
2079
|
setSelectedAssetSymbol(symbol);
|
|
2048
2080
|
onClose();
|
|
2049
|
-
}
|
|
2050
|
-
modalContainer
|
|
2081
|
+
}
|
|
2051
2082
|
}
|
|
2052
2083
|
),
|
|
2053
2084
|
/* @__PURE__ */ jsx(
|
|
2054
2085
|
SettingModal,
|
|
2055
2086
|
{
|
|
2056
2087
|
isOpen: isOpenSettings,
|
|
2057
|
-
onClose: onCloseSettings
|
|
2058
|
-
modalContainer
|
|
2088
|
+
onClose: onCloseSettings
|
|
2059
2089
|
}
|
|
2060
2090
|
)
|
|
2061
2091
|
] });
|
|
2062
2092
|
};
|
|
2063
|
-
const FormHeader = memo(
|
|
2064
|
-
FormHeaderComponent,
|
|
2065
|
-
(prev, next) => prev.modalContainer === next.modalContainer
|
|
2066
|
-
);
|
|
2093
|
+
const FormHeader = memo(FormHeaderComponent);
|
|
2067
2094
|
async function fetchQuotes(req) {
|
|
2068
2095
|
const params = {
|
|
2069
2096
|
srcChainKey: req.srcChainKey,
|
|
@@ -2611,8 +2638,7 @@ const ChainSelectModal = ({
|
|
|
2611
2638
|
onClose,
|
|
2612
2639
|
items,
|
|
2613
2640
|
allowedItems,
|
|
2614
|
-
onChangeChain
|
|
2615
|
-
modalContainer
|
|
2641
|
+
onChangeChain
|
|
2616
2642
|
}) => {
|
|
2617
2643
|
const { t: t2 } = useTranslation();
|
|
2618
2644
|
const [query, setQuery] = useState("");
|
|
@@ -2701,7 +2727,6 @@ const ChainSelectModal = ({
|
|
|
2701
2727
|
{
|
|
2702
2728
|
isOpen,
|
|
2703
2729
|
onClose: handleClose,
|
|
2704
|
-
modalContainer,
|
|
2705
2730
|
children: /* @__PURE__ */ jsxs(ModalContent, { children: [
|
|
2706
2731
|
/* @__PURE__ */ jsxs(ModalHeader, { children: [
|
|
2707
2732
|
/* @__PURE__ */ jsx(ModalTitle, { children: t2("bridge.selectNetwork") }),
|
|
@@ -2839,8 +2864,7 @@ const SwapSection = ({
|
|
|
2839
2864
|
disableNetworkSelect,
|
|
2840
2865
|
isSource,
|
|
2841
2866
|
onSelect,
|
|
2842
|
-
onAmountChange
|
|
2843
|
-
modalContainer
|
|
2867
|
+
onAmountChange
|
|
2844
2868
|
}) => {
|
|
2845
2869
|
const { isOpen, onClose, onOpen } = useModal();
|
|
2846
2870
|
const { assetMatrix, selectedAssetSymbol } = useTokensStore();
|
|
@@ -2873,9 +2897,9 @@ const SwapSection = ({
|
|
|
2873
2897
|
"div",
|
|
2874
2898
|
{
|
|
2875
2899
|
className: cn(
|
|
2876
|
-
"p-4 flex flex-col gap-4 transition-colors bg-
|
|
2900
|
+
"p-4 flex flex-col gap-4 transition-colors bg-input",
|
|
2877
2901
|
{
|
|
2878
|
-
"bg-
|
|
2902
|
+
"bg-input-focus": isSource && isFocused
|
|
2879
2903
|
},
|
|
2880
2904
|
className
|
|
2881
2905
|
),
|
|
@@ -2935,8 +2959,7 @@ const SwapSection = ({
|
|
|
2935
2959
|
onClose,
|
|
2936
2960
|
items: chains,
|
|
2937
2961
|
allowedItems: allowedChains,
|
|
2938
|
-
onChangeChain
|
|
2939
|
-
modalContainer
|
|
2962
|
+
onChangeChain
|
|
2940
2963
|
}
|
|
2941
2964
|
)
|
|
2942
2965
|
] });
|
|
@@ -3921,7 +3944,7 @@ function useSilentValidations(amountString) {
|
|
|
3921
3944
|
]);
|
|
3922
3945
|
return validationResult;
|
|
3923
3946
|
}
|
|
3924
|
-
|
|
3947
|
+
const SubmitButton = () => {
|
|
3925
3948
|
const { t: t2 } = useTranslation();
|
|
3926
3949
|
const { chainRegistry } = useChainStrategies();
|
|
3927
3950
|
const { srcAddress, dstAddress } = useAddresses();
|
|
@@ -3997,7 +4020,7 @@ function useTransferAction() {
|
|
|
3997
4020
|
maximumAmountFormatted,
|
|
3998
4021
|
chainRegistry
|
|
3999
4022
|
]);
|
|
4000
|
-
const
|
|
4023
|
+
const handleClick = async () => {
|
|
4001
4024
|
if (isBusy) return;
|
|
4002
4025
|
if (missingSrc && srcChainKey) {
|
|
4003
4026
|
onOpen("src");
|
|
@@ -4017,33 +4040,15 @@ function useTransferAction() {
|
|
|
4017
4040
|
}
|
|
4018
4041
|
};
|
|
4019
4042
|
const disabled = isBusy || amountNum <= 0 || status === "loading" || isBalanceLoading || hasInsufficientBalance || hasAmountTooLarge || !gas.hasEnoughGas || noRoute || !isValidForTransfer;
|
|
4020
|
-
return {
|
|
4021
|
-
// состояния
|
|
4022
|
-
isBusy,
|
|
4023
|
-
canTransfer,
|
|
4024
|
-
missingSrc,
|
|
4025
|
-
missingDst,
|
|
4026
|
-
hasEnoughGas: gas.hasEnoughGas,
|
|
4027
|
-
noRoute,
|
|
4028
|
-
// представление
|
|
4029
|
-
label,
|
|
4030
|
-
disabled,
|
|
4031
|
-
// действие
|
|
4032
|
-
onClick
|
|
4033
|
-
};
|
|
4034
|
-
}
|
|
4035
|
-
const SubmitButton = () => {
|
|
4036
|
-
const { label, disabled, onClick } = useTransferAction();
|
|
4037
|
-
return /* @__PURE__ */ jsx(Button, { onClick, disabled, size: "lg", children: label });
|
|
4043
|
+
return /* @__PURE__ */ jsx(Button, { onClick: handleClick, disabled, className: "w-full", children: label });
|
|
4038
4044
|
};
|
|
4039
4045
|
function short(addr) {
|
|
4040
4046
|
return addr.slice(0, 4) + "…" + addr.slice(-4);
|
|
4041
4047
|
}
|
|
4042
|
-
const WalletSelectModal = ({
|
|
4043
|
-
modalContainer
|
|
4044
|
-
}) => {
|
|
4048
|
+
const WalletSelectModal = () => {
|
|
4045
4049
|
const { t: t2 } = useTranslation();
|
|
4046
4050
|
const { isOpen, onClose } = useWalletSelectModal();
|
|
4051
|
+
const { connect, connectors, isPending } = useConnect();
|
|
4047
4052
|
const { chainRegistry } = useChainStrategies();
|
|
4048
4053
|
const tonWallet = chainRegistry.getStrategyByType("ton");
|
|
4049
4054
|
const metaMaskWallet = chainRegistry.getStrategyByType("evm");
|
|
@@ -4076,7 +4081,13 @@ const WalletSelectModal = ({
|
|
|
4076
4081
|
onDisconnect: () => tronWallet.disconnect()
|
|
4077
4082
|
});
|
|
4078
4083
|
}
|
|
4079
|
-
const isWalletConnected = (walletId) =>
|
|
4084
|
+
const isWalletConnected = (walletId) => {
|
|
4085
|
+
const isEvmConnector = connectors.some((c) => c.id === walletId);
|
|
4086
|
+
if (isEvmConnector && metaMaskWallet?.isConnected()) {
|
|
4087
|
+
return true;
|
|
4088
|
+
}
|
|
4089
|
+
return connectedWallets.some((w) => w.id === walletId);
|
|
4090
|
+
};
|
|
4080
4091
|
const tonWallets = [
|
|
4081
4092
|
{
|
|
4082
4093
|
id: "ton",
|
|
@@ -4085,14 +4096,15 @@ const WalletSelectModal = ({
|
|
|
4085
4096
|
enabled: true
|
|
4086
4097
|
}
|
|
4087
4098
|
];
|
|
4088
|
-
const evmWallets =
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4099
|
+
const evmWallets = connectors.filter(
|
|
4100
|
+
(connector) => connector.id === "walletConnect" || connector.id === "metaMaskSDK"
|
|
4101
|
+
).map((connector) => ({
|
|
4102
|
+
id: connector.id,
|
|
4103
|
+
name: connector.name,
|
|
4104
|
+
icon: MetaMaskIcon,
|
|
4105
|
+
// You can add a WalletConnect icon here
|
|
4106
|
+
enabled: true
|
|
4107
|
+
}));
|
|
4096
4108
|
const tronWallets = [
|
|
4097
4109
|
{
|
|
4098
4110
|
id: "tronlink",
|
|
@@ -4122,9 +4134,6 @@ const WalletSelectModal = ({
|
|
|
4122
4134
|
case "ton":
|
|
4123
4135
|
await tonWallet?.connect();
|
|
4124
4136
|
break;
|
|
4125
|
-
case "metamask":
|
|
4126
|
-
await metaMaskWallet?.connect();
|
|
4127
|
-
break;
|
|
4128
4137
|
case "tronlink":
|
|
4129
4138
|
await tronWallet?.connect();
|
|
4130
4139
|
break;
|
|
@@ -4136,7 +4145,7 @@ const WalletSelectModal = ({
|
|
|
4136
4145
|
console.error("Failed to connect wallet:", error);
|
|
4137
4146
|
}
|
|
4138
4147
|
};
|
|
4139
|
-
return /* @__PURE__ */ jsx(Modal, { isOpen, onClose,
|
|
4148
|
+
return /* @__PURE__ */ jsx(Modal, { isOpen, onClose, children: /* @__PURE__ */ jsxs(ModalContent, { children: [
|
|
4140
4149
|
/* @__PURE__ */ jsxs(ModalHeader, { children: [
|
|
4141
4150
|
/* @__PURE__ */ jsx(ModalTitle, { children: t2("wallets.chooseWallet", { defaultValue: "Choose wallet" }) }),
|
|
4142
4151
|
/* @__PURE__ */ jsx(ModalDescription, { children: t2("wallets.oneWalletPerEnv", {
|
|
@@ -4149,56 +4158,47 @@ const WalletSelectModal = ({
|
|
|
4149
4158
|
/* @__PURE__ */ jsx("div", { className: "px-5 py-2 leading-4 text-base font-semibold text-muted-foreground uppercase", children: t2("wallets.connected") }),
|
|
4150
4159
|
/* @__PURE__ */ jsx("div", { className: "", children: connectedWallets.map((wallet) => {
|
|
4151
4160
|
const IconComponent = wallet.icon;
|
|
4152
|
-
return /* @__PURE__ */ jsx("div", { className: "", children: /* @__PURE__ */ jsxs(
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
/* @__PURE__ */ jsx("div", { onClick: () => {
|
|
4161
|
+
return /* @__PURE__ */ jsx("div", { className: "", children: /* @__PURE__ */ jsxs(Button, { className: "w-full cursor-pointer bg-transparent flex shadow-none items-center justify-between gap-2.5 px-5 py-2.5 hover:bg-muted h-auto rounded-12 transition-[300]", children: [
|
|
4162
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-3 min-w-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
4163
|
+
/* @__PURE__ */ jsx("div", { className: "w-7.5 h-7.5 flex items-center justify-center", children: /* @__PURE__ */ jsx(IconComponent, { className: "size-7.5" }) }),
|
|
4164
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
|
|
4165
|
+
/* @__PURE__ */ jsx("p", { className: "font-extrabold text-foreground text-sm leading-4 truncate", children: short(wallet.address) }),
|
|
4166
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: wallet.name })
|
|
4167
|
+
] })
|
|
4168
|
+
] }) }),
|
|
4169
|
+
/* @__PURE__ */ jsx(
|
|
4170
|
+
"div",
|
|
4171
|
+
{
|
|
4172
|
+
onClick: () => {
|
|
4165
4173
|
wallet.onDisconnect();
|
|
4166
4174
|
onClose();
|
|
4167
|
-
},
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4175
|
+
},
|
|
4176
|
+
className: "text-sm font-medium text-muted-foreground",
|
|
4177
|
+
children: /* @__PURE__ */ jsx(ExitIcon, { className: "text-[#808080] size-6" })
|
|
4178
|
+
}
|
|
4179
|
+
)
|
|
4180
|
+
] }) }, wallet.id);
|
|
4171
4181
|
}) })
|
|
4172
4182
|
] }),
|
|
4173
4183
|
categories.map((category) => /* @__PURE__ */ jsxs("div", { children: [
|
|
4174
4184
|
/* @__PURE__ */ jsx("div", { className: "px-5 py-2 leading-4 text-base font-semibold text-muted-foreground uppercase", children: category.title }),
|
|
4175
4185
|
/* @__PURE__ */ jsx("div", { className: "", children: category.wallets.map((wallet) => {
|
|
4176
4186
|
const IconComponent = wallet.icon;
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
return /* @__PURE__ */ jsx(
|
|
4180
|
-
Button,
|
|
4181
|
-
{
|
|
4182
|
-
type: "button",
|
|
4183
|
-
onClick: show,
|
|
4184
|
-
disabled: isConnecting,
|
|
4185
|
-
className: "w-full cursor-pointer bg-transparent flex shadow-none items-center justify-between gap-2.5 px-5 py-2.5 hover:bg-muted h-auto rounded-12 transition-[300] disabled:opacity-50 disabled:cursor-not-allowed",
|
|
4186
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
4187
|
-
/* @__PURE__ */ jsx("div", { className: "w-7.5 h-7.5 flex items-center justify-center", children: /* @__PURE__ */ jsx(IconComponent, { className: "size-7.5" }) }),
|
|
4188
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
|
|
4189
|
-
/* @__PURE__ */ jsx("p", { className: "font-extrabold text-foreground text-sm leading-4 truncate", children: wallet.name }),
|
|
4190
|
-
wallet.comingSoon ? /* @__PURE__ */ jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: t2("wallets.comingSoon") }) : /* @__PURE__ */ jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: t2("wallets.connect") })
|
|
4191
|
-
] })
|
|
4192
|
-
] })
|
|
4193
|
-
}
|
|
4194
|
-
);
|
|
4195
|
-
} }) }, wallet.id);
|
|
4196
|
-
}
|
|
4187
|
+
const isEvmConnector = category.title === t2("wallets.evmWallets");
|
|
4188
|
+
const connector = isEvmConnector ? connectors.find((c) => c.id === wallet.id) : null;
|
|
4197
4189
|
return /* @__PURE__ */ jsx("div", { className: "", children: /* @__PURE__ */ jsx(
|
|
4198
4190
|
Button,
|
|
4199
4191
|
{
|
|
4200
|
-
|
|
4201
|
-
|
|
4192
|
+
type: "button",
|
|
4193
|
+
onClick: () => {
|
|
4194
|
+
if (connector) {
|
|
4195
|
+
connect({ connector });
|
|
4196
|
+
onClose();
|
|
4197
|
+
} else {
|
|
4198
|
+
handleWalletSelect(wallet.id);
|
|
4199
|
+
}
|
|
4200
|
+
},
|
|
4201
|
+
disabled: isEvmConnector ? isPending : !wallet.enabled,
|
|
4202
4202
|
className: "w-full cursor-pointer bg-transparent flex shadow-none items-center justify-between gap-2.5 px-5 py-2.5 hover:bg-muted h-auto rounded-12 transition-[300] disabled:opacity-50 disabled:cursor-not-allowed",
|
|
4203
4203
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
4204
4204
|
/* @__PURE__ */ jsx("div", { className: "w-7.5 h-7.5 flex items-center justify-center", children: /* @__PURE__ */ jsx(IconComponent, { className: "size-7.5" }) }),
|
|
@@ -4214,39 +4214,6 @@ const WalletSelectModal = ({
|
|
|
4214
4214
|
] })
|
|
4215
4215
|
] }) });
|
|
4216
4216
|
};
|
|
4217
|
-
function Card({ className, ...props }) {
|
|
4218
|
-
return /* @__PURE__ */ jsx(
|
|
4219
|
-
"div",
|
|
4220
|
-
{
|
|
4221
|
-
"data-slot": "card",
|
|
4222
|
-
className: cn(
|
|
4223
|
-
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
|
4224
|
-
className
|
|
4225
|
-
),
|
|
4226
|
-
...props
|
|
4227
|
-
}
|
|
4228
|
-
);
|
|
4229
|
-
}
|
|
4230
|
-
function CardContent({ className, ...props }) {
|
|
4231
|
-
return /* @__PURE__ */ jsx(
|
|
4232
|
-
"div",
|
|
4233
|
-
{
|
|
4234
|
-
"data-slot": "card-content",
|
|
4235
|
-
className: cn("px-6", className),
|
|
4236
|
-
...props
|
|
4237
|
-
}
|
|
4238
|
-
);
|
|
4239
|
-
}
|
|
4240
|
-
function CardFooter({ className, ...props }) {
|
|
4241
|
-
return /* @__PURE__ */ jsx(
|
|
4242
|
-
"div",
|
|
4243
|
-
{
|
|
4244
|
-
"data-slot": "card-footer",
|
|
4245
|
-
className: cn("flex items-center px-6 [.border-t]:pt-6", className),
|
|
4246
|
-
...props
|
|
4247
|
-
}
|
|
4248
|
-
);
|
|
4249
|
-
}
|
|
4250
4217
|
const TransactionProgressVector = (props) => {
|
|
4251
4218
|
return /* @__PURE__ */ jsxs("svg", { width: "200", height: "200", viewBox: "0 0 200 200", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: [
|
|
4252
4219
|
/* @__PURE__ */ jsx(
|
|
@@ -6171,7 +6138,7 @@ const ConfirmStep = () => {
|
|
|
6171
6138
|
/* @__PURE__ */ jsx("div", { className: "text-3xl font-black relative z-10", children: formatTime })
|
|
6172
6139
|
] }) });
|
|
6173
6140
|
};
|
|
6174
|
-
const TransactionManager = (
|
|
6141
|
+
const TransactionManager = () => {
|
|
6175
6142
|
const { current } = useTransactionStore();
|
|
6176
6143
|
const status = current?.status;
|
|
6177
6144
|
if (!status || status === "idle") return null;
|
|
@@ -6189,7 +6156,7 @@ const TransactionManager = ({ modalContainer }) => {
|
|
|
6189
6156
|
step = /* @__PURE__ */ jsx(SuccessStep, {});
|
|
6190
6157
|
}
|
|
6191
6158
|
return /* @__PURE__ */ jsx(Modal, { isOpen: true, onClose: () => {
|
|
6192
|
-
},
|
|
6159
|
+
}, children: step });
|
|
6193
6160
|
};
|
|
6194
6161
|
const useTokensRequest = () => {
|
|
6195
6162
|
const { setTokens, setSelectedToken, setSelectedAssetSymbol } = useTokensStore();
|
|
@@ -6310,6 +6277,49 @@ class ChainStrategyRegistry {
|
|
|
6310
6277
|
await strategy.disconnect();
|
|
6311
6278
|
}
|
|
6312
6279
|
}
|
|
6280
|
+
const EVM_CONFIG = {
|
|
6281
|
+
usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
6282
|
+
gasEstimates: {
|
|
6283
|
+
approve: 65000n,
|
|
6284
|
+
bridge: 300000n
|
|
6285
|
+
},
|
|
6286
|
+
gasBuffer: 1.2,
|
|
6287
|
+
// 20% buffer
|
|
6288
|
+
timeout: 3e5,
|
|
6289
|
+
// 5 minutes (increased for slower networks)
|
|
6290
|
+
requiredConfirmations: 3
|
|
6291
|
+
// Wait for 3 confirmations for reorg protection
|
|
6292
|
+
};
|
|
6293
|
+
const TON_CONFIG = {
|
|
6294
|
+
apiUrl: "https://toncenter.com/api/v2",
|
|
6295
|
+
timeout: 36e4,
|
|
6296
|
+
// 6 minutes
|
|
6297
|
+
validUntil: 600
|
|
6298
|
+
// 10 minutes
|
|
6299
|
+
};
|
|
6300
|
+
const TRON_CONFIG = {
|
|
6301
|
+
timeout: 12e4,
|
|
6302
|
+
// 2 minutes (for 19 confirmations)
|
|
6303
|
+
feeLimit: 1e8,
|
|
6304
|
+
// 100 TRX in sun
|
|
6305
|
+
requiredConfirmations: 19,
|
|
6306
|
+
// TRON standard: 19 blocks for confirmation
|
|
6307
|
+
pollingInterval: 3e3
|
|
6308
|
+
// 3 seconds between checks
|
|
6309
|
+
};
|
|
6310
|
+
let tonClientInstance = null;
|
|
6311
|
+
function getTonClient(customClient, apiKey) {
|
|
6312
|
+
if (customClient) {
|
|
6313
|
+
return customClient;
|
|
6314
|
+
}
|
|
6315
|
+
if (!tonClientInstance) {
|
|
6316
|
+
tonClientInstance = new TonClient({
|
|
6317
|
+
endpoint: `${TON_CONFIG.apiUrl}/jsonRPC`,
|
|
6318
|
+
apiKey
|
|
6319
|
+
});
|
|
6320
|
+
}
|
|
6321
|
+
return tonClientInstance;
|
|
6322
|
+
}
|
|
6313
6323
|
function isNativeAddress(addr) {
|
|
6314
6324
|
if (!addr) return false;
|
|
6315
6325
|
const a = addr.toLowerCase();
|
|
@@ -6335,44 +6345,72 @@ function formatUnitsFromBigIntStr(valueStr, decimals) {
|
|
|
6335
6345
|
const tail = s.slice(s.length - decimals).replace(/0+$/, "");
|
|
6336
6346
|
return Number(tail ? `${head}.${tail}` : head);
|
|
6337
6347
|
}
|
|
6338
|
-
|
|
6348
|
+
function isTonFriendlyAddress(address) {
|
|
6349
|
+
return !!address && /^[A-Za-z0-9_-]{48,}$/.test(address);
|
|
6350
|
+
}
|
|
6351
|
+
function normalizeTickerSymbol(symbol) {
|
|
6352
|
+
return symbol.toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
|
|
6353
|
+
}
|
|
6354
|
+
function parseTonAddress(address) {
|
|
6355
|
+
if (address.startsWith("0x")) {
|
|
6356
|
+
const hex = address.slice(2);
|
|
6357
|
+
return Address$1.parseRaw(`0:${hex}`);
|
|
6358
|
+
}
|
|
6359
|
+
if (address.includes(":")) {
|
|
6360
|
+
return Address$1.parseRaw(address);
|
|
6361
|
+
}
|
|
6362
|
+
return Address$1.parse(address);
|
|
6363
|
+
}
|
|
6364
|
+
async function getEvmBalances(publicClient, address, tokens) {
|
|
6339
6365
|
const balances = {};
|
|
6340
6366
|
try {
|
|
6341
|
-
|
|
6367
|
+
console.log("start getEvmBalances");
|
|
6368
|
+
console.log("publicClient:", publicClient);
|
|
6369
|
+
console.log("isAddress:", isAddress(address));
|
|
6370
|
+
console.log("tokens:", tokens);
|
|
6371
|
+
if (!address || !isAddress(address)) {
|
|
6342
6372
|
console.warn(`Invalid EVM address provided: ${address}`);
|
|
6343
6373
|
return balances;
|
|
6344
6374
|
}
|
|
6345
|
-
if (
|
|
6346
|
-
throw new Error("No
|
|
6375
|
+
if (!publicClient) {
|
|
6376
|
+
throw new Error("No public client provided");
|
|
6347
6377
|
}
|
|
6348
|
-
const provider = new ethers.BrowserProvider(window.ethereum);
|
|
6349
6378
|
for (const token of tokens) {
|
|
6350
6379
|
try {
|
|
6351
6380
|
let balance = 0;
|
|
6352
6381
|
const isNative = isNativeAddress(token.address);
|
|
6353
6382
|
if (isNative) {
|
|
6354
|
-
const ethBalance = await
|
|
6355
|
-
|
|
6383
|
+
const ethBalance = await publicClient.getBalance({
|
|
6384
|
+
address
|
|
6385
|
+
});
|
|
6386
|
+
balance = parseFloat(formatUnits(ethBalance, token.decimals));
|
|
6356
6387
|
} else {
|
|
6357
|
-
if (!
|
|
6388
|
+
if (!isAddress(token.address)) {
|
|
6358
6389
|
continue;
|
|
6359
6390
|
}
|
|
6360
|
-
const
|
|
6361
|
-
|
|
6391
|
+
const bytecode = await publicClient.getBytecode({
|
|
6392
|
+
address: token.address
|
|
6393
|
+
});
|
|
6394
|
+
if (!bytecode || bytecode === "0x") {
|
|
6362
6395
|
continue;
|
|
6363
6396
|
}
|
|
6364
|
-
const contract = new ethers.Contract(
|
|
6365
|
-
token.address,
|
|
6366
|
-
[
|
|
6367
|
-
"function balanceOf(address owner) view returns (uint256)",
|
|
6368
|
-
"function decimals() view returns (uint8)"
|
|
6369
|
-
],
|
|
6370
|
-
provider
|
|
6371
|
-
);
|
|
6372
6397
|
try {
|
|
6373
|
-
const tokenBalance = await
|
|
6398
|
+
const tokenBalance = await publicClient.readContract({
|
|
6399
|
+
address: token.address,
|
|
6400
|
+
abi: [
|
|
6401
|
+
{
|
|
6402
|
+
name: "balanceOf",
|
|
6403
|
+
type: "function",
|
|
6404
|
+
stateMutability: "view",
|
|
6405
|
+
inputs: [{ name: "owner", type: "address" }],
|
|
6406
|
+
outputs: [{ name: "balance", type: "uint256" }]
|
|
6407
|
+
}
|
|
6408
|
+
],
|
|
6409
|
+
functionName: "balanceOf",
|
|
6410
|
+
args: [address]
|
|
6411
|
+
});
|
|
6374
6412
|
balance = parseFloat(
|
|
6375
|
-
|
|
6413
|
+
formatUnits(tokenBalance, token.decimals)
|
|
6376
6414
|
);
|
|
6377
6415
|
} catch {
|
|
6378
6416
|
continue;
|
|
@@ -6395,6 +6433,68 @@ async function getEvmBalances(address, tokens) {
|
|
|
6395
6433
|
}
|
|
6396
6434
|
return balances;
|
|
6397
6435
|
}
|
|
6436
|
+
async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
|
|
6437
|
+
const balances = {};
|
|
6438
|
+
try {
|
|
6439
|
+
if (!isTonFriendlyAddress(address)) {
|
|
6440
|
+
console.warn(`Invalid TON address provided: ${address}`);
|
|
6441
|
+
return balances;
|
|
6442
|
+
}
|
|
6443
|
+
const client = getTonClient(customTonClient, tonApiKey);
|
|
6444
|
+
const accountAddress = Address$1.parse(address);
|
|
6445
|
+
console.log(address);
|
|
6446
|
+
console.log(tokens);
|
|
6447
|
+
try {
|
|
6448
|
+
const balance = await client.getBalance(accountAddress);
|
|
6449
|
+
const tonBalance = Number(balance) / 1e9;
|
|
6450
|
+
console.log("tonBalance", tonBalance);
|
|
6451
|
+
if (tonBalance > 0) {
|
|
6452
|
+
balances.TON = { balance: tonBalance, address: "ton-native" };
|
|
6453
|
+
}
|
|
6454
|
+
} catch (error) {
|
|
6455
|
+
console.warn("Failed to get native TON balance:", error);
|
|
6456
|
+
}
|
|
6457
|
+
for (const token of tokens) {
|
|
6458
|
+
try {
|
|
6459
|
+
if (isNativeAddress(token.address) || token.symbol.toUpperCase() === "TON") {
|
|
6460
|
+
continue;
|
|
6461
|
+
}
|
|
6462
|
+
const jettonMasterAddress = parseTonAddress(token.address);
|
|
6463
|
+
const jettonWalletAddress = await client.runMethod(
|
|
6464
|
+
jettonMasterAddress,
|
|
6465
|
+
"get_wallet_address",
|
|
6466
|
+
[
|
|
6467
|
+
{
|
|
6468
|
+
type: "slice",
|
|
6469
|
+
cell: beginCell().storeAddress(accountAddress).endCell()
|
|
6470
|
+
}
|
|
6471
|
+
]
|
|
6472
|
+
);
|
|
6473
|
+
const jettonWalletAddr = jettonWalletAddress.stack.readAddress();
|
|
6474
|
+
const jettonData = await client.runMethod(
|
|
6475
|
+
jettonWalletAddr,
|
|
6476
|
+
"get_wallet_data"
|
|
6477
|
+
);
|
|
6478
|
+
const jettonBalance = jettonData.stack.readBigNumber();
|
|
6479
|
+
const humanBalance = Number(jettonBalance) / Math.pow(10, token.decimals);
|
|
6480
|
+
if (humanBalance > 0) {
|
|
6481
|
+
const symbolUpper = token.symbol.toUpperCase();
|
|
6482
|
+
const symbolNorm = normalizeTickerSymbol(symbolUpper);
|
|
6483
|
+
const entry = { balance: humanBalance, address: token.address };
|
|
6484
|
+
balances[symbolUpper] = entry;
|
|
6485
|
+
if (symbolNorm !== symbolUpper) {
|
|
6486
|
+
balances[symbolNorm] = entry;
|
|
6487
|
+
}
|
|
6488
|
+
}
|
|
6489
|
+
} catch (error) {
|
|
6490
|
+
console.debug(`Failed to get balance for ${token.symbol}:`, error);
|
|
6491
|
+
}
|
|
6492
|
+
}
|
|
6493
|
+
} catch (error) {
|
|
6494
|
+
console.error("Failed to get TON balances:", error);
|
|
6495
|
+
}
|
|
6496
|
+
return balances;
|
|
6497
|
+
}
|
|
6398
6498
|
async function getTronBalances(tronWeb, address, tokens) {
|
|
6399
6499
|
const balances = {};
|
|
6400
6500
|
try {
|
|
@@ -6438,30 +6538,6 @@ async function getTronBalances(tronWeb, address, tokens) {
|
|
|
6438
6538
|
}
|
|
6439
6539
|
return balances;
|
|
6440
6540
|
}
|
|
6441
|
-
const EVM_CONFIG = {
|
|
6442
|
-
usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
6443
|
-
gasEstimates: {
|
|
6444
|
-
approve: 65000n,
|
|
6445
|
-
bridge: 300000n
|
|
6446
|
-
},
|
|
6447
|
-
gasBuffer: 1.2,
|
|
6448
|
-
// 20% buffer
|
|
6449
|
-
timeout: 12e4
|
|
6450
|
-
// 2 minutes
|
|
6451
|
-
};
|
|
6452
|
-
const TON_CONFIG = {
|
|
6453
|
-
apiUrl: "https://toncenter.com/api/v2",
|
|
6454
|
-
timeout: 36e4,
|
|
6455
|
-
// 6 minutes
|
|
6456
|
-
validUntil: 600
|
|
6457
|
-
// 10 minutes
|
|
6458
|
-
};
|
|
6459
|
-
const TRON_CONFIG = {
|
|
6460
|
-
timeout: 6e4,
|
|
6461
|
-
// 1 minute
|
|
6462
|
-
feeLimit: 1e8
|
|
6463
|
-
// 100 TRX in sun
|
|
6464
|
-
};
|
|
6465
6541
|
const ERC20_ABI = [
|
|
6466
6542
|
"function approve(address spender, uint256 amount) returns (bool)",
|
|
6467
6543
|
"function allowance(address owner, address spender) view returns (uint256)",
|
|
@@ -6472,7 +6548,9 @@ class EvmChainStrategy {
|
|
|
6472
6548
|
constructor(config) {
|
|
6473
6549
|
__publicField(this, "config");
|
|
6474
6550
|
__publicField(this, "provider");
|
|
6551
|
+
__publicField(this, "publicClient");
|
|
6475
6552
|
this.config = config;
|
|
6553
|
+
this.publicClient = config.publicClient;
|
|
6476
6554
|
if (config.walletClient) {
|
|
6477
6555
|
this.provider = new BrowserProvider(config.walletClient.transport);
|
|
6478
6556
|
}
|
|
@@ -6511,7 +6589,11 @@ class EvmChainStrategy {
|
|
|
6511
6589
|
return t2("wallets.connectEvmWallet");
|
|
6512
6590
|
}
|
|
6513
6591
|
async getBalances(address, tokens) {
|
|
6514
|
-
|
|
6592
|
+
if (!this.publicClient) {
|
|
6593
|
+
console.warn("No publicClient available for balance query");
|
|
6594
|
+
return {};
|
|
6595
|
+
}
|
|
6596
|
+
return await getEvmBalances(this.publicClient, address, tokens);
|
|
6515
6597
|
}
|
|
6516
6598
|
isAddressValid(address) {
|
|
6517
6599
|
if (!address) return false;
|
|
@@ -6540,8 +6622,8 @@ class EvmChainStrategy {
|
|
|
6540
6622
|
const totalGas = approveGas + bridgeGas;
|
|
6541
6623
|
const bufferMultiplier = BigInt(Math.floor(EVM_CONFIG.gasBuffer * 100));
|
|
6542
6624
|
const requiredWei = gasPrice * totalGas * bufferMultiplier / 100n;
|
|
6543
|
-
const { formatUnits } = await import("ethers");
|
|
6544
|
-
estimatedGas = Number(
|
|
6625
|
+
const { formatUnits: formatUnits2 } = await import("ethers");
|
|
6626
|
+
estimatedGas = Number(formatUnits2(requiredWei, nativeDecimals));
|
|
6545
6627
|
} catch {
|
|
6546
6628
|
estimatedGas = null;
|
|
6547
6629
|
}
|
|
@@ -6624,17 +6706,14 @@ class EvmChainStrategy {
|
|
|
6624
6706
|
if (!provider) {
|
|
6625
6707
|
throw new ProviderNotAvailableError("evm");
|
|
6626
6708
|
}
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
}
|
|
6636
|
-
await new Promise((r) => setTimeout(r, 2500));
|
|
6637
|
-
}
|
|
6709
|
+
console.log(
|
|
6710
|
+
`Waiting for ${EVM_CONFIG.requiredConfirmations} confirmations for tx: ${txHash}`
|
|
6711
|
+
);
|
|
6712
|
+
const receipt = await provider.waitForTransaction(
|
|
6713
|
+
txHash,
|
|
6714
|
+
EVM_CONFIG.requiredConfirmations,
|
|
6715
|
+
EVM_CONFIG.timeout
|
|
6716
|
+
);
|
|
6638
6717
|
if (!receipt) {
|
|
6639
6718
|
const error = new TransactionTimeoutError("evm", txHash);
|
|
6640
6719
|
return {
|
|
@@ -6649,11 +6728,35 @@ class EvmChainStrategy {
|
|
|
6649
6728
|
error: error.message
|
|
6650
6729
|
};
|
|
6651
6730
|
}
|
|
6652
|
-
console.log(
|
|
6731
|
+
console.log(
|
|
6732
|
+
`EVM transaction confirmed in block ${receipt.blockNumber} with ${EVM_CONFIG.requiredConfirmations} confirmations`
|
|
6733
|
+
);
|
|
6653
6734
|
return {
|
|
6654
6735
|
completed: true
|
|
6655
6736
|
};
|
|
6656
6737
|
} catch (error) {
|
|
6738
|
+
if (error && typeof error === "object" && "code" in error && error.code === "TRANSACTION_REPLACED") {
|
|
6739
|
+
console.log(
|
|
6740
|
+
`Transaction was replaced: ${"reason" in error ? String(error.reason) : "unknown"}`
|
|
6741
|
+
);
|
|
6742
|
+
if ("receipt" in error && error.receipt) {
|
|
6743
|
+
const replacementReceipt = error.receipt;
|
|
6744
|
+
if (replacementReceipt.status === 1) {
|
|
6745
|
+
console.log(
|
|
6746
|
+
`Replacement transaction succeeded in block ${replacementReceipt.blockNumber}`
|
|
6747
|
+
);
|
|
6748
|
+
return {
|
|
6749
|
+
completed: true
|
|
6750
|
+
};
|
|
6751
|
+
} else {
|
|
6752
|
+
const chainError2 = new TransactionRevertedError("evm", txHash);
|
|
6753
|
+
return {
|
|
6754
|
+
completed: false,
|
|
6755
|
+
error: chainError2.message
|
|
6756
|
+
};
|
|
6757
|
+
}
|
|
6758
|
+
}
|
|
6759
|
+
}
|
|
6657
6760
|
const chainError = toChainStrategyError(
|
|
6658
6761
|
error,
|
|
6659
6762
|
"evm",
|
|
@@ -6767,13 +6870,52 @@ class EvmChainStrategy {
|
|
|
6767
6870
|
return false;
|
|
6768
6871
|
}
|
|
6769
6872
|
}
|
|
6873
|
+
/**
|
|
6874
|
+
* Check if a block has reached finality status (optional, for critical transactions)
|
|
6875
|
+
* This is more stringent than confirmations and protects against long-range reorgs
|
|
6876
|
+
*
|
|
6877
|
+
* Usage: Call this method after waitForCompletion if you need additional security
|
|
6878
|
+
* for high-value transactions. The method checks if the block has been marked as
|
|
6879
|
+
* "finalized" by the Ethereum consensus layer (2/3 of validators).
|
|
6880
|
+
*
|
|
6881
|
+
* @param blockNumber - The block number to check for finality
|
|
6882
|
+
* @returns true if the block is finalized, false otherwise
|
|
6883
|
+
*/
|
|
6884
|
+
async checkFinality(blockNumber) {
|
|
6885
|
+
try {
|
|
6886
|
+
const provider = this.provider;
|
|
6887
|
+
if (!provider) {
|
|
6888
|
+
return false;
|
|
6889
|
+
}
|
|
6890
|
+
const finalizedBlock = await provider.getBlock("finalized");
|
|
6891
|
+
if (!finalizedBlock) {
|
|
6892
|
+
console.debug(
|
|
6893
|
+
"Finalized block not available (pre-merge or unsupported)"
|
|
6894
|
+
);
|
|
6895
|
+
return false;
|
|
6896
|
+
}
|
|
6897
|
+
const isFinalized = blockNumber <= finalizedBlock.number;
|
|
6898
|
+
if (isFinalized) {
|
|
6899
|
+
console.log(
|
|
6900
|
+
`Block ${blockNumber} has reached finality (finalized block: ${finalizedBlock.number})`
|
|
6901
|
+
);
|
|
6902
|
+
} else {
|
|
6903
|
+
console.debug(
|
|
6904
|
+
`Block ${blockNumber} not yet finalized (finalized block: ${finalizedBlock.number})`
|
|
6905
|
+
);
|
|
6906
|
+
}
|
|
6907
|
+
return isFinalized;
|
|
6908
|
+
} catch (error) {
|
|
6909
|
+
console.debug("Error checking finality:", error);
|
|
6910
|
+
return false;
|
|
6911
|
+
}
|
|
6912
|
+
}
|
|
6770
6913
|
}
|
|
6771
6914
|
class TonChainStrategy {
|
|
6772
6915
|
constructor(config) {
|
|
6773
6916
|
__publicField(this, "config");
|
|
6774
6917
|
this.config = config;
|
|
6775
6918
|
}
|
|
6776
|
-
// ========== Identity ==========
|
|
6777
6919
|
canHandle(chainKey) {
|
|
6778
6920
|
return chainKey.toLowerCase() === "ton";
|
|
6779
6921
|
}
|
|
@@ -6783,7 +6925,6 @@ class TonChainStrategy {
|
|
|
6783
6925
|
getName() {
|
|
6784
6926
|
return "TON Chain Strategy";
|
|
6785
6927
|
}
|
|
6786
|
-
// ========== Wallet Management ==========
|
|
6787
6928
|
async connect() {
|
|
6788
6929
|
await this.config.tonConnectUI?.openModal();
|
|
6789
6930
|
}
|
|
@@ -6808,17 +6949,26 @@ class TonChainStrategy {
|
|
|
6808
6949
|
getConnectLabel(t2) {
|
|
6809
6950
|
return t2("wallets.connectTonWallet");
|
|
6810
6951
|
}
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6952
|
+
async getBalances(address, tokens) {
|
|
6953
|
+
return await getTonBalances(
|
|
6954
|
+
address,
|
|
6955
|
+
tokens,
|
|
6956
|
+
this.config.tonClient,
|
|
6957
|
+
this.config.tonApiKey
|
|
6958
|
+
);
|
|
6814
6959
|
}
|
|
6815
6960
|
isAddressValid(address) {
|
|
6816
6961
|
if (!address) return false;
|
|
6817
6962
|
return true;
|
|
6818
6963
|
}
|
|
6819
|
-
// ========== Gas Estimation ==========
|
|
6820
6964
|
async estimateGasRequirement(params) {
|
|
6821
|
-
const {
|
|
6965
|
+
const {
|
|
6966
|
+
selectedToken,
|
|
6967
|
+
nativeTokenSymbol,
|
|
6968
|
+
amount,
|
|
6969
|
+
balances,
|
|
6970
|
+
reserveFallback
|
|
6971
|
+
} = params;
|
|
6822
6972
|
const nativeSym = nativeTokenSymbol.toUpperCase();
|
|
6823
6973
|
const isNativeSelected = nativeSym === (selectedToken?.symbol ?? "").toUpperCase();
|
|
6824
6974
|
const nativeBalance = Number(balances[nativeSym]?.balance ?? 0);
|
|
@@ -6840,7 +6990,6 @@ class TonChainStrategy {
|
|
|
6840
6990
|
isNativeSelected
|
|
6841
6991
|
};
|
|
6842
6992
|
}
|
|
6843
|
-
// ========== Transaction Execution ==========
|
|
6844
6993
|
validateSteps(steps) {
|
|
6845
6994
|
if (!steps || steps.length === 0) {
|
|
6846
6995
|
throw new InvalidStepsError("ton", "No transaction steps provided");
|
|
@@ -6893,19 +7042,17 @@ class TonChainStrategy {
|
|
|
6893
7042
|
const result = await this.config.tonConnectUI.sendTransaction(
|
|
6894
7043
|
transaction
|
|
6895
7044
|
);
|
|
6896
|
-
const hash = this.getTxHash(result.boc);
|
|
6897
7045
|
return {
|
|
6898
7046
|
chainKey: "ton",
|
|
6899
|
-
hash
|
|
7047
|
+
hash: result.boc
|
|
6900
7048
|
};
|
|
6901
7049
|
} catch (error) {
|
|
6902
7050
|
throw toChainStrategyError(error, "ton", "transaction");
|
|
6903
7051
|
}
|
|
6904
7052
|
}
|
|
6905
|
-
async waitForCompletion(txHash
|
|
7053
|
+
async waitForCompletion(txHash) {
|
|
6906
7054
|
try {
|
|
6907
7055
|
const confirmed = await this.checkTonTransaction(
|
|
6908
|
-
context.srcAddress,
|
|
6909
7056
|
txHash,
|
|
6910
7057
|
TON_CONFIG.timeout
|
|
6911
7058
|
);
|
|
@@ -6935,39 +7082,78 @@ class TonChainStrategy {
|
|
|
6935
7082
|
};
|
|
6936
7083
|
}
|
|
6937
7084
|
}
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
7085
|
+
getNormalizedExtMessageHash(message) {
|
|
7086
|
+
if (message.info.type !== "external-in") {
|
|
7087
|
+
throw new Error(`Expected external-in message, got ${message.info.type}`);
|
|
7088
|
+
}
|
|
7089
|
+
const normalizedInfo = {
|
|
7090
|
+
...message.info,
|
|
7091
|
+
src: void 0,
|
|
7092
|
+
importFee: 0n
|
|
7093
|
+
};
|
|
7094
|
+
const normalizedMessage = {
|
|
7095
|
+
...message,
|
|
7096
|
+
info: normalizedInfo,
|
|
7097
|
+
init: null
|
|
7098
|
+
};
|
|
7099
|
+
return beginCell$1().store(storeMessage(normalizedMessage, { forceRef: true })).endCell().hash();
|
|
6943
7100
|
}
|
|
6944
|
-
async checkTonTransaction(
|
|
7101
|
+
async checkTonTransaction(bocBase64, timeoutMs = 36e4) {
|
|
6945
7102
|
const deadline = Date.now() + timeoutMs;
|
|
6946
|
-
const
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
7103
|
+
const client = getTonClient(this.config.tonClient, this.config.tonApiKey);
|
|
7104
|
+
try {
|
|
7105
|
+
const inMessage = loadMessage(Cell.fromBase64(bocBase64).beginParse());
|
|
7106
|
+
if (inMessage.info.type !== "external-in") {
|
|
7107
|
+
console.debug(
|
|
7108
|
+
"Expected external-in message, got:",
|
|
7109
|
+
inMessage.info.type
|
|
6951
7110
|
);
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
const
|
|
6961
|
-
|
|
6962
|
-
|
|
7111
|
+
return false;
|
|
7112
|
+
}
|
|
7113
|
+
const accountAddress = inMessage.info.dest;
|
|
7114
|
+
const targetMessageHash = this.getNormalizedExtMessageHash(inMessage);
|
|
7115
|
+
let lt = void 0;
|
|
7116
|
+
let hash = void 0;
|
|
7117
|
+
while (Date.now() < deadline) {
|
|
7118
|
+
try {
|
|
7119
|
+
const transactions = await client.getTransactions(accountAddress, {
|
|
7120
|
+
lt,
|
|
7121
|
+
hash,
|
|
7122
|
+
limit: 10,
|
|
7123
|
+
archival: true
|
|
7124
|
+
});
|
|
7125
|
+
if (transactions.length === 0) {
|
|
7126
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
7127
|
+
lt = void 0;
|
|
7128
|
+
hash = void 0;
|
|
7129
|
+
continue;
|
|
6963
7130
|
}
|
|
7131
|
+
for (const tx of transactions) {
|
|
7132
|
+
if (tx.inMessage?.info.type === "external-in") {
|
|
7133
|
+
const txInMessageHash = this.getNormalizedExtMessageHash(
|
|
7134
|
+
tx.inMessage
|
|
7135
|
+
);
|
|
7136
|
+
if (txInMessageHash.equals(targetMessageHash)) {
|
|
7137
|
+
console.debug("Transaction found by in-message hash");
|
|
7138
|
+
return true;
|
|
7139
|
+
}
|
|
7140
|
+
}
|
|
7141
|
+
}
|
|
7142
|
+
const lastTx = transactions[transactions.length - 1];
|
|
7143
|
+
lt = lastTx.lt.toString();
|
|
7144
|
+
hash = lastTx.hash().toString("base64");
|
|
7145
|
+
} catch (error) {
|
|
7146
|
+
console.debug("Error fetching transactions:", error);
|
|
7147
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
7148
|
+
lt = void 0;
|
|
7149
|
+
hash = void 0;
|
|
6964
7150
|
}
|
|
6965
|
-
} catch (e) {
|
|
6966
|
-
console.debug("TonCenter polling error:", e);
|
|
6967
7151
|
}
|
|
6968
|
-
|
|
7152
|
+
return false;
|
|
7153
|
+
} catch (error) {
|
|
7154
|
+
console.debug("Error parsing BOC or checking transaction:", error);
|
|
7155
|
+
return false;
|
|
6969
7156
|
}
|
|
6970
|
-
return false;
|
|
6971
7157
|
}
|
|
6972
7158
|
}
|
|
6973
7159
|
class TronChainStrategy {
|
|
@@ -7028,7 +7214,13 @@ class TronChainStrategy {
|
|
|
7028
7214
|
}
|
|
7029
7215
|
// ========== Gas Estimation ==========
|
|
7030
7216
|
async estimateGasRequirement(params) {
|
|
7031
|
-
const {
|
|
7217
|
+
const {
|
|
7218
|
+
selectedToken,
|
|
7219
|
+
nativeTokenSymbol,
|
|
7220
|
+
amount,
|
|
7221
|
+
balances,
|
|
7222
|
+
reserveFallback
|
|
7223
|
+
} = params;
|
|
7032
7224
|
const nativeSym = nativeTokenSymbol.toUpperCase();
|
|
7033
7225
|
const isNativeSelected = nativeSym === (selectedToken?.symbol ?? "").toUpperCase();
|
|
7034
7226
|
const nativeBalance = Number(balances[nativeSym]?.balance ?? 0);
|
|
@@ -7050,7 +7242,6 @@ class TronChainStrategy {
|
|
|
7050
7242
|
isNativeSelected
|
|
7051
7243
|
};
|
|
7052
7244
|
}
|
|
7053
|
-
// ========== Transaction Execution ==========
|
|
7054
7245
|
validateSteps(steps) {
|
|
7055
7246
|
console.log("validateSteps");
|
|
7056
7247
|
if (!steps?.length) {
|
|
@@ -7085,7 +7276,10 @@ class TronChainStrategy {
|
|
|
7085
7276
|
if (String(step.chainKey).toLowerCase() !== "tron") continue;
|
|
7086
7277
|
const tx = step.transaction;
|
|
7087
7278
|
if (!tx) {
|
|
7088
|
-
throw new InvalidTransactionDataError(
|
|
7279
|
+
throw new InvalidTransactionDataError(
|
|
7280
|
+
"tron",
|
|
7281
|
+
"Missing transaction data"
|
|
7282
|
+
);
|
|
7089
7283
|
}
|
|
7090
7284
|
const hexData = typeof tx?.data === "string" ? tx.data : "";
|
|
7091
7285
|
const parsed = this.parseTronStep(step, tx, hexData);
|
|
@@ -7136,13 +7330,19 @@ class TronChainStrategy {
|
|
|
7136
7330
|
break;
|
|
7137
7331
|
}
|
|
7138
7332
|
default:
|
|
7139
|
-
throw new InvalidStepsError(
|
|
7333
|
+
throw new InvalidStepsError(
|
|
7334
|
+
"tron",
|
|
7335
|
+
"Unsupported TRON parsed tx kind"
|
|
7336
|
+
);
|
|
7140
7337
|
}
|
|
7141
7338
|
const { txid } = await this.signAndBroadcast(tronWeb, unsigned);
|
|
7142
7339
|
lastTxId = txid;
|
|
7143
7340
|
}
|
|
7144
7341
|
if (!lastTxId) {
|
|
7145
|
-
throw new TransactionFailedError(
|
|
7342
|
+
throw new TransactionFailedError(
|
|
7343
|
+
"tron",
|
|
7344
|
+
"No TRON transaction was executed"
|
|
7345
|
+
);
|
|
7146
7346
|
}
|
|
7147
7347
|
return { hash: lastTxId, chainKey: "tron" };
|
|
7148
7348
|
}
|
|
@@ -7152,47 +7352,84 @@ class TronChainStrategy {
|
|
|
7152
7352
|
if (!tronWeb) {
|
|
7153
7353
|
throw new ProviderNotAvailableError("tron");
|
|
7154
7354
|
}
|
|
7355
|
+
console.log(
|
|
7356
|
+
`Waiting for ${TRON_CONFIG.requiredConfirmations} confirmations for TRON tx: ${txHash}`
|
|
7357
|
+
);
|
|
7155
7358
|
const deadline = Date.now() + TRON_CONFIG.timeout;
|
|
7156
|
-
|
|
7359
|
+
let txBlockNumber = null;
|
|
7360
|
+
while (Date.now() < deadline && !txBlockNumber) {
|
|
7157
7361
|
try {
|
|
7158
7362
|
const info = await tronWeb.trx.getTransactionInfo(txHash);
|
|
7159
|
-
|
|
7160
|
-
if (info) {
|
|
7363
|
+
if (info && info.blockNumber) {
|
|
7161
7364
|
const result = info.receipt?.result;
|
|
7162
|
-
if (result
|
|
7163
|
-
|
|
7365
|
+
if (result !== "SUCCESS") {
|
|
7366
|
+
const msg = this.hexToAscii(info.resMessage) || null;
|
|
7367
|
+
let reason = msg;
|
|
7368
|
+
const cr = info.contractResult?.[0];
|
|
7369
|
+
if (cr && /^0x?08c379a0/i.test(cr)) {
|
|
7370
|
+
try {
|
|
7371
|
+
const clean = cr.replace(/^0x/, "");
|
|
7372
|
+
const len = parseInt(clean.slice(8 + 64, 8 + 64 + 64), 16);
|
|
7373
|
+
const strHex = clean.slice(
|
|
7374
|
+
8 + 64 + 64,
|
|
7375
|
+
8 + 64 + 64 + len * 2
|
|
7376
|
+
);
|
|
7377
|
+
const str = this.hexToAscii("0x" + strHex);
|
|
7378
|
+
if (str) reason = str;
|
|
7379
|
+
} catch (e) {
|
|
7380
|
+
console.debug("TRON revert string decode error", e);
|
|
7381
|
+
}
|
|
7382
|
+
}
|
|
7383
|
+
const error2 = new TransactionRevertedError(
|
|
7384
|
+
"tron",
|
|
7385
|
+
txHash,
|
|
7386
|
+
reason || "Unknown error"
|
|
7387
|
+
);
|
|
7164
7388
|
return {
|
|
7165
|
-
completed:
|
|
7389
|
+
completed: false,
|
|
7390
|
+
error: error2.message
|
|
7166
7391
|
};
|
|
7167
7392
|
}
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7393
|
+
txBlockNumber = info.blockNumber;
|
|
7394
|
+
console.log(`TRON transaction found in block ${txBlockNumber}`);
|
|
7395
|
+
}
|
|
7396
|
+
} catch (e) {
|
|
7397
|
+
console.debug("TRON getTransactionInfo error:", e);
|
|
7398
|
+
}
|
|
7399
|
+
if (!txBlockNumber) {
|
|
7400
|
+
await new Promise((r) => setTimeout(r, TRON_CONFIG.pollingInterval));
|
|
7401
|
+
}
|
|
7402
|
+
}
|
|
7403
|
+
if (!txBlockNumber) {
|
|
7404
|
+
const error2 = new TransactionTimeoutError("tron", txHash);
|
|
7405
|
+
return {
|
|
7406
|
+
completed: false,
|
|
7407
|
+
error: error2.message
|
|
7408
|
+
};
|
|
7409
|
+
}
|
|
7410
|
+
let confirmations = 0;
|
|
7411
|
+
while (Date.now() < deadline) {
|
|
7412
|
+
try {
|
|
7413
|
+
const currentBlock = await tronWeb.trx.getCurrentBlock();
|
|
7414
|
+
const currentBlockNumber = currentBlock?.block_header?.raw_data?.number;
|
|
7415
|
+
if (currentBlockNumber) {
|
|
7416
|
+
confirmations = currentBlockNumber - txBlockNumber;
|
|
7417
|
+
if (confirmations >= TRON_CONFIG.requiredConfirmations) {
|
|
7418
|
+
console.log(
|
|
7419
|
+
`TRON transaction confirmed in block ${txBlockNumber} with ${confirmations} confirmations`
|
|
7420
|
+
);
|
|
7421
|
+
return {
|
|
7422
|
+
completed: true
|
|
7423
|
+
};
|
|
7181
7424
|
}
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
txHash,
|
|
7185
|
-
reason || "Unknown error"
|
|
7425
|
+
console.log(
|
|
7426
|
+
`TRON transaction confirmations: ${confirmations}/${TRON_CONFIG.requiredConfirmations}`
|
|
7186
7427
|
);
|
|
7187
|
-
return {
|
|
7188
|
-
completed: false,
|
|
7189
|
-
error: error2.message
|
|
7190
|
-
};
|
|
7191
7428
|
}
|
|
7192
7429
|
} catch (e) {
|
|
7193
|
-
console.debug("TRON
|
|
7430
|
+
console.debug("TRON getCurrentBlock error:", e);
|
|
7194
7431
|
}
|
|
7195
|
-
await new Promise((r) => setTimeout(r,
|
|
7432
|
+
await new Promise((r) => setTimeout(r, TRON_CONFIG.pollingInterval));
|
|
7196
7433
|
}
|
|
7197
7434
|
const error = new TransactionTimeoutError("tron", txHash);
|
|
7198
7435
|
return {
|
|
@@ -7200,14 +7437,17 @@ class TronChainStrategy {
|
|
|
7200
7437
|
error: error.message
|
|
7201
7438
|
};
|
|
7202
7439
|
} catch (error) {
|
|
7203
|
-
const chainError = toChainStrategyError(
|
|
7440
|
+
const chainError = toChainStrategyError(
|
|
7441
|
+
error,
|
|
7442
|
+
"tron",
|
|
7443
|
+
"waitForCompletion"
|
|
7444
|
+
);
|
|
7204
7445
|
return {
|
|
7205
7446
|
completed: false,
|
|
7206
7447
|
error: chainError.message
|
|
7207
7448
|
};
|
|
7208
7449
|
}
|
|
7209
7450
|
}
|
|
7210
|
-
// ========== Private Helper Methods ==========
|
|
7211
7451
|
getTronWeb() {
|
|
7212
7452
|
return typeof window !== "undefined" ? window.tronWeb : void 0;
|
|
7213
7453
|
}
|
|
@@ -7260,7 +7500,10 @@ class TronChainStrategy {
|
|
|
7260
7500
|
amount: this.extractAmountFromTxData(tx.data)
|
|
7261
7501
|
};
|
|
7262
7502
|
}
|
|
7263
|
-
throw new InvalidTransactionDataError(
|
|
7503
|
+
throw new InvalidTransactionDataError(
|
|
7504
|
+
"tron",
|
|
7505
|
+
"Cannot parse approve transaction"
|
|
7506
|
+
);
|
|
7264
7507
|
}
|
|
7265
7508
|
if (step?.type === "transfer" || step?.type === "bridge") {
|
|
7266
7509
|
const s = step;
|
|
@@ -7290,7 +7533,10 @@ class TronChainStrategy {
|
|
|
7290
7533
|
feeLimit: raw2.feeLimit
|
|
7291
7534
|
};
|
|
7292
7535
|
}
|
|
7293
|
-
throw new InvalidTransactionDataError(
|
|
7536
|
+
throw new InvalidTransactionDataError(
|
|
7537
|
+
"tron",
|
|
7538
|
+
"Cannot parse transfer/bridge transaction"
|
|
7539
|
+
);
|
|
7294
7540
|
}
|
|
7295
7541
|
if (tx?.to && tx?.value && !tx?.data) {
|
|
7296
7542
|
const v = BigInt(tx.value.toString());
|
|
@@ -7310,19 +7556,28 @@ class TronChainStrategy {
|
|
|
7310
7556
|
feeLimit: raw.feeLimit
|
|
7311
7557
|
};
|
|
7312
7558
|
}
|
|
7313
|
-
throw new InvalidTransactionDataError(
|
|
7559
|
+
throw new InvalidTransactionDataError(
|
|
7560
|
+
"tron",
|
|
7561
|
+
`Unsupported TRON step type: ${step?.type ?? "unknown"}`
|
|
7562
|
+
);
|
|
7314
7563
|
}
|
|
7315
7564
|
extractSpenderFromTxData(data) {
|
|
7316
7565
|
const clean = data.replace(/^0x/, "");
|
|
7317
7566
|
if (clean.length < 74) {
|
|
7318
|
-
throw new InvalidTransactionDataError(
|
|
7567
|
+
throw new InvalidTransactionDataError(
|
|
7568
|
+
"tron",
|
|
7569
|
+
"Invalid transaction data length"
|
|
7570
|
+
);
|
|
7319
7571
|
}
|
|
7320
7572
|
return "41" + clean.slice(32, 72);
|
|
7321
7573
|
}
|
|
7322
7574
|
extractAmountFromTxData(data) {
|
|
7323
7575
|
const clean = data.replace(/^0x/, "");
|
|
7324
7576
|
if (clean.length < 138) {
|
|
7325
|
-
throw new InvalidTransactionDataError(
|
|
7577
|
+
throw new InvalidTransactionDataError(
|
|
7578
|
+
"tron",
|
|
7579
|
+
"Invalid transaction data length"
|
|
7580
|
+
);
|
|
7326
7581
|
}
|
|
7327
7582
|
const amountHex = clean.slice(72, 136);
|
|
7328
7583
|
return BigInt("0x" + amountHex).toString();
|
|
@@ -7330,7 +7585,10 @@ class TronChainStrategy {
|
|
|
7330
7585
|
extractRecipientFromTxData(data) {
|
|
7331
7586
|
const clean = data.replace(/^0x/, "");
|
|
7332
7587
|
if (clean.length < 74) {
|
|
7333
|
-
throw new InvalidTransactionDataError(
|
|
7588
|
+
throw new InvalidTransactionDataError(
|
|
7589
|
+
"tron",
|
|
7590
|
+
"Invalid transaction data length"
|
|
7591
|
+
);
|
|
7334
7592
|
}
|
|
7335
7593
|
return "41" + clean.slice(32, 72);
|
|
7336
7594
|
}
|
|
@@ -7405,7 +7663,6 @@ class TronChainStrategy {
|
|
|
7405
7663
|
return null;
|
|
7406
7664
|
}
|
|
7407
7665
|
}
|
|
7408
|
-
// ========== Transaction Builders ==========
|
|
7409
7666
|
async buildApprove(tronWeb, p) {
|
|
7410
7667
|
const res = await tronWeb.transactionBuilder.triggerSmartContract(
|
|
7411
7668
|
p.token,
|
|
@@ -7418,7 +7675,10 @@ class TronChainStrategy {
|
|
|
7418
7675
|
p.from
|
|
7419
7676
|
);
|
|
7420
7677
|
if (!res?.transaction) {
|
|
7421
|
-
throw new TransactionFailedError(
|
|
7678
|
+
throw new TransactionFailedError(
|
|
7679
|
+
"tron",
|
|
7680
|
+
"Failed to build approve transaction"
|
|
7681
|
+
);
|
|
7422
7682
|
}
|
|
7423
7683
|
return res.transaction;
|
|
7424
7684
|
}
|
|
@@ -7434,7 +7694,10 @@ class TronChainStrategy {
|
|
|
7434
7694
|
p.from
|
|
7435
7695
|
);
|
|
7436
7696
|
if (!res?.transaction) {
|
|
7437
|
-
throw new TransactionFailedError(
|
|
7697
|
+
throw new TransactionFailedError(
|
|
7698
|
+
"tron",
|
|
7699
|
+
"Failed to build transfer transaction"
|
|
7700
|
+
);
|
|
7438
7701
|
}
|
|
7439
7702
|
return res.transaction;
|
|
7440
7703
|
}
|
|
@@ -7454,12 +7717,13 @@ class TronChainStrategy {
|
|
|
7454
7717
|
p.from
|
|
7455
7718
|
);
|
|
7456
7719
|
if (!res?.transaction) {
|
|
7457
|
-
throw new TransactionFailedError(
|
|
7720
|
+
throw new TransactionFailedError(
|
|
7721
|
+
"tron",
|
|
7722
|
+
"Failed to build raw call transaction"
|
|
7723
|
+
);
|
|
7458
7724
|
}
|
|
7459
7725
|
return res.transaction;
|
|
7460
7726
|
}
|
|
7461
|
-
// ========== Transaction Sender ==========
|
|
7462
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7463
7727
|
async signAndBroadcast(tronWeb, unsignedTx) {
|
|
7464
7728
|
const signed = await tronWeb.trx.sign(unsignedTx);
|
|
7465
7729
|
const sent = await tronWeb.trx.sendRawTransaction(signed);
|
|
@@ -7471,33 +7735,77 @@ class TronChainStrategy {
|
|
|
7471
7735
|
}
|
|
7472
7736
|
return { txid: sent.txid };
|
|
7473
7737
|
}
|
|
7738
|
+
/**
|
|
7739
|
+
* Check if a transaction has been solidified (confirmed by solidityNode)
|
|
7740
|
+
* This is an additional check for critical transactions to ensure they are
|
|
7741
|
+
* truly confirmed and available through the solidityNode API.
|
|
7742
|
+
*
|
|
7743
|
+
* Usage: Call this method after waitForCompletion for high-value transactions
|
|
7744
|
+
* to get additional assurance that the transaction is solidified.
|
|
7745
|
+
*
|
|
7746
|
+
* @param txHash - Transaction hash to check
|
|
7747
|
+
* @returns true if the transaction is solidified, false otherwise
|
|
7748
|
+
*/
|
|
7749
|
+
async checkSolidified(txHash) {
|
|
7750
|
+
try {
|
|
7751
|
+
const tronWeb = this.getTronWeb();
|
|
7752
|
+
if (!tronWeb) {
|
|
7753
|
+
return false;
|
|
7754
|
+
}
|
|
7755
|
+
const info = await tronWeb.trx.getTransactionInfo(txHash);
|
|
7756
|
+
if (!info || !info.blockNumber) {
|
|
7757
|
+
console.debug(
|
|
7758
|
+
"Transaction not yet solidified (no blockNumber in info)"
|
|
7759
|
+
);
|
|
7760
|
+
return false;
|
|
7761
|
+
}
|
|
7762
|
+
const result = info.receipt?.result;
|
|
7763
|
+
if (result === "SUCCESS") {
|
|
7764
|
+
console.log(
|
|
7765
|
+
`Transaction ${txHash} is solidified in block ${info.blockNumber}`
|
|
7766
|
+
);
|
|
7767
|
+
return true;
|
|
7768
|
+
}
|
|
7769
|
+
console.debug(`Transaction solidified but result is: ${result}`);
|
|
7770
|
+
return false;
|
|
7771
|
+
} catch (error) {
|
|
7772
|
+
console.debug("Error checking solidified status:", error);
|
|
7773
|
+
return false;
|
|
7774
|
+
}
|
|
7775
|
+
}
|
|
7474
7776
|
}
|
|
7475
7777
|
function ChainStrategyProvider({
|
|
7476
7778
|
children,
|
|
7477
7779
|
evmWallet,
|
|
7478
7780
|
tonWallet,
|
|
7479
|
-
tronWallet
|
|
7781
|
+
tronWallet,
|
|
7782
|
+
tonClient,
|
|
7783
|
+
tonApiKey
|
|
7480
7784
|
}) {
|
|
7481
7785
|
const evmStrategy = useMemo(
|
|
7482
7786
|
() => new EvmChainStrategy({
|
|
7483
7787
|
evmAddress: evmWallet.address,
|
|
7484
7788
|
evmIsConnected: evmWallet.isConnected,
|
|
7485
7789
|
evmDisconnect: evmWallet.disconnect,
|
|
7486
|
-
walletClient: evmWallet.walletClient
|
|
7790
|
+
walletClient: evmWallet.walletClient,
|
|
7791
|
+
publicClient: evmWallet.publicClient
|
|
7487
7792
|
}),
|
|
7488
7793
|
[
|
|
7489
7794
|
evmWallet.address,
|
|
7490
7795
|
evmWallet.isConnected,
|
|
7491
7796
|
evmWallet.disconnect,
|
|
7492
|
-
evmWallet.walletClient
|
|
7797
|
+
evmWallet.walletClient,
|
|
7798
|
+
evmWallet.publicClient
|
|
7493
7799
|
]
|
|
7494
7800
|
);
|
|
7495
7801
|
const tonStrategy = useMemo(
|
|
7496
7802
|
() => new TonChainStrategy({
|
|
7497
7803
|
tonConnectUI: tonWallet.tonConnectUI,
|
|
7498
|
-
tonAddress: tonWallet.address
|
|
7804
|
+
tonAddress: tonWallet.address,
|
|
7805
|
+
tonClient,
|
|
7806
|
+
tonApiKey
|
|
7499
7807
|
}),
|
|
7500
|
-
[tonWallet.tonConnectUI, tonWallet.address]
|
|
7808
|
+
[tonWallet.tonConnectUI, tonWallet.address, tonClient, tonApiKey]
|
|
7501
7809
|
);
|
|
7502
7810
|
const tronStrategy = useMemo(
|
|
7503
7811
|
() => new TronChainStrategy({
|
|
@@ -7533,6 +7841,7 @@ const EvaaBridgeWithProviders = (props) => {
|
|
|
7533
7841
|
const { address: evmAddress, isConnected: evmIsConnected } = useAccount();
|
|
7534
7842
|
const { disconnect: evmDisconnect } = useDisconnect();
|
|
7535
7843
|
const { data: walletClient } = useWalletClient();
|
|
7844
|
+
const publicClient = usePublicClient();
|
|
7536
7845
|
const {
|
|
7537
7846
|
address: tronAddress,
|
|
7538
7847
|
connected: tronConnected,
|
|
@@ -7550,14 +7859,15 @@ const EvaaBridgeWithProviders = (props) => {
|
|
|
7550
7859
|
useEffect(() => {
|
|
7551
7860
|
setTronConnected(!!tronConnected);
|
|
7552
7861
|
}, [tronConnected, setTronConnected]);
|
|
7553
|
-
return /* @__PURE__ */ jsx(
|
|
7862
|
+
return /* @__PURE__ */ jsx(ModalContainerProvider, { containerId: props.modalContainerId, children: /* @__PURE__ */ jsx(
|
|
7554
7863
|
ChainStrategyProvider,
|
|
7555
7864
|
{
|
|
7556
7865
|
evmWallet: {
|
|
7557
7866
|
address: evmAddress,
|
|
7558
7867
|
isConnected: evmIsConnected,
|
|
7559
7868
|
disconnect: evmDisconnect,
|
|
7560
|
-
walletClient
|
|
7869
|
+
walletClient,
|
|
7870
|
+
publicClient
|
|
7561
7871
|
},
|
|
7562
7872
|
tonWallet: {
|
|
7563
7873
|
tonConnectUI,
|
|
@@ -7570,9 +7880,11 @@ const EvaaBridgeWithProviders = (props) => {
|
|
|
7570
7880
|
connect: tronConnect,
|
|
7571
7881
|
disconnect: tronDisconnect
|
|
7572
7882
|
},
|
|
7883
|
+
tonClient: props.tonClient,
|
|
7884
|
+
tonApiKey: props.tonApiKey,
|
|
7573
7885
|
children: /* @__PURE__ */ jsx(EvaaBridgeContent, { ...props })
|
|
7574
7886
|
}
|
|
7575
|
-
);
|
|
7887
|
+
) });
|
|
7576
7888
|
};
|
|
7577
7889
|
const EvaaBridgeContent = ({
|
|
7578
7890
|
className,
|
|
@@ -7581,7 +7893,6 @@ const EvaaBridgeContent = ({
|
|
|
7581
7893
|
onChainChange
|
|
7582
7894
|
} = {}) => {
|
|
7583
7895
|
const { t: t2 } = useTranslation();
|
|
7584
|
-
const modalContainerRef = useRef(null);
|
|
7585
7896
|
useTokensRequest();
|
|
7586
7897
|
useChainsRequest();
|
|
7587
7898
|
const [sendToAnother, setSendToAnother] = useState(false);
|
|
@@ -7674,16 +7985,15 @@ const EvaaBridgeContent = ({
|
|
|
7674
7985
|
}, [chains, assetMatrix, allowedFromChains]);
|
|
7675
7986
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7676
7987
|
/* @__PURE__ */ jsxs(
|
|
7677
|
-
|
|
7988
|
+
Card,
|
|
7678
7989
|
{
|
|
7679
7990
|
className: cn(
|
|
7680
|
-
"
|
|
7991
|
+
"max-w-md w-full mx-auto flex flex-col relative",
|
|
7681
7992
|
className
|
|
7682
7993
|
),
|
|
7683
|
-
ref: modalContainerRef,
|
|
7684
7994
|
children: [
|
|
7685
|
-
/* @__PURE__ */ jsx(FormHeader, {
|
|
7686
|
-
/* @__PURE__ */ jsxs(
|
|
7995
|
+
/* @__PURE__ */ jsx(FormHeader, {}),
|
|
7996
|
+
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-[1px]", children: [
|
|
7687
7997
|
/* @__PURE__ */ jsx(
|
|
7688
7998
|
SwapSection,
|
|
7689
7999
|
{
|
|
@@ -7696,8 +8006,7 @@ const EvaaBridgeContent = ({
|
|
|
7696
8006
|
amount,
|
|
7697
8007
|
isSource: true,
|
|
7698
8008
|
onAmountChange: handleAmountChange,
|
|
7699
|
-
onSelect: handleFromChainChange
|
|
7700
|
-
modalContainer: modalContainerRef.current || void 0
|
|
8009
|
+
onSelect: handleFromChainChange
|
|
7701
8010
|
}
|
|
7702
8011
|
),
|
|
7703
8012
|
/* @__PURE__ */ jsx(SwapButton, {}),
|
|
@@ -7711,8 +8020,7 @@ const EvaaBridgeContent = ({
|
|
|
7711
8020
|
allowedChains: allowedToChains,
|
|
7712
8021
|
amount: outputAmount,
|
|
7713
8022
|
readOnlyAmount: true,
|
|
7714
|
-
onSelect: handleToChainChange
|
|
7715
|
-
modalContainer: modalContainerRef.current || void 0
|
|
8023
|
+
onSelect: handleToChainChange
|
|
7716
8024
|
}
|
|
7717
8025
|
),
|
|
7718
8026
|
/* @__PURE__ */ jsx(
|
|
@@ -7721,15 +8029,15 @@ const EvaaBridgeContent = ({
|
|
|
7721
8029
|
enabled: sendToAnother,
|
|
7722
8030
|
onToggle: () => setSendToAnother((v) => !v)
|
|
7723
8031
|
}
|
|
7724
|
-
)
|
|
8032
|
+
),
|
|
8033
|
+
/* @__PURE__ */ jsx(SubmitButton, {})
|
|
7725
8034
|
] }),
|
|
7726
|
-
/* @__PURE__ */ jsx(
|
|
7727
|
-
/* @__PURE__ */ jsx(ReceiveRow, {})
|
|
8035
|
+
/* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(ReceiveRow, {}) })
|
|
7728
8036
|
]
|
|
7729
8037
|
}
|
|
7730
8038
|
),
|
|
7731
|
-
/* @__PURE__ */ jsx(WalletSelectModal, {
|
|
7732
|
-
/* @__PURE__ */ jsx(TransactionManager, {
|
|
8039
|
+
/* @__PURE__ */ jsx(WalletSelectModal, {}),
|
|
8040
|
+
/* @__PURE__ */ jsx(TransactionManager, {}),
|
|
7733
8041
|
/* @__PURE__ */ jsx(Toaster, { position: "top-right", richColors: true })
|
|
7734
8042
|
] });
|
|
7735
8043
|
};
|
|
@@ -7813,8 +8121,8 @@ export {
|
|
|
7813
8121
|
getQuoteDetails,
|
|
7814
8122
|
getQuoteFees,
|
|
7815
8123
|
getQuotesByPriority,
|
|
7816
|
-
getSwapBalances,
|
|
7817
8124
|
getTokens,
|
|
8125
|
+
getTonBalances,
|
|
7818
8126
|
getTronBalances,
|
|
7819
8127
|
isAddressValidForChain,
|
|
7820
8128
|
isEvmAddress,
|
|
@@ -7823,7 +8131,7 @@ export {
|
|
|
7823
8131
|
isZeroAddr,
|
|
7824
8132
|
listAssetsForSelect,
|
|
7825
8133
|
lookupTokenMeta,
|
|
7826
|
-
normalizeTickerSymbol,
|
|
8134
|
+
normalizeTickerSymbol$1 as normalizeTickerSymbol,
|
|
7827
8135
|
pollUntilDelivered,
|
|
7828
8136
|
resolveTokenOnChain,
|
|
7829
8137
|
resolveTokenOnChainFromMatrix$2 as resolveTokenOnChainFromMatrix,
|