@rash2x/bridge-widget 0.1.4 → 0.1.5
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 +655 -345
- package/dist/evaa-bridge.cjs.map +1 -1
- package/dist/evaa-bridge.mjs +660 -350
- package/dist/evaa-bridge.mjs.map +1 -1
- package/dist/index.d.ts +7 -3
- package/package.json +7 -11
package/dist/evaa-bridge.cjs
CHANGED
|
@@ -44,10 +44,11 @@ const reactWindow = require("react-window");
|
|
|
44
44
|
const SwitchPrimitive = require("@radix-ui/react-switch");
|
|
45
45
|
const lucideReact = require("lucide-react");
|
|
46
46
|
const AccordionPrimitive = require("@radix-ui/react-accordion");
|
|
47
|
-
const connectkit = require("connectkit");
|
|
48
47
|
const i18next = require("i18next");
|
|
49
48
|
const sonner = require("sonner");
|
|
50
49
|
const ethers = require("ethers");
|
|
50
|
+
const viem = require("viem");
|
|
51
|
+
const ton = require("@ton/ton");
|
|
51
52
|
const tronwalletAdapters = require("@tronweb3/tronwallet-adapters");
|
|
52
53
|
function _interopNamespaceDefault(e) {
|
|
53
54
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -551,7 +552,7 @@ function cn(...inputs) {
|
|
|
551
552
|
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
552
553
|
}
|
|
553
554
|
const buttonVariants = classVarianceAuthority.cva(
|
|
554
|
-
"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",
|
|
555
|
+
"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",
|
|
555
556
|
{
|
|
556
557
|
variants: {
|
|
557
558
|
variant: {
|
|
@@ -824,19 +825,6 @@ const Tip = (props) => {
|
|
|
824
825
|
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: text }) })
|
|
825
826
|
] });
|
|
826
827
|
};
|
|
827
|
-
function toLD(human, decimals) {
|
|
828
|
-
const [i = "0", f = ""] = human.replace(",", ".").split(".");
|
|
829
|
-
const frac = (f + "0".repeat(decimals)).slice(0, decimals);
|
|
830
|
-
return BigInt(i + frac).toString();
|
|
831
|
-
}
|
|
832
|
-
function fromLD(ld, decimals) {
|
|
833
|
-
const bi = BigInt(ld || "0");
|
|
834
|
-
if (decimals === 0) return Number(bi);
|
|
835
|
-
const base = BigInt(10) ** BigInt(decimals);
|
|
836
|
-
const int = bi / base;
|
|
837
|
-
const frac = Number(bi % base) / Number(base);
|
|
838
|
-
return Number(int) + frac;
|
|
839
|
-
}
|
|
840
828
|
async function getChains() {
|
|
841
829
|
const res = await fetch("https://stargate.finance/api/v1/chains", {
|
|
842
830
|
credentials: "same-origin"
|
|
@@ -884,49 +872,16 @@ async function getDestTokens(srcChainKey, srcTokenAddr) {
|
|
|
884
872
|
});
|
|
885
873
|
return unique;
|
|
886
874
|
}
|
|
887
|
-
|
|
888
|
-
function normalizeTickerSymbol(s) {
|
|
875
|
+
function normalizeTickerSymbol$1(s) {
|
|
889
876
|
return s.toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
|
|
890
877
|
}
|
|
891
|
-
async function getSwapBalances(accountFriendly) {
|
|
892
|
-
if (!isTonFriendly(accountFriendly)) throw new Error("Invalid TON address");
|
|
893
|
-
const accRes = await fetch(
|
|
894
|
-
`https://tonapi.io/v2/accounts/${accountFriendly}`
|
|
895
|
-
);
|
|
896
|
-
if (!accRes.ok) throw new Error(`TON account fetch failed: ${accRes.status}`);
|
|
897
|
-
const acc = await accRes.json();
|
|
898
|
-
const ton = fromLD(String(acc?.balance ?? "0"), 9);
|
|
899
|
-
const result = {
|
|
900
|
-
TON: { balance: ton, address: "ton-native" }
|
|
901
|
-
};
|
|
902
|
-
const jetsRes = await fetch(
|
|
903
|
-
`https://tonapi.io/v2/accounts/${accountFriendly}/jettons?limit=200`
|
|
904
|
-
);
|
|
905
|
-
if (!jetsRes.ok) return result;
|
|
906
|
-
const jets = await jetsRes.json();
|
|
907
|
-
const items = jets?.balances ?? jets?.jettons ?? jets?.items ?? [];
|
|
908
|
-
for (const it of items) {
|
|
909
|
-
const rawSym = (it?.jetton?.symbol ?? it?.symbol ?? "").toString();
|
|
910
|
-
if (!rawSym) continue;
|
|
911
|
-
const symUpper = rawSym.toUpperCase();
|
|
912
|
-
const symNorm = normalizeTickerSymbol(symUpper);
|
|
913
|
-
const master = (it?.jetton?.address ?? it?.address ?? "").toString();
|
|
914
|
-
const decimals = Number(it?.jetton?.decimals ?? it?.decimals ?? 9) || 9;
|
|
915
|
-
const raw = (it?.balance ?? "0").toString();
|
|
916
|
-
const human = fromLD(raw, decimals);
|
|
917
|
-
const entry = { balance: human, address: master };
|
|
918
|
-
result[symUpper] = entry;
|
|
919
|
-
if (symNorm !== symUpper) result[symNorm] = entry;
|
|
920
|
-
}
|
|
921
|
-
return result;
|
|
922
|
-
}
|
|
923
878
|
const BASE_URL$1 = "https://icons-ckg.pages.dev/stargate-light/tokens";
|
|
924
879
|
const TokenSymbol = ({
|
|
925
880
|
symbol,
|
|
926
881
|
className = "w-4 h-4",
|
|
927
882
|
alt
|
|
928
883
|
}) => {
|
|
929
|
-
const normalizedSymbol = normalizeTickerSymbol(symbol).toLowerCase();
|
|
884
|
+
const normalizedSymbol = normalizeTickerSymbol$1(symbol).toLowerCase();
|
|
930
885
|
const src = `${BASE_URL$1}/${normalizedSymbol}.svg`;
|
|
931
886
|
return /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: alt ?? symbol, className });
|
|
932
887
|
};
|
|
@@ -1340,6 +1295,19 @@ function useChainStrategies() {
|
|
|
1340
1295
|
}
|
|
1341
1296
|
return context;
|
|
1342
1297
|
}
|
|
1298
|
+
function toLD(human, decimals) {
|
|
1299
|
+
const [i = "0", f = ""] = human.replace(",", ".").split(".");
|
|
1300
|
+
const frac = (f + "0".repeat(decimals)).slice(0, decimals);
|
|
1301
|
+
return BigInt(i + frac).toString();
|
|
1302
|
+
}
|
|
1303
|
+
function fromLD(ld, decimals) {
|
|
1304
|
+
const bi = BigInt(ld || "0");
|
|
1305
|
+
if (decimals === 0) return Number(bi);
|
|
1306
|
+
const base = BigInt(10) ** BigInt(decimals);
|
|
1307
|
+
const int = bi / base;
|
|
1308
|
+
const frac = Number(bi % base) / Number(base);
|
|
1309
|
+
return Number(int) + frac;
|
|
1310
|
+
}
|
|
1343
1311
|
function resolveTokenOnChainFromMatrix$2(assetMatrix, assetSymbol, chainKey) {
|
|
1344
1312
|
if (!assetMatrix || !assetSymbol || !chainKey) return void 0;
|
|
1345
1313
|
const byChain = assetMatrix[assetSymbol.toUpperCase()];
|
|
@@ -1521,20 +1489,17 @@ function useBalances(chainKey, address) {
|
|
|
1521
1489
|
const data = query.data;
|
|
1522
1490
|
if (data) {
|
|
1523
1491
|
for (const [sum, v] of Object.entries(data)) {
|
|
1524
|
-
map.set(normalizeTickerSymbol(sum), Number(v.balance ?? 0));
|
|
1492
|
+
map.set(normalizeTickerSymbol$1(sum), Number(v.balance ?? 0));
|
|
1525
1493
|
}
|
|
1526
1494
|
}
|
|
1527
1495
|
return map;
|
|
1528
1496
|
}, [query.data]);
|
|
1529
1497
|
const getBalance = require$$0.useCallback(
|
|
1530
|
-
(symbol) => balanceBySymbol.get(normalizeTickerSymbol(symbol)) ?? 0,
|
|
1498
|
+
(symbol) => balanceBySymbol.get(normalizeTickerSymbol$1(symbol)) ?? 0,
|
|
1531
1499
|
[balanceBySymbol]
|
|
1532
1500
|
);
|
|
1533
1501
|
const isLoading = query.isLoading || query.isFetching;
|
|
1534
|
-
const balances = require$$0.useMemo(
|
|
1535
|
-
() => query.data || {},
|
|
1536
|
-
[query.data]
|
|
1537
|
-
);
|
|
1502
|
+
const balances = require$$0.useMemo(() => query.data || {}, [query.data]);
|
|
1538
1503
|
return {
|
|
1539
1504
|
balances,
|
|
1540
1505
|
getBalance,
|
|
@@ -1990,17 +1955,17 @@ const RefreshButton = () => {
|
|
|
1990
1955
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1991
1956
|
Button,
|
|
1992
1957
|
{
|
|
1993
|
-
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" : ""}`,
|
|
1994
1958
|
onClick: handleRefresh,
|
|
1995
1959
|
disabled: spinning,
|
|
1960
|
+
variant: "secondary",
|
|
1961
|
+
size: "sm",
|
|
1996
1962
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1997
1963
|
ReloadIcon,
|
|
1998
1964
|
{
|
|
1999
1965
|
style: {
|
|
2000
1966
|
transform: `rotate(${turns * 180}deg)`,
|
|
2001
1967
|
transition: "transform 300ms linear"
|
|
2002
|
-
}
|
|
2003
|
-
className: "size-4 text-foreground m-1 will-change-transform"
|
|
1968
|
+
}
|
|
2004
1969
|
}
|
|
2005
1970
|
)
|
|
2006
1971
|
}
|
|
@@ -2008,7 +1973,6 @@ const RefreshButton = () => {
|
|
|
2008
1973
|
};
|
|
2009
1974
|
const SelectTokenButton = ({
|
|
2010
1975
|
onClick,
|
|
2011
|
-
className,
|
|
2012
1976
|
token
|
|
2013
1977
|
}) => {
|
|
2014
1978
|
const { t } = reactI18next.useTranslation();
|
|
@@ -2019,7 +1983,8 @@ const SelectTokenButton = ({
|
|
|
2019
1983
|
Button,
|
|
2020
1984
|
{
|
|
2021
1985
|
onClick,
|
|
2022
|
-
|
|
1986
|
+
size: "sm",
|
|
1987
|
+
variant: "secondary",
|
|
2023
1988
|
type: "button",
|
|
2024
1989
|
"aria-label": label,
|
|
2025
1990
|
children: [
|
|
@@ -2039,6 +2004,75 @@ const SelectTokenButton = ({
|
|
|
2039
2004
|
}
|
|
2040
2005
|
);
|
|
2041
2006
|
};
|
|
2007
|
+
function Card({ className, ...props }) {
|
|
2008
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2009
|
+
"div",
|
|
2010
|
+
{
|
|
2011
|
+
"data-slot": "card",
|
|
2012
|
+
className: cn(
|
|
2013
|
+
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
|
2014
|
+
className
|
|
2015
|
+
),
|
|
2016
|
+
...props
|
|
2017
|
+
}
|
|
2018
|
+
);
|
|
2019
|
+
}
|
|
2020
|
+
function CardHeader({ className, ...props }) {
|
|
2021
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2022
|
+
"div",
|
|
2023
|
+
{
|
|
2024
|
+
"data-slot": "card-header",
|
|
2025
|
+
className: cn(
|
|
2026
|
+
"@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",
|
|
2027
|
+
className
|
|
2028
|
+
),
|
|
2029
|
+
...props
|
|
2030
|
+
}
|
|
2031
|
+
);
|
|
2032
|
+
}
|
|
2033
|
+
function CardTitle({ className, ...props }) {
|
|
2034
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2035
|
+
"div",
|
|
2036
|
+
{
|
|
2037
|
+
"data-slot": "card-title",
|
|
2038
|
+
className: cn("leading-none font-semibold", className),
|
|
2039
|
+
...props
|
|
2040
|
+
}
|
|
2041
|
+
);
|
|
2042
|
+
}
|
|
2043
|
+
function CardAction({ className, ...props }) {
|
|
2044
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2045
|
+
"div",
|
|
2046
|
+
{
|
|
2047
|
+
"data-slot": "card-action",
|
|
2048
|
+
className: cn(
|
|
2049
|
+
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
|
2050
|
+
className
|
|
2051
|
+
),
|
|
2052
|
+
...props
|
|
2053
|
+
}
|
|
2054
|
+
);
|
|
2055
|
+
}
|
|
2056
|
+
function CardContent({ className, ...props }) {
|
|
2057
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2058
|
+
"div",
|
|
2059
|
+
{
|
|
2060
|
+
"data-slot": "card-content",
|
|
2061
|
+
className: cn("px-6", className),
|
|
2062
|
+
...props
|
|
2063
|
+
}
|
|
2064
|
+
);
|
|
2065
|
+
}
|
|
2066
|
+
function CardFooter({ className, ...props }) {
|
|
2067
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2068
|
+
"div",
|
|
2069
|
+
{
|
|
2070
|
+
"data-slot": "card-footer",
|
|
2071
|
+
className: cn("flex items-center px-6 [.border-t]:pt-6", className),
|
|
2072
|
+
...props
|
|
2073
|
+
}
|
|
2074
|
+
);
|
|
2075
|
+
}
|
|
2042
2076
|
const FormHeaderComponent = ({ modalContainer }) => {
|
|
2043
2077
|
const { t } = reactI18next.useTranslation();
|
|
2044
2078
|
const { isOpen, onClose, onOpen } = useModal();
|
|
@@ -2055,29 +2089,14 @@ const FormHeaderComponent = ({ modalContainer }) => {
|
|
|
2055
2089
|
const sum = selectedAssetSymbol.toUpperCase();
|
|
2056
2090
|
return assets.find((a) => a.symbol.toUpperCase() === sum) ?? assets[0];
|
|
2057
2091
|
}, [assets, selectedAssetSymbol]);
|
|
2058
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2059
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2060
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2065
|
-
|
|
2066
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2067
|
-
Button,
|
|
2068
|
-
{
|
|
2069
|
-
className: "cursor-pointer py-1.5 h-8.5 hover:scale-110 shadow-none px-8.5 hover:bg-secondary bg-secondary !rounded-40",
|
|
2070
|
-
onClick: onOpenSettings,
|
|
2071
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2072
|
-
BoltIcon,
|
|
2073
|
-
{
|
|
2074
|
-
className: "size-4 text-foreground m-1",
|
|
2075
|
-
stroke: "currentColor"
|
|
2076
|
-
}
|
|
2077
|
-
)
|
|
2078
|
-
}
|
|
2079
|
-
)
|
|
2080
|
-
] })
|
|
2092
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "gap-y-0", children: [
|
|
2093
|
+
/* @__PURE__ */ jsxRuntime.jsxs(CardTitle, { className: "flex items-center gap-2.5", children: [
|
|
2094
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-normal leading-3.5 text-muted-foreground", children: t("bridge.selectToken") }),
|
|
2095
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTokenButton, { token: current, onClick: onOpen })
|
|
2096
|
+
] }),
|
|
2097
|
+
/* @__PURE__ */ jsxRuntime.jsxs(CardAction, { className: "flex items-center gap-2.5", children: [
|
|
2098
|
+
/* @__PURE__ */ jsxRuntime.jsx(RefreshButton, {}),
|
|
2099
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: onOpenSettings, size: "sm", variant: "secondary", children: /* @__PURE__ */ jsxRuntime.jsx(BoltIcon, { stroke: "currentColor" }) })
|
|
2081
2100
|
] }),
|
|
2082
2101
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2083
2102
|
TokenSelectModal,
|
|
@@ -3963,7 +3982,7 @@ function useSilentValidations(amountString) {
|
|
|
3963
3982
|
]);
|
|
3964
3983
|
return validationResult;
|
|
3965
3984
|
}
|
|
3966
|
-
|
|
3985
|
+
const SubmitButton = () => {
|
|
3967
3986
|
const { t } = reactI18next.useTranslation();
|
|
3968
3987
|
const { chainRegistry } = useChainStrategies();
|
|
3969
3988
|
const { srcAddress, dstAddress } = useAddresses();
|
|
@@ -4039,7 +4058,7 @@ function useTransferAction() {
|
|
|
4039
4058
|
maximumAmountFormatted,
|
|
4040
4059
|
chainRegistry
|
|
4041
4060
|
]);
|
|
4042
|
-
const
|
|
4061
|
+
const handleClick = async () => {
|
|
4043
4062
|
if (isBusy) return;
|
|
4044
4063
|
if (missingSrc && srcChainKey) {
|
|
4045
4064
|
onOpen("src");
|
|
@@ -4059,24 +4078,7 @@ function useTransferAction() {
|
|
|
4059
4078
|
}
|
|
4060
4079
|
};
|
|
4061
4080
|
const disabled = isBusy || amountNum <= 0 || status === "loading" || isBalanceLoading || hasInsufficientBalance || hasAmountTooLarge || !gas.hasEnoughGas || noRoute || !isValidForTransfer;
|
|
4062
|
-
return {
|
|
4063
|
-
// состояния
|
|
4064
|
-
isBusy,
|
|
4065
|
-
canTransfer,
|
|
4066
|
-
missingSrc,
|
|
4067
|
-
missingDst,
|
|
4068
|
-
hasEnoughGas: gas.hasEnoughGas,
|
|
4069
|
-
noRoute,
|
|
4070
|
-
// представление
|
|
4071
|
-
label,
|
|
4072
|
-
disabled,
|
|
4073
|
-
// действие
|
|
4074
|
-
onClick
|
|
4075
|
-
};
|
|
4076
|
-
}
|
|
4077
|
-
const SubmitButton = () => {
|
|
4078
|
-
const { label, disabled, onClick } = useTransferAction();
|
|
4079
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick, disabled, size: "lg", children: label });
|
|
4081
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleClick, disabled, className: "w-full", children: label });
|
|
4080
4082
|
};
|
|
4081
4083
|
function short(addr) {
|
|
4082
4084
|
return addr.slice(0, 4) + "…" + addr.slice(-4);
|
|
@@ -4086,6 +4088,7 @@ const WalletSelectModal = ({
|
|
|
4086
4088
|
}) => {
|
|
4087
4089
|
const { t } = reactI18next.useTranslation();
|
|
4088
4090
|
const { isOpen, onClose } = useWalletSelectModal();
|
|
4091
|
+
const { connect, connectors, isPending } = wagmi.useConnect();
|
|
4089
4092
|
const { chainRegistry } = useChainStrategies();
|
|
4090
4093
|
const tonWallet = chainRegistry.getStrategyByType("ton");
|
|
4091
4094
|
const metaMaskWallet = chainRegistry.getStrategyByType("evm");
|
|
@@ -4118,7 +4121,13 @@ const WalletSelectModal = ({
|
|
|
4118
4121
|
onDisconnect: () => tronWallet.disconnect()
|
|
4119
4122
|
});
|
|
4120
4123
|
}
|
|
4121
|
-
const isWalletConnected = (walletId) =>
|
|
4124
|
+
const isWalletConnected = (walletId) => {
|
|
4125
|
+
const isEvmConnector = connectors.some((c) => c.id === walletId);
|
|
4126
|
+
if (isEvmConnector && metaMaskWallet?.isConnected()) {
|
|
4127
|
+
return true;
|
|
4128
|
+
}
|
|
4129
|
+
return connectedWallets.some((w) => w.id === walletId);
|
|
4130
|
+
};
|
|
4122
4131
|
const tonWallets = [
|
|
4123
4132
|
{
|
|
4124
4133
|
id: "ton",
|
|
@@ -4127,14 +4136,15 @@ const WalletSelectModal = ({
|
|
|
4127
4136
|
enabled: true
|
|
4128
4137
|
}
|
|
4129
4138
|
];
|
|
4130
|
-
const evmWallets =
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4139
|
+
const evmWallets = connectors.filter(
|
|
4140
|
+
(connector) => connector.id === "walletConnect" || connector.id === "metaMaskSDK"
|
|
4141
|
+
).map((connector) => ({
|
|
4142
|
+
id: connector.id,
|
|
4143
|
+
name: connector.name,
|
|
4144
|
+
icon: MetaMaskIcon,
|
|
4145
|
+
// You can add a WalletConnect icon here
|
|
4146
|
+
enabled: true
|
|
4147
|
+
}));
|
|
4138
4148
|
const tronWallets = [
|
|
4139
4149
|
{
|
|
4140
4150
|
id: "tronlink",
|
|
@@ -4164,9 +4174,6 @@ const WalletSelectModal = ({
|
|
|
4164
4174
|
case "ton":
|
|
4165
4175
|
await tonWallet?.connect();
|
|
4166
4176
|
break;
|
|
4167
|
-
case "metamask":
|
|
4168
|
-
await metaMaskWallet?.connect();
|
|
4169
|
-
break;
|
|
4170
4177
|
case "tronlink":
|
|
4171
4178
|
await tronWallet?.connect();
|
|
4172
4179
|
break;
|
|
@@ -4191,56 +4198,47 @@ const WalletSelectModal = ({
|
|
|
4191
4198
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-2 leading-4 text-base font-semibold text-muted-foreground uppercase", children: t("wallets.connected") }),
|
|
4192
4199
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: connectedWallets.map((wallet) => {
|
|
4193
4200
|
const IconComponent = wallet.icon;
|
|
4194
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { onClick: () => {
|
|
4201
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: /* @__PURE__ */ jsxRuntime.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: [
|
|
4202
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
4203
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7.5 h-7.5 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: "size-7.5" }) }),
|
|
4204
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
|
|
4205
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-extrabold text-foreground text-sm leading-4 truncate", children: short(wallet.address) }),
|
|
4206
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: wallet.name })
|
|
4207
|
+
] })
|
|
4208
|
+
] }) }),
|
|
4209
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4210
|
+
"div",
|
|
4211
|
+
{
|
|
4212
|
+
onClick: () => {
|
|
4207
4213
|
wallet.onDisconnect();
|
|
4208
4214
|
onClose();
|
|
4209
|
-
},
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4215
|
+
},
|
|
4216
|
+
className: "text-sm font-medium text-muted-foreground",
|
|
4217
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ExitIcon, { className: "text-[#808080] size-6" })
|
|
4218
|
+
}
|
|
4219
|
+
)
|
|
4220
|
+
] }) }, wallet.id);
|
|
4213
4221
|
}) })
|
|
4214
4222
|
] }),
|
|
4215
4223
|
categories.map((category) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4216
4224
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-2 leading-4 text-base font-semibold text-muted-foreground uppercase", children: category.title }),
|
|
4217
4225
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: category.wallets.map((wallet) => {
|
|
4218
4226
|
const IconComponent = wallet.icon;
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4222
|
-
Button,
|
|
4223
|
-
{
|
|
4224
|
-
type: "button",
|
|
4225
|
-
onClick: show,
|
|
4226
|
-
disabled: isConnecting,
|
|
4227
|
-
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",
|
|
4228
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
4229
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7.5 h-7.5 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: "size-7.5" }) }),
|
|
4230
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
|
|
4231
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-extrabold text-foreground text-sm leading-4 truncate", children: wallet.name }),
|
|
4232
|
-
wallet.comingSoon ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: t("wallets.comingSoon") }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: t("wallets.connect") })
|
|
4233
|
-
] })
|
|
4234
|
-
] })
|
|
4235
|
-
}
|
|
4236
|
-
);
|
|
4237
|
-
} }) }, wallet.id);
|
|
4238
|
-
}
|
|
4227
|
+
const isEvmConnector = category.title === t("wallets.evmWallets");
|
|
4228
|
+
const connector = isEvmConnector ? connectors.find((c) => c.id === wallet.id) : null;
|
|
4239
4229
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4240
4230
|
Button,
|
|
4241
4231
|
{
|
|
4242
|
-
|
|
4243
|
-
|
|
4232
|
+
type: "button",
|
|
4233
|
+
onClick: () => {
|
|
4234
|
+
if (connector) {
|
|
4235
|
+
connect({ connector });
|
|
4236
|
+
onClose();
|
|
4237
|
+
} else {
|
|
4238
|
+
handleWalletSelect(wallet.id);
|
|
4239
|
+
}
|
|
4240
|
+
},
|
|
4241
|
+
disabled: isEvmConnector ? isPending : !wallet.enabled,
|
|
4244
4242
|
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",
|
|
4245
4243
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
4246
4244
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7.5 h-7.5 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: "size-7.5" }) }),
|
|
@@ -4256,39 +4254,6 @@ const WalletSelectModal = ({
|
|
|
4256
4254
|
] })
|
|
4257
4255
|
] }) });
|
|
4258
4256
|
};
|
|
4259
|
-
function Card({ className, ...props }) {
|
|
4260
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4261
|
-
"div",
|
|
4262
|
-
{
|
|
4263
|
-
"data-slot": "card",
|
|
4264
|
-
className: cn(
|
|
4265
|
-
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
|
4266
|
-
className
|
|
4267
|
-
),
|
|
4268
|
-
...props
|
|
4269
|
-
}
|
|
4270
|
-
);
|
|
4271
|
-
}
|
|
4272
|
-
function CardContent({ className, ...props }) {
|
|
4273
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4274
|
-
"div",
|
|
4275
|
-
{
|
|
4276
|
-
"data-slot": "card-content",
|
|
4277
|
-
className: cn("px-6", className),
|
|
4278
|
-
...props
|
|
4279
|
-
}
|
|
4280
|
-
);
|
|
4281
|
-
}
|
|
4282
|
-
function CardFooter({ className, ...props }) {
|
|
4283
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4284
|
-
"div",
|
|
4285
|
-
{
|
|
4286
|
-
"data-slot": "card-footer",
|
|
4287
|
-
className: cn("flex items-center px-6 [.border-t]:pt-6", className),
|
|
4288
|
-
...props
|
|
4289
|
-
}
|
|
4290
|
-
);
|
|
4291
|
-
}
|
|
4292
4257
|
const TransactionProgressVector = (props) => {
|
|
4293
4258
|
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "200", height: "200", viewBox: "0 0 200 200", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: [
|
|
4294
4259
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -6352,6 +6317,49 @@ class ChainStrategyRegistry {
|
|
|
6352
6317
|
await strategy.disconnect();
|
|
6353
6318
|
}
|
|
6354
6319
|
}
|
|
6320
|
+
const EVM_CONFIG = {
|
|
6321
|
+
usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
6322
|
+
gasEstimates: {
|
|
6323
|
+
approve: 65000n,
|
|
6324
|
+
bridge: 300000n
|
|
6325
|
+
},
|
|
6326
|
+
gasBuffer: 1.2,
|
|
6327
|
+
// 20% buffer
|
|
6328
|
+
timeout: 3e5,
|
|
6329
|
+
// 5 minutes (increased for slower networks)
|
|
6330
|
+
requiredConfirmations: 3
|
|
6331
|
+
// Wait for 3 confirmations for reorg protection
|
|
6332
|
+
};
|
|
6333
|
+
const TON_CONFIG = {
|
|
6334
|
+
apiUrl: "https://toncenter.com/api/v2",
|
|
6335
|
+
timeout: 36e4,
|
|
6336
|
+
// 6 minutes
|
|
6337
|
+
validUntil: 600
|
|
6338
|
+
// 10 minutes
|
|
6339
|
+
};
|
|
6340
|
+
const TRON_CONFIG = {
|
|
6341
|
+
timeout: 12e4,
|
|
6342
|
+
// 2 minutes (for 19 confirmations)
|
|
6343
|
+
feeLimit: 1e8,
|
|
6344
|
+
// 100 TRX in sun
|
|
6345
|
+
requiredConfirmations: 19,
|
|
6346
|
+
// TRON standard: 19 blocks for confirmation
|
|
6347
|
+
pollingInterval: 3e3
|
|
6348
|
+
// 3 seconds between checks
|
|
6349
|
+
};
|
|
6350
|
+
let tonClientInstance = null;
|
|
6351
|
+
function getTonClient(customClient, apiKey) {
|
|
6352
|
+
if (customClient) {
|
|
6353
|
+
return customClient;
|
|
6354
|
+
}
|
|
6355
|
+
if (!tonClientInstance) {
|
|
6356
|
+
tonClientInstance = new ton.TonClient({
|
|
6357
|
+
endpoint: `${TON_CONFIG.apiUrl}/jsonRPC`,
|
|
6358
|
+
apiKey
|
|
6359
|
+
});
|
|
6360
|
+
}
|
|
6361
|
+
return tonClientInstance;
|
|
6362
|
+
}
|
|
6355
6363
|
function isNativeAddress(addr) {
|
|
6356
6364
|
if (!addr) return false;
|
|
6357
6365
|
const a = addr.toLowerCase();
|
|
@@ -6377,44 +6385,72 @@ function formatUnitsFromBigIntStr(valueStr, decimals) {
|
|
|
6377
6385
|
const tail = s.slice(s.length - decimals).replace(/0+$/, "");
|
|
6378
6386
|
return Number(tail ? `${head}.${tail}` : head);
|
|
6379
6387
|
}
|
|
6380
|
-
|
|
6388
|
+
function isTonFriendlyAddress(address) {
|
|
6389
|
+
return !!address && /^[A-Za-z0-9_-]{48,}$/.test(address);
|
|
6390
|
+
}
|
|
6391
|
+
function normalizeTickerSymbol(symbol) {
|
|
6392
|
+
return symbol.toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
|
|
6393
|
+
}
|
|
6394
|
+
function parseTonAddress(address) {
|
|
6395
|
+
if (address.startsWith("0x")) {
|
|
6396
|
+
const hex = address.slice(2);
|
|
6397
|
+
return ton.Address.parseRaw(`0:${hex}`);
|
|
6398
|
+
}
|
|
6399
|
+
if (address.includes(":")) {
|
|
6400
|
+
return ton.Address.parseRaw(address);
|
|
6401
|
+
}
|
|
6402
|
+
return ton.Address.parse(address);
|
|
6403
|
+
}
|
|
6404
|
+
async function getEvmBalances(publicClient, address, tokens) {
|
|
6381
6405
|
const balances = {};
|
|
6382
6406
|
try {
|
|
6383
|
-
|
|
6407
|
+
console.log("start getEvmBalances");
|
|
6408
|
+
console.log("publicClient:", publicClient);
|
|
6409
|
+
console.log("isAddress:", viem.isAddress(address));
|
|
6410
|
+
console.log("tokens:", tokens);
|
|
6411
|
+
if (!address || !viem.isAddress(address)) {
|
|
6384
6412
|
console.warn(`Invalid EVM address provided: ${address}`);
|
|
6385
6413
|
return balances;
|
|
6386
6414
|
}
|
|
6387
|
-
if (
|
|
6388
|
-
throw new Error("No
|
|
6415
|
+
if (!publicClient) {
|
|
6416
|
+
throw new Error("No public client provided");
|
|
6389
6417
|
}
|
|
6390
|
-
const provider = new ethers.ethers.BrowserProvider(window.ethereum);
|
|
6391
6418
|
for (const token of tokens) {
|
|
6392
6419
|
try {
|
|
6393
6420
|
let balance = 0;
|
|
6394
6421
|
const isNative = isNativeAddress(token.address);
|
|
6395
6422
|
if (isNative) {
|
|
6396
|
-
const ethBalance = await
|
|
6397
|
-
|
|
6423
|
+
const ethBalance = await publicClient.getBalance({
|
|
6424
|
+
address
|
|
6425
|
+
});
|
|
6426
|
+
balance = parseFloat(viem.formatUnits(ethBalance, token.decimals));
|
|
6398
6427
|
} else {
|
|
6399
|
-
if (!
|
|
6428
|
+
if (!viem.isAddress(token.address)) {
|
|
6400
6429
|
continue;
|
|
6401
6430
|
}
|
|
6402
|
-
const
|
|
6403
|
-
|
|
6431
|
+
const bytecode = await publicClient.getBytecode({
|
|
6432
|
+
address: token.address
|
|
6433
|
+
});
|
|
6434
|
+
if (!bytecode || bytecode === "0x") {
|
|
6404
6435
|
continue;
|
|
6405
6436
|
}
|
|
6406
|
-
const contract = new ethers.ethers.Contract(
|
|
6407
|
-
token.address,
|
|
6408
|
-
[
|
|
6409
|
-
"function balanceOf(address owner) view returns (uint256)",
|
|
6410
|
-
"function decimals() view returns (uint8)"
|
|
6411
|
-
],
|
|
6412
|
-
provider
|
|
6413
|
-
);
|
|
6414
6437
|
try {
|
|
6415
|
-
const tokenBalance = await
|
|
6438
|
+
const tokenBalance = await publicClient.readContract({
|
|
6439
|
+
address: token.address,
|
|
6440
|
+
abi: [
|
|
6441
|
+
{
|
|
6442
|
+
name: "balanceOf",
|
|
6443
|
+
type: "function",
|
|
6444
|
+
stateMutability: "view",
|
|
6445
|
+
inputs: [{ name: "owner", type: "address" }],
|
|
6446
|
+
outputs: [{ name: "balance", type: "uint256" }]
|
|
6447
|
+
}
|
|
6448
|
+
],
|
|
6449
|
+
functionName: "balanceOf",
|
|
6450
|
+
args: [address]
|
|
6451
|
+
});
|
|
6416
6452
|
balance = parseFloat(
|
|
6417
|
-
|
|
6453
|
+
viem.formatUnits(tokenBalance, token.decimals)
|
|
6418
6454
|
);
|
|
6419
6455
|
} catch {
|
|
6420
6456
|
continue;
|
|
@@ -6437,6 +6473,68 @@ async function getEvmBalances(address, tokens) {
|
|
|
6437
6473
|
}
|
|
6438
6474
|
return balances;
|
|
6439
6475
|
}
|
|
6476
|
+
async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
|
|
6477
|
+
const balances = {};
|
|
6478
|
+
try {
|
|
6479
|
+
if (!isTonFriendlyAddress(address)) {
|
|
6480
|
+
console.warn(`Invalid TON address provided: ${address}`);
|
|
6481
|
+
return balances;
|
|
6482
|
+
}
|
|
6483
|
+
const client = getTonClient(customTonClient, tonApiKey);
|
|
6484
|
+
const accountAddress = ton.Address.parse(address);
|
|
6485
|
+
console.log(address);
|
|
6486
|
+
console.log(tokens);
|
|
6487
|
+
try {
|
|
6488
|
+
const balance = await client.getBalance(accountAddress);
|
|
6489
|
+
const tonBalance = Number(balance) / 1e9;
|
|
6490
|
+
console.log("tonBalance", tonBalance);
|
|
6491
|
+
if (tonBalance > 0) {
|
|
6492
|
+
balances.TON = { balance: tonBalance, address: "ton-native" };
|
|
6493
|
+
}
|
|
6494
|
+
} catch (error) {
|
|
6495
|
+
console.warn("Failed to get native TON balance:", error);
|
|
6496
|
+
}
|
|
6497
|
+
for (const token of tokens) {
|
|
6498
|
+
try {
|
|
6499
|
+
if (isNativeAddress(token.address) || token.symbol.toUpperCase() === "TON") {
|
|
6500
|
+
continue;
|
|
6501
|
+
}
|
|
6502
|
+
const jettonMasterAddress = parseTonAddress(token.address);
|
|
6503
|
+
const jettonWalletAddress = await client.runMethod(
|
|
6504
|
+
jettonMasterAddress,
|
|
6505
|
+
"get_wallet_address",
|
|
6506
|
+
[
|
|
6507
|
+
{
|
|
6508
|
+
type: "slice",
|
|
6509
|
+
cell: ton.beginCell().storeAddress(accountAddress).endCell()
|
|
6510
|
+
}
|
|
6511
|
+
]
|
|
6512
|
+
);
|
|
6513
|
+
const jettonWalletAddr = jettonWalletAddress.stack.readAddress();
|
|
6514
|
+
const jettonData = await client.runMethod(
|
|
6515
|
+
jettonWalletAddr,
|
|
6516
|
+
"get_wallet_data"
|
|
6517
|
+
);
|
|
6518
|
+
const jettonBalance = jettonData.stack.readBigNumber();
|
|
6519
|
+
const humanBalance = Number(jettonBalance) / Math.pow(10, token.decimals);
|
|
6520
|
+
if (humanBalance > 0) {
|
|
6521
|
+
const symbolUpper = token.symbol.toUpperCase();
|
|
6522
|
+
const symbolNorm = normalizeTickerSymbol(symbolUpper);
|
|
6523
|
+
const entry = { balance: humanBalance, address: token.address };
|
|
6524
|
+
balances[symbolUpper] = entry;
|
|
6525
|
+
if (symbolNorm !== symbolUpper) {
|
|
6526
|
+
balances[symbolNorm] = entry;
|
|
6527
|
+
}
|
|
6528
|
+
}
|
|
6529
|
+
} catch (error) {
|
|
6530
|
+
console.debug(`Failed to get balance for ${token.symbol}:`, error);
|
|
6531
|
+
}
|
|
6532
|
+
}
|
|
6533
|
+
} catch (error) {
|
|
6534
|
+
console.error("Failed to get TON balances:", error);
|
|
6535
|
+
}
|
|
6536
|
+
return balances;
|
|
6537
|
+
}
|
|
6440
6538
|
async function getTronBalances(tronWeb, address, tokens) {
|
|
6441
6539
|
const balances = {};
|
|
6442
6540
|
try {
|
|
@@ -6480,30 +6578,6 @@ async function getTronBalances(tronWeb, address, tokens) {
|
|
|
6480
6578
|
}
|
|
6481
6579
|
return balances;
|
|
6482
6580
|
}
|
|
6483
|
-
const EVM_CONFIG = {
|
|
6484
|
-
usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
6485
|
-
gasEstimates: {
|
|
6486
|
-
approve: 65000n,
|
|
6487
|
-
bridge: 300000n
|
|
6488
|
-
},
|
|
6489
|
-
gasBuffer: 1.2,
|
|
6490
|
-
// 20% buffer
|
|
6491
|
-
timeout: 12e4
|
|
6492
|
-
// 2 minutes
|
|
6493
|
-
};
|
|
6494
|
-
const TON_CONFIG = {
|
|
6495
|
-
apiUrl: "https://toncenter.com/api/v2",
|
|
6496
|
-
timeout: 36e4,
|
|
6497
|
-
// 6 minutes
|
|
6498
|
-
validUntil: 600
|
|
6499
|
-
// 10 minutes
|
|
6500
|
-
};
|
|
6501
|
-
const TRON_CONFIG = {
|
|
6502
|
-
timeout: 6e4,
|
|
6503
|
-
// 1 minute
|
|
6504
|
-
feeLimit: 1e8
|
|
6505
|
-
// 100 TRX in sun
|
|
6506
|
-
};
|
|
6507
6581
|
const ERC20_ABI = [
|
|
6508
6582
|
"function approve(address spender, uint256 amount) returns (bool)",
|
|
6509
6583
|
"function allowance(address owner, address spender) view returns (uint256)",
|
|
@@ -6514,7 +6588,9 @@ class EvmChainStrategy {
|
|
|
6514
6588
|
constructor(config) {
|
|
6515
6589
|
__publicField(this, "config");
|
|
6516
6590
|
__publicField(this, "provider");
|
|
6591
|
+
__publicField(this, "publicClient");
|
|
6517
6592
|
this.config = config;
|
|
6593
|
+
this.publicClient = config.publicClient;
|
|
6518
6594
|
if (config.walletClient) {
|
|
6519
6595
|
this.provider = new ethers.BrowserProvider(config.walletClient.transport);
|
|
6520
6596
|
}
|
|
@@ -6553,7 +6629,11 @@ class EvmChainStrategy {
|
|
|
6553
6629
|
return t("wallets.connectEvmWallet");
|
|
6554
6630
|
}
|
|
6555
6631
|
async getBalances(address, tokens) {
|
|
6556
|
-
|
|
6632
|
+
if (!this.publicClient) {
|
|
6633
|
+
console.warn("No publicClient available for balance query");
|
|
6634
|
+
return {};
|
|
6635
|
+
}
|
|
6636
|
+
return await getEvmBalances(this.publicClient, address, tokens);
|
|
6557
6637
|
}
|
|
6558
6638
|
isAddressValid(address) {
|
|
6559
6639
|
if (!address) return false;
|
|
@@ -6666,17 +6746,14 @@ class EvmChainStrategy {
|
|
|
6666
6746
|
if (!provider) {
|
|
6667
6747
|
throw new ProviderNotAvailableError("evm");
|
|
6668
6748
|
}
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
}
|
|
6678
|
-
await new Promise((r) => setTimeout(r, 2500));
|
|
6679
|
-
}
|
|
6749
|
+
console.log(
|
|
6750
|
+
`Waiting for ${EVM_CONFIG.requiredConfirmations} confirmations for tx: ${txHash}`
|
|
6751
|
+
);
|
|
6752
|
+
const receipt = await provider.waitForTransaction(
|
|
6753
|
+
txHash,
|
|
6754
|
+
EVM_CONFIG.requiredConfirmations,
|
|
6755
|
+
EVM_CONFIG.timeout
|
|
6756
|
+
);
|
|
6680
6757
|
if (!receipt) {
|
|
6681
6758
|
const error = new TransactionTimeoutError("evm", txHash);
|
|
6682
6759
|
return {
|
|
@@ -6691,11 +6768,35 @@ class EvmChainStrategy {
|
|
|
6691
6768
|
error: error.message
|
|
6692
6769
|
};
|
|
6693
6770
|
}
|
|
6694
|
-
console.log(
|
|
6771
|
+
console.log(
|
|
6772
|
+
`EVM transaction confirmed in block ${receipt.blockNumber} with ${EVM_CONFIG.requiredConfirmations} confirmations`
|
|
6773
|
+
);
|
|
6695
6774
|
return {
|
|
6696
6775
|
completed: true
|
|
6697
6776
|
};
|
|
6698
6777
|
} catch (error) {
|
|
6778
|
+
if (error && typeof error === "object" && "code" in error && error.code === "TRANSACTION_REPLACED") {
|
|
6779
|
+
console.log(
|
|
6780
|
+
`Transaction was replaced: ${"reason" in error ? String(error.reason) : "unknown"}`
|
|
6781
|
+
);
|
|
6782
|
+
if ("receipt" in error && error.receipt) {
|
|
6783
|
+
const replacementReceipt = error.receipt;
|
|
6784
|
+
if (replacementReceipt.status === 1) {
|
|
6785
|
+
console.log(
|
|
6786
|
+
`Replacement transaction succeeded in block ${replacementReceipt.blockNumber}`
|
|
6787
|
+
);
|
|
6788
|
+
return {
|
|
6789
|
+
completed: true
|
|
6790
|
+
};
|
|
6791
|
+
} else {
|
|
6792
|
+
const chainError2 = new TransactionRevertedError("evm", txHash);
|
|
6793
|
+
return {
|
|
6794
|
+
completed: false,
|
|
6795
|
+
error: chainError2.message
|
|
6796
|
+
};
|
|
6797
|
+
}
|
|
6798
|
+
}
|
|
6799
|
+
}
|
|
6699
6800
|
const chainError = toChainStrategyError(
|
|
6700
6801
|
error,
|
|
6701
6802
|
"evm",
|
|
@@ -6809,13 +6910,52 @@ class EvmChainStrategy {
|
|
|
6809
6910
|
return false;
|
|
6810
6911
|
}
|
|
6811
6912
|
}
|
|
6913
|
+
/**
|
|
6914
|
+
* Check if a block has reached finality status (optional, for critical transactions)
|
|
6915
|
+
* This is more stringent than confirmations and protects against long-range reorgs
|
|
6916
|
+
*
|
|
6917
|
+
* Usage: Call this method after waitForCompletion if you need additional security
|
|
6918
|
+
* for high-value transactions. The method checks if the block has been marked as
|
|
6919
|
+
* "finalized" by the Ethereum consensus layer (2/3 of validators).
|
|
6920
|
+
*
|
|
6921
|
+
* @param blockNumber - The block number to check for finality
|
|
6922
|
+
* @returns true if the block is finalized, false otherwise
|
|
6923
|
+
*/
|
|
6924
|
+
async checkFinality(blockNumber) {
|
|
6925
|
+
try {
|
|
6926
|
+
const provider = this.provider;
|
|
6927
|
+
if (!provider) {
|
|
6928
|
+
return false;
|
|
6929
|
+
}
|
|
6930
|
+
const finalizedBlock = await provider.getBlock("finalized");
|
|
6931
|
+
if (!finalizedBlock) {
|
|
6932
|
+
console.debug(
|
|
6933
|
+
"Finalized block not available (pre-merge or unsupported)"
|
|
6934
|
+
);
|
|
6935
|
+
return false;
|
|
6936
|
+
}
|
|
6937
|
+
const isFinalized = blockNumber <= finalizedBlock.number;
|
|
6938
|
+
if (isFinalized) {
|
|
6939
|
+
console.log(
|
|
6940
|
+
`Block ${blockNumber} has reached finality (finalized block: ${finalizedBlock.number})`
|
|
6941
|
+
);
|
|
6942
|
+
} else {
|
|
6943
|
+
console.debug(
|
|
6944
|
+
`Block ${blockNumber} not yet finalized (finalized block: ${finalizedBlock.number})`
|
|
6945
|
+
);
|
|
6946
|
+
}
|
|
6947
|
+
return isFinalized;
|
|
6948
|
+
} catch (error) {
|
|
6949
|
+
console.debug("Error checking finality:", error);
|
|
6950
|
+
return false;
|
|
6951
|
+
}
|
|
6952
|
+
}
|
|
6812
6953
|
}
|
|
6813
6954
|
class TonChainStrategy {
|
|
6814
6955
|
constructor(config) {
|
|
6815
6956
|
__publicField(this, "config");
|
|
6816
6957
|
this.config = config;
|
|
6817
6958
|
}
|
|
6818
|
-
// ========== Identity ==========
|
|
6819
6959
|
canHandle(chainKey) {
|
|
6820
6960
|
return chainKey.toLowerCase() === "ton";
|
|
6821
6961
|
}
|
|
@@ -6825,7 +6965,6 @@ class TonChainStrategy {
|
|
|
6825
6965
|
getName() {
|
|
6826
6966
|
return "TON Chain Strategy";
|
|
6827
6967
|
}
|
|
6828
|
-
// ========== Wallet Management ==========
|
|
6829
6968
|
async connect() {
|
|
6830
6969
|
await this.config.tonConnectUI?.openModal();
|
|
6831
6970
|
}
|
|
@@ -6850,17 +6989,26 @@ class TonChainStrategy {
|
|
|
6850
6989
|
getConnectLabel(t) {
|
|
6851
6990
|
return t("wallets.connectTonWallet");
|
|
6852
6991
|
}
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6992
|
+
async getBalances(address, tokens) {
|
|
6993
|
+
return await getTonBalances(
|
|
6994
|
+
address,
|
|
6995
|
+
tokens,
|
|
6996
|
+
this.config.tonClient,
|
|
6997
|
+
this.config.tonApiKey
|
|
6998
|
+
);
|
|
6856
6999
|
}
|
|
6857
7000
|
isAddressValid(address) {
|
|
6858
7001
|
if (!address) return false;
|
|
6859
7002
|
return true;
|
|
6860
7003
|
}
|
|
6861
|
-
// ========== Gas Estimation ==========
|
|
6862
7004
|
async estimateGasRequirement(params) {
|
|
6863
|
-
const {
|
|
7005
|
+
const {
|
|
7006
|
+
selectedToken,
|
|
7007
|
+
nativeTokenSymbol,
|
|
7008
|
+
amount,
|
|
7009
|
+
balances,
|
|
7010
|
+
reserveFallback
|
|
7011
|
+
} = params;
|
|
6864
7012
|
const nativeSym = nativeTokenSymbol.toUpperCase();
|
|
6865
7013
|
const isNativeSelected = nativeSym === (selectedToken?.symbol ?? "").toUpperCase();
|
|
6866
7014
|
const nativeBalance = Number(balances[nativeSym]?.balance ?? 0);
|
|
@@ -6882,7 +7030,6 @@ class TonChainStrategy {
|
|
|
6882
7030
|
isNativeSelected
|
|
6883
7031
|
};
|
|
6884
7032
|
}
|
|
6885
|
-
// ========== Transaction Execution ==========
|
|
6886
7033
|
validateSteps(steps) {
|
|
6887
7034
|
if (!steps || steps.length === 0) {
|
|
6888
7035
|
throw new InvalidStepsError("ton", "No transaction steps provided");
|
|
@@ -6935,19 +7082,17 @@ class TonChainStrategy {
|
|
|
6935
7082
|
const result = await this.config.tonConnectUI.sendTransaction(
|
|
6936
7083
|
transaction
|
|
6937
7084
|
);
|
|
6938
|
-
const hash = this.getTxHash(result.boc);
|
|
6939
7085
|
return {
|
|
6940
7086
|
chainKey: "ton",
|
|
6941
|
-
hash
|
|
7087
|
+
hash: result.boc
|
|
6942
7088
|
};
|
|
6943
7089
|
} catch (error) {
|
|
6944
7090
|
throw toChainStrategyError(error, "ton", "transaction");
|
|
6945
7091
|
}
|
|
6946
7092
|
}
|
|
6947
|
-
async waitForCompletion(txHash
|
|
7093
|
+
async waitForCompletion(txHash) {
|
|
6948
7094
|
try {
|
|
6949
7095
|
const confirmed = await this.checkTonTransaction(
|
|
6950
|
-
context.srcAddress,
|
|
6951
7096
|
txHash,
|
|
6952
7097
|
TON_CONFIG.timeout
|
|
6953
7098
|
);
|
|
@@ -6977,39 +7122,78 @@ class TonChainStrategy {
|
|
|
6977
7122
|
};
|
|
6978
7123
|
}
|
|
6979
7124
|
}
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
7125
|
+
getNormalizedExtMessageHash(message) {
|
|
7126
|
+
if (message.info.type !== "external-in") {
|
|
7127
|
+
throw new Error(`Expected external-in message, got ${message.info.type}`);
|
|
7128
|
+
}
|
|
7129
|
+
const normalizedInfo = {
|
|
7130
|
+
...message.info,
|
|
7131
|
+
src: void 0,
|
|
7132
|
+
importFee: 0n
|
|
7133
|
+
};
|
|
7134
|
+
const normalizedMessage = {
|
|
7135
|
+
...message,
|
|
7136
|
+
info: normalizedInfo,
|
|
7137
|
+
init: null
|
|
7138
|
+
};
|
|
7139
|
+
return core.beginCell().store(core.storeMessage(normalizedMessage, { forceRef: true })).endCell().hash();
|
|
6985
7140
|
}
|
|
6986
|
-
async checkTonTransaction(
|
|
7141
|
+
async checkTonTransaction(bocBase64, timeoutMs = 36e4) {
|
|
6987
7142
|
const deadline = Date.now() + timeoutMs;
|
|
6988
|
-
const
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
7143
|
+
const client = getTonClient(this.config.tonClient, this.config.tonApiKey);
|
|
7144
|
+
try {
|
|
7145
|
+
const inMessage = core.loadMessage(core.Cell.fromBase64(bocBase64).beginParse());
|
|
7146
|
+
if (inMessage.info.type !== "external-in") {
|
|
7147
|
+
console.debug(
|
|
7148
|
+
"Expected external-in message, got:",
|
|
7149
|
+
inMessage.info.type
|
|
6993
7150
|
);
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
const
|
|
7003
|
-
|
|
7004
|
-
|
|
7151
|
+
return false;
|
|
7152
|
+
}
|
|
7153
|
+
const accountAddress = inMessage.info.dest;
|
|
7154
|
+
const targetMessageHash = this.getNormalizedExtMessageHash(inMessage);
|
|
7155
|
+
let lt = void 0;
|
|
7156
|
+
let hash = void 0;
|
|
7157
|
+
while (Date.now() < deadline) {
|
|
7158
|
+
try {
|
|
7159
|
+
const transactions = await client.getTransactions(accountAddress, {
|
|
7160
|
+
lt,
|
|
7161
|
+
hash,
|
|
7162
|
+
limit: 10,
|
|
7163
|
+
archival: true
|
|
7164
|
+
});
|
|
7165
|
+
if (transactions.length === 0) {
|
|
7166
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
7167
|
+
lt = void 0;
|
|
7168
|
+
hash = void 0;
|
|
7169
|
+
continue;
|
|
7170
|
+
}
|
|
7171
|
+
for (const tx of transactions) {
|
|
7172
|
+
if (tx.inMessage?.info.type === "external-in") {
|
|
7173
|
+
const txInMessageHash = this.getNormalizedExtMessageHash(
|
|
7174
|
+
tx.inMessage
|
|
7175
|
+
);
|
|
7176
|
+
if (txInMessageHash.equals(targetMessageHash)) {
|
|
7177
|
+
console.debug("Transaction found by in-message hash");
|
|
7178
|
+
return true;
|
|
7179
|
+
}
|
|
7180
|
+
}
|
|
7005
7181
|
}
|
|
7182
|
+
const lastTx = transactions[transactions.length - 1];
|
|
7183
|
+
lt = lastTx.lt.toString();
|
|
7184
|
+
hash = lastTx.hash().toString("base64");
|
|
7185
|
+
} catch (error) {
|
|
7186
|
+
console.debug("Error fetching transactions:", error);
|
|
7187
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
7188
|
+
lt = void 0;
|
|
7189
|
+
hash = void 0;
|
|
7006
7190
|
}
|
|
7007
|
-
} catch (e) {
|
|
7008
|
-
console.debug("TonCenter polling error:", e);
|
|
7009
7191
|
}
|
|
7010
|
-
|
|
7192
|
+
return false;
|
|
7193
|
+
} catch (error) {
|
|
7194
|
+
console.debug("Error parsing BOC or checking transaction:", error);
|
|
7195
|
+
return false;
|
|
7011
7196
|
}
|
|
7012
|
-
return false;
|
|
7013
7197
|
}
|
|
7014
7198
|
}
|
|
7015
7199
|
class TronChainStrategy {
|
|
@@ -7070,7 +7254,13 @@ class TronChainStrategy {
|
|
|
7070
7254
|
}
|
|
7071
7255
|
// ========== Gas Estimation ==========
|
|
7072
7256
|
async estimateGasRequirement(params) {
|
|
7073
|
-
const {
|
|
7257
|
+
const {
|
|
7258
|
+
selectedToken,
|
|
7259
|
+
nativeTokenSymbol,
|
|
7260
|
+
amount,
|
|
7261
|
+
balances,
|
|
7262
|
+
reserveFallback
|
|
7263
|
+
} = params;
|
|
7074
7264
|
const nativeSym = nativeTokenSymbol.toUpperCase();
|
|
7075
7265
|
const isNativeSelected = nativeSym === (selectedToken?.symbol ?? "").toUpperCase();
|
|
7076
7266
|
const nativeBalance = Number(balances[nativeSym]?.balance ?? 0);
|
|
@@ -7092,7 +7282,6 @@ class TronChainStrategy {
|
|
|
7092
7282
|
isNativeSelected
|
|
7093
7283
|
};
|
|
7094
7284
|
}
|
|
7095
|
-
// ========== Transaction Execution ==========
|
|
7096
7285
|
validateSteps(steps) {
|
|
7097
7286
|
console.log("validateSteps");
|
|
7098
7287
|
if (!steps?.length) {
|
|
@@ -7127,7 +7316,10 @@ class TronChainStrategy {
|
|
|
7127
7316
|
if (String(step.chainKey).toLowerCase() !== "tron") continue;
|
|
7128
7317
|
const tx = step.transaction;
|
|
7129
7318
|
if (!tx) {
|
|
7130
|
-
throw new InvalidTransactionDataError(
|
|
7319
|
+
throw new InvalidTransactionDataError(
|
|
7320
|
+
"tron",
|
|
7321
|
+
"Missing transaction data"
|
|
7322
|
+
);
|
|
7131
7323
|
}
|
|
7132
7324
|
const hexData = typeof tx?.data === "string" ? tx.data : "";
|
|
7133
7325
|
const parsed = this.parseTronStep(step, tx, hexData);
|
|
@@ -7178,13 +7370,19 @@ class TronChainStrategy {
|
|
|
7178
7370
|
break;
|
|
7179
7371
|
}
|
|
7180
7372
|
default:
|
|
7181
|
-
throw new InvalidStepsError(
|
|
7373
|
+
throw new InvalidStepsError(
|
|
7374
|
+
"tron",
|
|
7375
|
+
"Unsupported TRON parsed tx kind"
|
|
7376
|
+
);
|
|
7182
7377
|
}
|
|
7183
7378
|
const { txid } = await this.signAndBroadcast(tronWeb, unsigned);
|
|
7184
7379
|
lastTxId = txid;
|
|
7185
7380
|
}
|
|
7186
7381
|
if (!lastTxId) {
|
|
7187
|
-
throw new TransactionFailedError(
|
|
7382
|
+
throw new TransactionFailedError(
|
|
7383
|
+
"tron",
|
|
7384
|
+
"No TRON transaction was executed"
|
|
7385
|
+
);
|
|
7188
7386
|
}
|
|
7189
7387
|
return { hash: lastTxId, chainKey: "tron" };
|
|
7190
7388
|
}
|
|
@@ -7194,47 +7392,84 @@ class TronChainStrategy {
|
|
|
7194
7392
|
if (!tronWeb) {
|
|
7195
7393
|
throw new ProviderNotAvailableError("tron");
|
|
7196
7394
|
}
|
|
7395
|
+
console.log(
|
|
7396
|
+
`Waiting for ${TRON_CONFIG.requiredConfirmations} confirmations for TRON tx: ${txHash}`
|
|
7397
|
+
);
|
|
7197
7398
|
const deadline = Date.now() + TRON_CONFIG.timeout;
|
|
7198
|
-
|
|
7399
|
+
let txBlockNumber = null;
|
|
7400
|
+
while (Date.now() < deadline && !txBlockNumber) {
|
|
7199
7401
|
try {
|
|
7200
7402
|
const info = await tronWeb.trx.getTransactionInfo(txHash);
|
|
7201
|
-
|
|
7202
|
-
if (info) {
|
|
7403
|
+
if (info && info.blockNumber) {
|
|
7203
7404
|
const result = info.receipt?.result;
|
|
7204
|
-
if (result
|
|
7205
|
-
|
|
7405
|
+
if (result !== "SUCCESS") {
|
|
7406
|
+
const msg = this.hexToAscii(info.resMessage) || null;
|
|
7407
|
+
let reason = msg;
|
|
7408
|
+
const cr = info.contractResult?.[0];
|
|
7409
|
+
if (cr && /^0x?08c379a0/i.test(cr)) {
|
|
7410
|
+
try {
|
|
7411
|
+
const clean = cr.replace(/^0x/, "");
|
|
7412
|
+
const len = parseInt(clean.slice(8 + 64, 8 + 64 + 64), 16);
|
|
7413
|
+
const strHex = clean.slice(
|
|
7414
|
+
8 + 64 + 64,
|
|
7415
|
+
8 + 64 + 64 + len * 2
|
|
7416
|
+
);
|
|
7417
|
+
const str = this.hexToAscii("0x" + strHex);
|
|
7418
|
+
if (str) reason = str;
|
|
7419
|
+
} catch (e) {
|
|
7420
|
+
console.debug("TRON revert string decode error", e);
|
|
7421
|
+
}
|
|
7422
|
+
}
|
|
7423
|
+
const error2 = new TransactionRevertedError(
|
|
7424
|
+
"tron",
|
|
7425
|
+
txHash,
|
|
7426
|
+
reason || "Unknown error"
|
|
7427
|
+
);
|
|
7206
7428
|
return {
|
|
7207
|
-
completed:
|
|
7429
|
+
completed: false,
|
|
7430
|
+
error: error2.message
|
|
7208
7431
|
};
|
|
7209
7432
|
}
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7433
|
+
txBlockNumber = info.blockNumber;
|
|
7434
|
+
console.log(`TRON transaction found in block ${txBlockNumber}`);
|
|
7435
|
+
}
|
|
7436
|
+
} catch (e) {
|
|
7437
|
+
console.debug("TRON getTransactionInfo error:", e);
|
|
7438
|
+
}
|
|
7439
|
+
if (!txBlockNumber) {
|
|
7440
|
+
await new Promise((r) => setTimeout(r, TRON_CONFIG.pollingInterval));
|
|
7441
|
+
}
|
|
7442
|
+
}
|
|
7443
|
+
if (!txBlockNumber) {
|
|
7444
|
+
const error2 = new TransactionTimeoutError("tron", txHash);
|
|
7445
|
+
return {
|
|
7446
|
+
completed: false,
|
|
7447
|
+
error: error2.message
|
|
7448
|
+
};
|
|
7449
|
+
}
|
|
7450
|
+
let confirmations = 0;
|
|
7451
|
+
while (Date.now() < deadline) {
|
|
7452
|
+
try {
|
|
7453
|
+
const currentBlock = await tronWeb.trx.getCurrentBlock();
|
|
7454
|
+
const currentBlockNumber = currentBlock?.block_header?.raw_data?.number;
|
|
7455
|
+
if (currentBlockNumber) {
|
|
7456
|
+
confirmations = currentBlockNumber - txBlockNumber;
|
|
7457
|
+
if (confirmations >= TRON_CONFIG.requiredConfirmations) {
|
|
7458
|
+
console.log(
|
|
7459
|
+
`TRON transaction confirmed in block ${txBlockNumber} with ${confirmations} confirmations`
|
|
7460
|
+
);
|
|
7461
|
+
return {
|
|
7462
|
+
completed: true
|
|
7463
|
+
};
|
|
7223
7464
|
}
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
txHash,
|
|
7227
|
-
reason || "Unknown error"
|
|
7465
|
+
console.log(
|
|
7466
|
+
`TRON transaction confirmations: ${confirmations}/${TRON_CONFIG.requiredConfirmations}`
|
|
7228
7467
|
);
|
|
7229
|
-
return {
|
|
7230
|
-
completed: false,
|
|
7231
|
-
error: error2.message
|
|
7232
|
-
};
|
|
7233
7468
|
}
|
|
7234
7469
|
} catch (e) {
|
|
7235
|
-
console.debug("TRON
|
|
7470
|
+
console.debug("TRON getCurrentBlock error:", e);
|
|
7236
7471
|
}
|
|
7237
|
-
await new Promise((r) => setTimeout(r,
|
|
7472
|
+
await new Promise((r) => setTimeout(r, TRON_CONFIG.pollingInterval));
|
|
7238
7473
|
}
|
|
7239
7474
|
const error = new TransactionTimeoutError("tron", txHash);
|
|
7240
7475
|
return {
|
|
@@ -7242,14 +7477,17 @@ class TronChainStrategy {
|
|
|
7242
7477
|
error: error.message
|
|
7243
7478
|
};
|
|
7244
7479
|
} catch (error) {
|
|
7245
|
-
const chainError = toChainStrategyError(
|
|
7480
|
+
const chainError = toChainStrategyError(
|
|
7481
|
+
error,
|
|
7482
|
+
"tron",
|
|
7483
|
+
"waitForCompletion"
|
|
7484
|
+
);
|
|
7246
7485
|
return {
|
|
7247
7486
|
completed: false,
|
|
7248
7487
|
error: chainError.message
|
|
7249
7488
|
};
|
|
7250
7489
|
}
|
|
7251
7490
|
}
|
|
7252
|
-
// ========== Private Helper Methods ==========
|
|
7253
7491
|
getTronWeb() {
|
|
7254
7492
|
return typeof window !== "undefined" ? window.tronWeb : void 0;
|
|
7255
7493
|
}
|
|
@@ -7302,7 +7540,10 @@ class TronChainStrategy {
|
|
|
7302
7540
|
amount: this.extractAmountFromTxData(tx.data)
|
|
7303
7541
|
};
|
|
7304
7542
|
}
|
|
7305
|
-
throw new InvalidTransactionDataError(
|
|
7543
|
+
throw new InvalidTransactionDataError(
|
|
7544
|
+
"tron",
|
|
7545
|
+
"Cannot parse approve transaction"
|
|
7546
|
+
);
|
|
7306
7547
|
}
|
|
7307
7548
|
if (step?.type === "transfer" || step?.type === "bridge") {
|
|
7308
7549
|
const s = step;
|
|
@@ -7332,7 +7573,10 @@ class TronChainStrategy {
|
|
|
7332
7573
|
feeLimit: raw2.feeLimit
|
|
7333
7574
|
};
|
|
7334
7575
|
}
|
|
7335
|
-
throw new InvalidTransactionDataError(
|
|
7576
|
+
throw new InvalidTransactionDataError(
|
|
7577
|
+
"tron",
|
|
7578
|
+
"Cannot parse transfer/bridge transaction"
|
|
7579
|
+
);
|
|
7336
7580
|
}
|
|
7337
7581
|
if (tx?.to && tx?.value && !tx?.data) {
|
|
7338
7582
|
const v = BigInt(tx.value.toString());
|
|
@@ -7352,19 +7596,28 @@ class TronChainStrategy {
|
|
|
7352
7596
|
feeLimit: raw.feeLimit
|
|
7353
7597
|
};
|
|
7354
7598
|
}
|
|
7355
|
-
throw new InvalidTransactionDataError(
|
|
7599
|
+
throw new InvalidTransactionDataError(
|
|
7600
|
+
"tron",
|
|
7601
|
+
`Unsupported TRON step type: ${step?.type ?? "unknown"}`
|
|
7602
|
+
);
|
|
7356
7603
|
}
|
|
7357
7604
|
extractSpenderFromTxData(data) {
|
|
7358
7605
|
const clean = data.replace(/^0x/, "");
|
|
7359
7606
|
if (clean.length < 74) {
|
|
7360
|
-
throw new InvalidTransactionDataError(
|
|
7607
|
+
throw new InvalidTransactionDataError(
|
|
7608
|
+
"tron",
|
|
7609
|
+
"Invalid transaction data length"
|
|
7610
|
+
);
|
|
7361
7611
|
}
|
|
7362
7612
|
return "41" + clean.slice(32, 72);
|
|
7363
7613
|
}
|
|
7364
7614
|
extractAmountFromTxData(data) {
|
|
7365
7615
|
const clean = data.replace(/^0x/, "");
|
|
7366
7616
|
if (clean.length < 138) {
|
|
7367
|
-
throw new InvalidTransactionDataError(
|
|
7617
|
+
throw new InvalidTransactionDataError(
|
|
7618
|
+
"tron",
|
|
7619
|
+
"Invalid transaction data length"
|
|
7620
|
+
);
|
|
7368
7621
|
}
|
|
7369
7622
|
const amountHex = clean.slice(72, 136);
|
|
7370
7623
|
return BigInt("0x" + amountHex).toString();
|
|
@@ -7372,7 +7625,10 @@ class TronChainStrategy {
|
|
|
7372
7625
|
extractRecipientFromTxData(data) {
|
|
7373
7626
|
const clean = data.replace(/^0x/, "");
|
|
7374
7627
|
if (clean.length < 74) {
|
|
7375
|
-
throw new InvalidTransactionDataError(
|
|
7628
|
+
throw new InvalidTransactionDataError(
|
|
7629
|
+
"tron",
|
|
7630
|
+
"Invalid transaction data length"
|
|
7631
|
+
);
|
|
7376
7632
|
}
|
|
7377
7633
|
return "41" + clean.slice(32, 72);
|
|
7378
7634
|
}
|
|
@@ -7447,7 +7703,6 @@ class TronChainStrategy {
|
|
|
7447
7703
|
return null;
|
|
7448
7704
|
}
|
|
7449
7705
|
}
|
|
7450
|
-
// ========== Transaction Builders ==========
|
|
7451
7706
|
async buildApprove(tronWeb, p) {
|
|
7452
7707
|
const res = await tronWeb.transactionBuilder.triggerSmartContract(
|
|
7453
7708
|
p.token,
|
|
@@ -7460,7 +7715,10 @@ class TronChainStrategy {
|
|
|
7460
7715
|
p.from
|
|
7461
7716
|
);
|
|
7462
7717
|
if (!res?.transaction) {
|
|
7463
|
-
throw new TransactionFailedError(
|
|
7718
|
+
throw new TransactionFailedError(
|
|
7719
|
+
"tron",
|
|
7720
|
+
"Failed to build approve transaction"
|
|
7721
|
+
);
|
|
7464
7722
|
}
|
|
7465
7723
|
return res.transaction;
|
|
7466
7724
|
}
|
|
@@ -7476,7 +7734,10 @@ class TronChainStrategy {
|
|
|
7476
7734
|
p.from
|
|
7477
7735
|
);
|
|
7478
7736
|
if (!res?.transaction) {
|
|
7479
|
-
throw new TransactionFailedError(
|
|
7737
|
+
throw new TransactionFailedError(
|
|
7738
|
+
"tron",
|
|
7739
|
+
"Failed to build transfer transaction"
|
|
7740
|
+
);
|
|
7480
7741
|
}
|
|
7481
7742
|
return res.transaction;
|
|
7482
7743
|
}
|
|
@@ -7496,12 +7757,13 @@ class TronChainStrategy {
|
|
|
7496
7757
|
p.from
|
|
7497
7758
|
);
|
|
7498
7759
|
if (!res?.transaction) {
|
|
7499
|
-
throw new TransactionFailedError(
|
|
7760
|
+
throw new TransactionFailedError(
|
|
7761
|
+
"tron",
|
|
7762
|
+
"Failed to build raw call transaction"
|
|
7763
|
+
);
|
|
7500
7764
|
}
|
|
7501
7765
|
return res.transaction;
|
|
7502
7766
|
}
|
|
7503
|
-
// ========== Transaction Sender ==========
|
|
7504
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7505
7767
|
async signAndBroadcast(tronWeb, unsignedTx) {
|
|
7506
7768
|
const signed = await tronWeb.trx.sign(unsignedTx);
|
|
7507
7769
|
const sent = await tronWeb.trx.sendRawTransaction(signed);
|
|
@@ -7513,33 +7775,77 @@ class TronChainStrategy {
|
|
|
7513
7775
|
}
|
|
7514
7776
|
return { txid: sent.txid };
|
|
7515
7777
|
}
|
|
7778
|
+
/**
|
|
7779
|
+
* Check if a transaction has been solidified (confirmed by solidityNode)
|
|
7780
|
+
* This is an additional check for critical transactions to ensure they are
|
|
7781
|
+
* truly confirmed and available through the solidityNode API.
|
|
7782
|
+
*
|
|
7783
|
+
* Usage: Call this method after waitForCompletion for high-value transactions
|
|
7784
|
+
* to get additional assurance that the transaction is solidified.
|
|
7785
|
+
*
|
|
7786
|
+
* @param txHash - Transaction hash to check
|
|
7787
|
+
* @returns true if the transaction is solidified, false otherwise
|
|
7788
|
+
*/
|
|
7789
|
+
async checkSolidified(txHash) {
|
|
7790
|
+
try {
|
|
7791
|
+
const tronWeb = this.getTronWeb();
|
|
7792
|
+
if (!tronWeb) {
|
|
7793
|
+
return false;
|
|
7794
|
+
}
|
|
7795
|
+
const info = await tronWeb.trx.getTransactionInfo(txHash);
|
|
7796
|
+
if (!info || !info.blockNumber) {
|
|
7797
|
+
console.debug(
|
|
7798
|
+
"Transaction not yet solidified (no blockNumber in info)"
|
|
7799
|
+
);
|
|
7800
|
+
return false;
|
|
7801
|
+
}
|
|
7802
|
+
const result = info.receipt?.result;
|
|
7803
|
+
if (result === "SUCCESS") {
|
|
7804
|
+
console.log(
|
|
7805
|
+
`Transaction ${txHash} is solidified in block ${info.blockNumber}`
|
|
7806
|
+
);
|
|
7807
|
+
return true;
|
|
7808
|
+
}
|
|
7809
|
+
console.debug(`Transaction solidified but result is: ${result}`);
|
|
7810
|
+
return false;
|
|
7811
|
+
} catch (error) {
|
|
7812
|
+
console.debug("Error checking solidified status:", error);
|
|
7813
|
+
return false;
|
|
7814
|
+
}
|
|
7815
|
+
}
|
|
7516
7816
|
}
|
|
7517
7817
|
function ChainStrategyProvider({
|
|
7518
7818
|
children,
|
|
7519
7819
|
evmWallet,
|
|
7520
7820
|
tonWallet,
|
|
7521
|
-
tronWallet
|
|
7821
|
+
tronWallet,
|
|
7822
|
+
tonClient,
|
|
7823
|
+
tonApiKey
|
|
7522
7824
|
}) {
|
|
7523
7825
|
const evmStrategy = require$$0.useMemo(
|
|
7524
7826
|
() => new EvmChainStrategy({
|
|
7525
7827
|
evmAddress: evmWallet.address,
|
|
7526
7828
|
evmIsConnected: evmWallet.isConnected,
|
|
7527
7829
|
evmDisconnect: evmWallet.disconnect,
|
|
7528
|
-
walletClient: evmWallet.walletClient
|
|
7830
|
+
walletClient: evmWallet.walletClient,
|
|
7831
|
+
publicClient: evmWallet.publicClient
|
|
7529
7832
|
}),
|
|
7530
7833
|
[
|
|
7531
7834
|
evmWallet.address,
|
|
7532
7835
|
evmWallet.isConnected,
|
|
7533
7836
|
evmWallet.disconnect,
|
|
7534
|
-
evmWallet.walletClient
|
|
7837
|
+
evmWallet.walletClient,
|
|
7838
|
+
evmWallet.publicClient
|
|
7535
7839
|
]
|
|
7536
7840
|
);
|
|
7537
7841
|
const tonStrategy = require$$0.useMemo(
|
|
7538
7842
|
() => new TonChainStrategy({
|
|
7539
7843
|
tonConnectUI: tonWallet.tonConnectUI,
|
|
7540
|
-
tonAddress: tonWallet.address
|
|
7844
|
+
tonAddress: tonWallet.address,
|
|
7845
|
+
tonClient,
|
|
7846
|
+
tonApiKey
|
|
7541
7847
|
}),
|
|
7542
|
-
[tonWallet.tonConnectUI, tonWallet.address]
|
|
7848
|
+
[tonWallet.tonConnectUI, tonWallet.address, tonClient, tonApiKey]
|
|
7543
7849
|
);
|
|
7544
7850
|
const tronStrategy = require$$0.useMemo(
|
|
7545
7851
|
() => new TronChainStrategy({
|
|
@@ -7575,6 +7881,7 @@ const EvaaBridgeWithProviders = (props) => {
|
|
|
7575
7881
|
const { address: evmAddress, isConnected: evmIsConnected } = wagmi.useAccount();
|
|
7576
7882
|
const { disconnect: evmDisconnect } = wagmi.useDisconnect();
|
|
7577
7883
|
const { data: walletClient } = wagmi.useWalletClient();
|
|
7884
|
+
const publicClient = wagmi.usePublicClient();
|
|
7578
7885
|
const {
|
|
7579
7886
|
address: tronAddress,
|
|
7580
7887
|
connected: tronConnected,
|
|
@@ -7599,7 +7906,8 @@ const EvaaBridgeWithProviders = (props) => {
|
|
|
7599
7906
|
address: evmAddress,
|
|
7600
7907
|
isConnected: evmIsConnected,
|
|
7601
7908
|
disconnect: evmDisconnect,
|
|
7602
|
-
walletClient
|
|
7909
|
+
walletClient,
|
|
7910
|
+
publicClient
|
|
7603
7911
|
},
|
|
7604
7912
|
tonWallet: {
|
|
7605
7913
|
tonConnectUI,
|
|
@@ -7612,6 +7920,8 @@ const EvaaBridgeWithProviders = (props) => {
|
|
|
7612
7920
|
connect: tronConnect,
|
|
7613
7921
|
disconnect: tronDisconnect
|
|
7614
7922
|
},
|
|
7923
|
+
tonClient: props.tonClient,
|
|
7924
|
+
tonApiKey: props.tonApiKey,
|
|
7615
7925
|
children: /* @__PURE__ */ jsxRuntime.jsx(EvaaBridgeContent, { ...props })
|
|
7616
7926
|
}
|
|
7617
7927
|
);
|
|
@@ -7716,16 +8026,16 @@ const EvaaBridgeContent = ({
|
|
|
7716
8026
|
}, [chains, assetMatrix, allowedFromChains]);
|
|
7717
8027
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7718
8028
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7719
|
-
|
|
8029
|
+
Card,
|
|
7720
8030
|
{
|
|
7721
8031
|
className: cn(
|
|
7722
|
-
"
|
|
8032
|
+
"max-w-md w-full mx-auto flex flex-col relative",
|
|
7723
8033
|
className
|
|
7724
8034
|
),
|
|
7725
8035
|
ref: modalContainerRef,
|
|
7726
8036
|
children: [
|
|
7727
8037
|
/* @__PURE__ */ jsxRuntime.jsx(FormHeader, { modalContainer: modalContainerRef.current }),
|
|
7728
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8038
|
+
/* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "space-y-[1px]", children: [
|
|
7729
8039
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7730
8040
|
SwapSection,
|
|
7731
8041
|
{
|
|
@@ -7763,10 +8073,10 @@ const EvaaBridgeContent = ({
|
|
|
7763
8073
|
enabled: sendToAnother,
|
|
7764
8074
|
onToggle: () => setSendToAnother((v) => !v)
|
|
7765
8075
|
}
|
|
7766
|
-
)
|
|
8076
|
+
),
|
|
8077
|
+
/* @__PURE__ */ jsxRuntime.jsx(SubmitButton, {})
|
|
7767
8078
|
] }),
|
|
7768
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7769
|
-
/* @__PURE__ */ jsxRuntime.jsx(ReceiveRow, {})
|
|
8079
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(ReceiveRow, {}) })
|
|
7770
8080
|
]
|
|
7771
8081
|
}
|
|
7772
8082
|
),
|
|
@@ -7854,8 +8164,8 @@ exports.getQuoteAmounts = getQuoteAmounts;
|
|
|
7854
8164
|
exports.getQuoteDetails = getQuoteDetails;
|
|
7855
8165
|
exports.getQuoteFees = getQuoteFees;
|
|
7856
8166
|
exports.getQuotesByPriority = getQuotesByPriority;
|
|
7857
|
-
exports.getSwapBalances = getSwapBalances;
|
|
7858
8167
|
exports.getTokens = getTokens;
|
|
8168
|
+
exports.getTonBalances = getTonBalances;
|
|
7859
8169
|
exports.getTronBalances = getTronBalances;
|
|
7860
8170
|
exports.isAddressValidForChain = isAddressValidForChain;
|
|
7861
8171
|
exports.isEvmAddress = isEvmAddress;
|
|
@@ -7864,7 +8174,7 @@ exports.isTronAddress = isTronAddress;
|
|
|
7864
8174
|
exports.isZeroAddr = isZeroAddr;
|
|
7865
8175
|
exports.listAssetsForSelect = listAssetsForSelect;
|
|
7866
8176
|
exports.lookupTokenMeta = lookupTokenMeta;
|
|
7867
|
-
exports.normalizeTickerSymbol = normalizeTickerSymbol;
|
|
8177
|
+
exports.normalizeTickerSymbol = normalizeTickerSymbol$1;
|
|
7868
8178
|
exports.pollUntilDelivered = pollUntilDelivered;
|
|
7869
8179
|
exports.resolveTokenOnChain = resolveTokenOnChain;
|
|
7870
8180
|
exports.resolveTokenOnChainFromMatrix = resolveTokenOnChainFromMatrix$2;
|