@elizaos/plugin-steward-app 2.0.3-beta.6 → 2.0.3-beta.7
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/ApprovalQueue.d.ts +18 -0
- package/dist/ApprovalQueue.d.ts.map +1 -0
- package/dist/ApprovalQueue.js +420 -0
- package/dist/ApprovalQueue.js.map +1 -0
- package/dist/StewardLogo.d.ts +11 -0
- package/dist/StewardLogo.d.ts.map +1 -0
- package/dist/StewardLogo.js +36 -0
- package/dist/StewardLogo.js.map +1 -0
- package/dist/StewardView.d.ts +13 -0
- package/dist/StewardView.d.ts.map +1 -0
- package/dist/StewardView.helpers.d.ts +15 -0
- package/dist/StewardView.helpers.d.ts.map +1 -0
- package/dist/StewardView.helpers.js +45 -0
- package/dist/StewardView.helpers.js.map +1 -0
- package/dist/StewardView.interact.d.ts +2 -0
- package/dist/StewardView.interact.d.ts.map +1 -0
- package/dist/StewardView.interact.js +54 -0
- package/dist/StewardView.interact.js.map +1 -0
- package/dist/StewardView.js +249 -0
- package/dist/StewardView.js.map +1 -0
- package/dist/TransactionHistory.d.ts +22 -0
- package/dist/TransactionHistory.d.ts.map +1 -0
- package/dist/TransactionHistory.js +361 -0
- package/dist/TransactionHistory.js.map +1 -0
- package/dist/__fixtures__/steward-sdk-fixtures.d.ts +10 -0
- package/dist/__fixtures__/steward-sdk-fixtures.d.ts.map +1 -0
- package/dist/__fixtures__/steward-sdk-fixtures.js +60 -0
- package/dist/__fixtures__/steward-sdk-fixtures.js.map +1 -0
- package/dist/actions/wallet-action-shared.d.ts +15 -0
- package/dist/actions/wallet-action-shared.d.ts.map +1 -0
- package/dist/actions/wallet-action-shared.js +16 -0
- package/dist/actions/wallet-action-shared.js.map +1 -0
- package/dist/api/binance-skill-helpers.d.ts +21 -0
- package/dist/api/binance-skill-helpers.d.ts.map +1 -0
- package/dist/api/binance-skill-helpers.js +790 -0
- package/dist/api/binance-skill-helpers.js.map +1 -0
- package/dist/api/bsc-trade.d.ts +36 -0
- package/dist/api/bsc-trade.d.ts.map +1 -0
- package/dist/api/bsc-trade.js +796 -0
- package/dist/api/bsc-trade.js.map +1 -0
- package/dist/api/trade-safety.d.ts +35 -0
- package/dist/api/trade-safety.d.ts.map +1 -0
- package/dist/api/trade-safety.js +56 -0
- package/dist/api/trade-safety.js.map +1 -0
- package/dist/api/tx-service.d.ts +53 -0
- package/dist/api/tx-service.d.ts.map +1 -0
- package/dist/api/tx-service.js +206 -0
- package/dist/api/tx-service.js.map +1 -0
- package/dist/api/wallet-bsc-routes.d.ts +63 -0
- package/dist/api/wallet-bsc-routes.d.ts.map +1 -0
- package/dist/api/wallet-bsc-routes.js +337 -0
- package/dist/api/wallet-bsc-routes.js.map +1 -0
- package/dist/api/wallet-capability.d.ts +2 -0
- package/dist/api/wallet-capability.d.ts.map +1 -0
- package/dist/api/wallet-capability.js +15 -0
- package/dist/api/wallet-capability.js.map +1 -0
- package/dist/api/wallet-dex-prices.d.ts +43 -0
- package/dist/api/wallet-dex-prices.d.ts.map +1 -0
- package/dist/api/wallet-dex-prices.js +132 -0
- package/dist/api/wallet-dex-prices.js.map +1 -0
- package/dist/api/wallet-evm-balance.d.ts +72 -0
- package/dist/api/wallet-evm-balance.d.ts.map +1 -0
- package/dist/api/wallet-evm-balance.js +697 -0
- package/dist/api/wallet-evm-balance.js.map +1 -0
- package/dist/api/wallet-routes.d.ts +27 -0
- package/dist/api/wallet-routes.d.ts.map +1 -0
- package/dist/api/wallet-routes.js +556 -0
- package/dist/api/wallet-routes.js.map +1 -0
- package/dist/api/wallet-rpc.d.ts +73 -0
- package/dist/api/wallet-rpc.d.ts.map +1 -0
- package/dist/api/wallet-rpc.js +460 -0
- package/dist/api/wallet-rpc.js.map +1 -0
- package/dist/api/wallet-trade-routes.d.ts +104 -0
- package/dist/api/wallet-trade-routes.d.ts.map +1 -0
- package/dist/api/wallet-trade-routes.js +353 -0
- package/dist/api/wallet-trade-routes.js.map +1 -0
- package/dist/api/wallet-trading-profile.d.ts +31 -0
- package/dist/api/wallet-trading-profile.d.ts.map +1 -0
- package/dist/api/wallet-trading-profile.js +500 -0
- package/dist/api/wallet-trading-profile.js.map +1 -0
- package/dist/api/wallet.d.ts +60 -0
- package/dist/api/wallet.d.ts.map +1 -0
- package/dist/api/wallet.js +617 -0
- package/dist/api/wallet.js.map +1 -0
- package/dist/chain-utils.d.ts +10 -0
- package/dist/chain-utils.d.ts.map +1 -0
- package/dist/chain-utils.js +81 -0
- package/dist/chain-utils.js.map +1 -0
- package/dist/components/StewardSpatialView.d.ts +74 -0
- package/dist/components/StewardSpatialView.d.ts.map +1 -0
- package/dist/components/StewardSpatialView.js +309 -0
- package/dist/components/StewardSpatialView.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +21 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +319 -0
- package/dist/plugin.js.map +1 -0
- package/dist/providers/steward-balance.d.ts +12 -0
- package/dist/providers/steward-balance.d.ts.map +1 -0
- package/dist/providers/steward-balance.js +85 -0
- package/dist/providers/steward-balance.js.map +1 -0
- package/dist/providers/steward-receive-address.d.ts +12 -0
- package/dist/providers/steward-receive-address.d.ts.map +1 -0
- package/dist/providers/steward-receive-address.js +47 -0
- package/dist/providers/steward-receive-address.js.map +1 -0
- package/dist/register-routes.d.ts +2 -0
- package/dist/register-routes.d.ts.map +1 -0
- package/dist/register-routes.js +6 -0
- package/dist/register-routes.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +34 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/routes/steward-bridge.d.ts +202 -0
- package/dist/routes/steward-bridge.d.ts.map +1 -0
- package/dist/routes/steward-bridge.js +776 -0
- package/dist/routes/steward-bridge.js.map +1 -0
- package/dist/routes/steward-compat-routes.d.ts +21 -0
- package/dist/routes/steward-compat-routes.d.ts.map +1 -0
- package/dist/routes/steward-compat-routes.js +350 -0
- package/dist/routes/steward-compat-routes.js.map +1 -0
- package/dist/routes/wallet-browser-compat-routes.d.ts +6 -0
- package/dist/routes/wallet-browser-compat-routes.d.ts.map +1 -0
- package/dist/routes/wallet-browser-compat-routes.js +402 -0
- package/dist/routes/wallet-browser-compat-routes.js.map +1 -0
- package/dist/routes/wallet-bsc-core-routes.d.ts +15 -0
- package/dist/routes/wallet-bsc-core-routes.d.ts.map +1 -0
- package/dist/routes/wallet-bsc-core-routes.js +59 -0
- package/dist/routes/wallet-bsc-core-routes.js.map +1 -0
- package/dist/routes/wallet-compat-routes.d.ts +13 -0
- package/dist/routes/wallet-compat-routes.d.ts.map +1 -0
- package/dist/routes/wallet-compat-routes.js +206 -0
- package/dist/routes/wallet-compat-routes.js.map +1 -0
- package/dist/routes/wallet-core-routes.d.ts +16 -0
- package/dist/routes/wallet-core-routes.d.ts.map +1 -0
- package/dist/routes/wallet-core-routes.js +48 -0
- package/dist/routes/wallet-core-routes.js.map +1 -0
- package/dist/routes/wallet-trade-compat-routes.d.ts +11 -0
- package/dist/routes/wallet-trade-compat-routes.d.ts.map +1 -0
- package/dist/routes/wallet-trade-compat-routes.js +570 -0
- package/dist/routes/wallet-trade-compat-routes.js.map +1 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.d.ts +7 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.d.ts.map +1 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.js +43 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.js.map +1 -0
- package/dist/security/wallet-os-store-actions.d.ts +14 -0
- package/dist/security/wallet-os-store-actions.d.ts.map +1 -0
- package/dist/security/wallet-os-store-actions.js +63 -0
- package/dist/security/wallet-os-store-actions.js.map +1 -0
- package/dist/services/steward-credentials.d.ts +2 -0
- package/dist/services/steward-credentials.d.ts.map +1 -0
- package/dist/services/steward-credentials.js +2 -0
- package/dist/services/steward-credentials.js.map +1 -0
- package/dist/services/steward-evm-account.d.ts +75 -0
- package/dist/services/steward-evm-account.d.ts.map +1 -0
- package/dist/services/steward-evm-account.js +279 -0
- package/dist/services/steward-evm-account.js.map +1 -0
- package/dist/services/steward-evm-bridge.d.ts +36 -0
- package/dist/services/steward-evm-bridge.d.ts.map +1 -0
- package/dist/services/steward-evm-bridge.js +78 -0
- package/dist/services/steward-evm-bridge.js.map +1 -0
- package/dist/services/steward-sidecar/health-check.d.ts +2 -0
- package/dist/services/steward-sidecar/health-check.d.ts.map +1 -0
- package/dist/services/steward-sidecar/health-check.js +2 -0
- package/dist/services/steward-sidecar/health-check.js.map +1 -0
- package/dist/services/steward-sidecar/helpers.d.ts +2 -0
- package/dist/services/steward-sidecar/helpers.d.ts.map +1 -0
- package/dist/services/steward-sidecar/helpers.js +2 -0
- package/dist/services/steward-sidecar/helpers.js.map +1 -0
- package/dist/services/steward-sidecar/process-management.d.ts +2 -0
- package/dist/services/steward-sidecar/process-management.d.ts.map +1 -0
- package/dist/services/steward-sidecar/process-management.js +2 -0
- package/dist/services/steward-sidecar/process-management.js.map +1 -0
- package/dist/services/steward-sidecar/types.d.ts +2 -0
- package/dist/services/steward-sidecar/types.d.ts.map +1 -0
- package/dist/services/steward-sidecar/types.js +2 -0
- package/dist/services/steward-sidecar/types.js.map +1 -0
- package/dist/services/steward-sidecar/wallet-setup.d.ts +2 -0
- package/dist/services/steward-sidecar/wallet-setup.d.ts.map +1 -0
- package/dist/services/steward-sidecar/wallet-setup.js +2 -0
- package/dist/services/steward-sidecar/wallet-setup.js.map +1 -0
- package/dist/services/steward-sidecar.d.ts +2 -0
- package/dist/services/steward-sidecar.d.ts.map +1 -0
- package/dist/services/steward-sidecar.js +2 -0
- package/dist/services/steward-sidecar.js.map +1 -0
- package/dist/services/steward-wallet.d.ts +25 -0
- package/dist/services/steward-wallet.d.ts.map +1 -0
- package/dist/services/steward-wallet.js +333 -0
- package/dist/services/steward-wallet.js.map +1 -0
- package/dist/steward-ui-state.d.ts +14 -0
- package/dist/steward-ui-state.d.ts.map +1 -0
- package/dist/steward-ui-state.js +46 -0
- package/dist/steward-ui-state.js.map +1 -0
- package/dist/steward-view-bundle.d.ts +3 -0
- package/dist/steward-view-bundle.d.ts.map +1 -0
- package/dist/steward-view-bundle.js +7 -0
- package/dist/steward-view-bundle.js.map +1 -0
- package/dist/types/bsc-trade.d.ts +180 -0
- package/dist/types/bsc-trade.d.ts.map +1 -0
- package/dist/types/bsc-trade.js +1 -0
- package/dist/types/bsc-trade.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/steward.d.ts +83 -0
- package/dist/types/steward.d.ts.map +1 -0
- package/dist/types/steward.js +1 -0
- package/dist/types/steward.js.map +1 -0
- package/dist/ui.d.ts +7 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +7 -0
- package/dist/ui.js.map +1 -0
- package/dist/views/bundle.js +601 -0
- package/dist/views/bundle.js.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,697 @@
|
|
|
1
|
+
import { logger } from "@elizaos/core";
|
|
2
|
+
import {
|
|
3
|
+
computeValueUsd,
|
|
4
|
+
fetchDexPrices,
|
|
5
|
+
WRAPPED_NATIVE
|
|
6
|
+
} from "./wallet-dex-prices.js";
|
|
7
|
+
import {
|
|
8
|
+
resolveAvalancheRpcUrls,
|
|
9
|
+
resolveBaseRpcUrls,
|
|
10
|
+
resolveBscRpcUrls,
|
|
11
|
+
resolveEthereumRpcUrls
|
|
12
|
+
} from "./wallet-rpc.js";
|
|
13
|
+
const FETCH_TIMEOUT_MS = 15e3;
|
|
14
|
+
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
15
|
+
const DEFAULT_EVM_CHAINS = [
|
|
16
|
+
{
|
|
17
|
+
name: "Ethereum",
|
|
18
|
+
subdomain: "eth-mainnet",
|
|
19
|
+
chainId: 1,
|
|
20
|
+
nativeSymbol: "ETH",
|
|
21
|
+
provider: "alchemy"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "Base",
|
|
25
|
+
subdomain: "base-mainnet",
|
|
26
|
+
chainId: 8453,
|
|
27
|
+
nativeSymbol: "ETH",
|
|
28
|
+
provider: "alchemy"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: "Arbitrum",
|
|
32
|
+
subdomain: "arb-mainnet",
|
|
33
|
+
chainId: 42161,
|
|
34
|
+
nativeSymbol: "ETH",
|
|
35
|
+
provider: "alchemy"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "Optimism",
|
|
39
|
+
subdomain: "opt-mainnet",
|
|
40
|
+
chainId: 10,
|
|
41
|
+
nativeSymbol: "ETH",
|
|
42
|
+
provider: "alchemy"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "Polygon",
|
|
46
|
+
subdomain: "polygon-mainnet",
|
|
47
|
+
chainId: 137,
|
|
48
|
+
nativeSymbol: "POL",
|
|
49
|
+
provider: "alchemy"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "BSC",
|
|
53
|
+
subdomain: "bnb-mainnet",
|
|
54
|
+
chainId: 56,
|
|
55
|
+
nativeSymbol: "BNB",
|
|
56
|
+
provider: "alchemy"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "Avalanche",
|
|
60
|
+
subdomain: "avax-mainnet",
|
|
61
|
+
chainId: 43114,
|
|
62
|
+
nativeSymbol: "AVAX",
|
|
63
|
+
provider: "alchemy"
|
|
64
|
+
}
|
|
65
|
+
];
|
|
66
|
+
async function jsonOrThrow(res) {
|
|
67
|
+
const text = await res.text();
|
|
68
|
+
if (!res.ok) throw new Error(text.slice(0, 200) || `HTTP ${res.status}`);
|
|
69
|
+
try {
|
|
70
|
+
return JSON.parse(text);
|
|
71
|
+
} catch {
|
|
72
|
+
throw new Error(text.slice(0, 200) || "Invalid JSON");
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function normalizeApiKey(value) {
|
|
76
|
+
if (typeof value !== "string") return null;
|
|
77
|
+
const trimmed = value.trim();
|
|
78
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
79
|
+
}
|
|
80
|
+
function normalizeStringArray(values) {
|
|
81
|
+
return [
|
|
82
|
+
...new Set(
|
|
83
|
+
(values ?? []).map((value) => normalizeApiKey(value)).filter((value) => Boolean(value))
|
|
84
|
+
)
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
function resolveEvmProviderKeys(alchemyOrKeys, maybeAnkrKey) {
|
|
88
|
+
if (typeof alchemyOrKeys === "string" || alchemyOrKeys == null) {
|
|
89
|
+
const alchemyKey = typeof alchemyOrKeys === "string" ? alchemyOrKeys : null;
|
|
90
|
+
return {
|
|
91
|
+
alchemyKey: normalizeApiKey(alchemyKey),
|
|
92
|
+
ankrKey: normalizeApiKey(maybeAnkrKey),
|
|
93
|
+
cloudManagedAccess: false,
|
|
94
|
+
bscRpcUrls: resolveBscRpcUrls({ cloudManagedAccess: false }),
|
|
95
|
+
ethereumRpcUrls: resolveEthereumRpcUrls({ cloudManagedAccess: false }),
|
|
96
|
+
baseRpcUrls: resolveBaseRpcUrls({ cloudManagedAccess: false }),
|
|
97
|
+
avaxRpcUrls: resolveAvalancheRpcUrls({ cloudManagedAccess: false }),
|
|
98
|
+
nodeRealBscRpcUrl: normalizeApiKey(
|
|
99
|
+
process.env.NODEREAL_BSC_RPC_URL ?? null
|
|
100
|
+
),
|
|
101
|
+
quickNodeBscRpcUrl: normalizeApiKey(
|
|
102
|
+
process.env.QUICKNODE_BSC_RPC_URL ?? null
|
|
103
|
+
),
|
|
104
|
+
bscRpcUrl: normalizeApiKey(process.env.BSC_RPC_URL ?? null),
|
|
105
|
+
ethereumRpcUrl: normalizeApiKey(process.env.ETHEREUM_RPC_URL ?? null),
|
|
106
|
+
baseRpcUrl: normalizeApiKey(process.env.BASE_RPC_URL ?? null),
|
|
107
|
+
avaxRpcUrl: normalizeApiKey(process.env.AVALANCHE_RPC_URL ?? null)
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const cloudManagedAccess = Boolean(alchemyOrKeys.cloudManagedAccess);
|
|
111
|
+
return {
|
|
112
|
+
alchemyKey: normalizeApiKey(alchemyOrKeys.alchemyKey),
|
|
113
|
+
ankrKey: normalizeApiKey(alchemyOrKeys.ankrKey ?? maybeAnkrKey),
|
|
114
|
+
cloudManagedAccess,
|
|
115
|
+
bscRpcUrls: normalizeStringArray([
|
|
116
|
+
...alchemyOrKeys.bscRpcUrls ?? [],
|
|
117
|
+
alchemyOrKeys.nodeRealBscRpcUrl ?? process.env.NODEREAL_BSC_RPC_URL,
|
|
118
|
+
alchemyOrKeys.quickNodeBscRpcUrl ?? process.env.QUICKNODE_BSC_RPC_URL,
|
|
119
|
+
alchemyOrKeys.bscRpcUrl ?? process.env.BSC_RPC_URL,
|
|
120
|
+
...resolveBscRpcUrls({ cloudManagedAccess })
|
|
121
|
+
]),
|
|
122
|
+
ethereumRpcUrls: normalizeStringArray([
|
|
123
|
+
...alchemyOrKeys.ethereumRpcUrls ?? [],
|
|
124
|
+
alchemyOrKeys.ethereumRpcUrl ?? process.env.ETHEREUM_RPC_URL,
|
|
125
|
+
...resolveEthereumRpcUrls({ cloudManagedAccess })
|
|
126
|
+
]),
|
|
127
|
+
baseRpcUrls: normalizeStringArray([
|
|
128
|
+
...alchemyOrKeys.baseRpcUrls ?? [],
|
|
129
|
+
alchemyOrKeys.baseRpcUrl ?? process.env.BASE_RPC_URL,
|
|
130
|
+
...resolveBaseRpcUrls({ cloudManagedAccess })
|
|
131
|
+
]),
|
|
132
|
+
avaxRpcUrls: normalizeStringArray([
|
|
133
|
+
...alchemyOrKeys.avaxRpcUrls ?? [],
|
|
134
|
+
alchemyOrKeys.avaxRpcUrl ?? process.env.AVALANCHE_RPC_URL,
|
|
135
|
+
...resolveAvalancheRpcUrls({ cloudManagedAccess })
|
|
136
|
+
]),
|
|
137
|
+
nodeRealBscRpcUrl: normalizeApiKey(
|
|
138
|
+
alchemyOrKeys.nodeRealBscRpcUrl ?? process.env.NODEREAL_BSC_RPC_URL
|
|
139
|
+
),
|
|
140
|
+
quickNodeBscRpcUrl: normalizeApiKey(
|
|
141
|
+
alchemyOrKeys.quickNodeBscRpcUrl ?? process.env.QUICKNODE_BSC_RPC_URL
|
|
142
|
+
),
|
|
143
|
+
bscRpcUrl: normalizeApiKey(
|
|
144
|
+
alchemyOrKeys.bscRpcUrl ?? process.env.BSC_RPC_URL
|
|
145
|
+
),
|
|
146
|
+
ethereumRpcUrl: normalizeApiKey(
|
|
147
|
+
alchemyOrKeys.ethereumRpcUrl ?? process.env.ETHEREUM_RPC_URL
|
|
148
|
+
),
|
|
149
|
+
baseRpcUrl: normalizeApiKey(
|
|
150
|
+
alchemyOrKeys.baseRpcUrl ?? process.env.BASE_RPC_URL
|
|
151
|
+
),
|
|
152
|
+
avaxRpcUrl: normalizeApiKey(
|
|
153
|
+
alchemyOrKeys.avaxRpcUrl ?? process.env.AVALANCHE_RPC_URL
|
|
154
|
+
)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function isBscChain(chain) {
|
|
158
|
+
return chain.chainId === 56 || (chain.ankrChain ?? "").toLowerCase() === "bsc";
|
|
159
|
+
}
|
|
160
|
+
function describeRpcEndpoint(url) {
|
|
161
|
+
try {
|
|
162
|
+
return new URL(url).host;
|
|
163
|
+
} catch {
|
|
164
|
+
return "rpc";
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function makeEvmChainFailure(chain, message) {
|
|
168
|
+
return {
|
|
169
|
+
chain: chain.name,
|
|
170
|
+
chainId: chain.chainId,
|
|
171
|
+
nativeBalance: "0",
|
|
172
|
+
nativeSymbol: chain.nativeSymbol,
|
|
173
|
+
nativeValueUsd: "0",
|
|
174
|
+
tokens: [],
|
|
175
|
+
error: message
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function rpcJsonRequest(body) {
|
|
179
|
+
return {
|
|
180
|
+
method: "POST",
|
|
181
|
+
headers: { "Content-Type": "application/json" },
|
|
182
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
183
|
+
body
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function asString(value) {
|
|
187
|
+
if (typeof value === "string") return value.trim();
|
|
188
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
189
|
+
return "";
|
|
190
|
+
}
|
|
191
|
+
function parseTokenDecimals(value, fallback = 18) {
|
|
192
|
+
const num = typeof value === "number" ? value : typeof value === "string" ? Number.parseInt(value, 10) : Number.NaN;
|
|
193
|
+
if (!Number.isFinite(num) || num < 0) return fallback;
|
|
194
|
+
return Math.trunc(num);
|
|
195
|
+
}
|
|
196
|
+
function parseAnkrBalance(asset, decimals) {
|
|
197
|
+
const tokenBalance = asString(asset.tokenBalance);
|
|
198
|
+
if (tokenBalance) {
|
|
199
|
+
if (/^\d+$/.test(tokenBalance))
|
|
200
|
+
return formatWei(BigInt(tokenBalance), decimals);
|
|
201
|
+
return tokenBalance;
|
|
202
|
+
}
|
|
203
|
+
const displayBalance = asString(asset.balance);
|
|
204
|
+
if (displayBalance) {
|
|
205
|
+
if (/^\d+$/.test(displayBalance))
|
|
206
|
+
return formatWei(BigInt(displayBalance), decimals);
|
|
207
|
+
return displayBalance;
|
|
208
|
+
}
|
|
209
|
+
const rawBalance = asString(asset.balanceRawInteger);
|
|
210
|
+
if (rawBalance && /^\d+$/.test(rawBalance))
|
|
211
|
+
return formatWei(BigInt(rawBalance), decimals);
|
|
212
|
+
return "0";
|
|
213
|
+
}
|
|
214
|
+
function isZeroBalance(balance) {
|
|
215
|
+
if (!balance) return true;
|
|
216
|
+
if (/^0+(\.0+)?$/.test(balance)) return true;
|
|
217
|
+
const parsed = Number.parseFloat(balance);
|
|
218
|
+
return Number.isFinite(parsed) ? parsed <= 0 : false;
|
|
219
|
+
}
|
|
220
|
+
function isAnkrNativeAsset(asset) {
|
|
221
|
+
const tokenType = (asset.tokenType ?? "").toUpperCase();
|
|
222
|
+
const symbol = (asset.tokenSymbol ?? "").toUpperCase();
|
|
223
|
+
const contract = (asset.contractAddress ?? "").toLowerCase();
|
|
224
|
+
if (tokenType === "NATIVE") return true;
|
|
225
|
+
return symbol === "BNB" && (!contract || contract === ZERO_ADDRESS);
|
|
226
|
+
}
|
|
227
|
+
function formatWei(wei, decimals) {
|
|
228
|
+
if (wei <= 0n || decimals <= 0) return wei <= 0n ? "0" : wei.toString();
|
|
229
|
+
const divisor = 10n ** BigInt(decimals);
|
|
230
|
+
const whole = wei / divisor;
|
|
231
|
+
const rem = wei % divisor;
|
|
232
|
+
if (rem === 0n) return whole.toString();
|
|
233
|
+
return `${whole}.${rem.toString().padStart(decimals, "0").replace(/0+$/, "")}`;
|
|
234
|
+
}
|
|
235
|
+
async function fetchAlchemyChainBalances(chain, address, alchemyKey) {
|
|
236
|
+
const url = `https://${chain.subdomain}.g.alchemy.com/v2/${alchemyKey}`;
|
|
237
|
+
const nativeData = await jsonOrThrow(
|
|
238
|
+
await fetch(
|
|
239
|
+
url,
|
|
240
|
+
rpcJsonRequest(
|
|
241
|
+
JSON.stringify({
|
|
242
|
+
jsonrpc: "2.0",
|
|
243
|
+
id: 1,
|
|
244
|
+
method: "eth_getBalance",
|
|
245
|
+
params: [address, "latest"]
|
|
246
|
+
})
|
|
247
|
+
)
|
|
248
|
+
)
|
|
249
|
+
);
|
|
250
|
+
const nativeBalance = formatWei(
|
|
251
|
+
nativeData.result ? BigInt(nativeData.result) : 0n,
|
|
252
|
+
18
|
|
253
|
+
);
|
|
254
|
+
const tokenData = await jsonOrThrow(
|
|
255
|
+
await fetch(
|
|
256
|
+
url,
|
|
257
|
+
rpcJsonRequest(
|
|
258
|
+
JSON.stringify({
|
|
259
|
+
jsonrpc: "2.0",
|
|
260
|
+
id: 2,
|
|
261
|
+
method: "alchemy_getTokenBalances",
|
|
262
|
+
params: [address, "DEFAULT_TOKENS"]
|
|
263
|
+
})
|
|
264
|
+
)
|
|
265
|
+
)
|
|
266
|
+
);
|
|
267
|
+
const nonZero = (tokenData.result?.tokenBalances ?? []).filter(
|
|
268
|
+
(t) => t.tokenBalance && t.tokenBalance !== "0x0" && t.tokenBalance !== "0x"
|
|
269
|
+
);
|
|
270
|
+
const metaResults = await Promise.allSettled(
|
|
271
|
+
nonZero.slice(0, 50).map(async (tok) => {
|
|
272
|
+
const meta = (await jsonOrThrow(
|
|
273
|
+
await fetch(
|
|
274
|
+
url,
|
|
275
|
+
rpcJsonRequest(
|
|
276
|
+
JSON.stringify({
|
|
277
|
+
jsonrpc: "2.0",
|
|
278
|
+
id: 3,
|
|
279
|
+
method: "alchemy_getTokenMetadata",
|
|
280
|
+
params: [tok.contractAddress]
|
|
281
|
+
})
|
|
282
|
+
)
|
|
283
|
+
)
|
|
284
|
+
)).result;
|
|
285
|
+
const decimals = meta?.decimals ?? 18;
|
|
286
|
+
return {
|
|
287
|
+
symbol: meta?.symbol ?? "???",
|
|
288
|
+
name: meta?.name ?? "Unknown Token",
|
|
289
|
+
contractAddress: tok.contractAddress,
|
|
290
|
+
balance: formatWei(BigInt(tok.tokenBalance), decimals),
|
|
291
|
+
decimals,
|
|
292
|
+
valueUsd: "0",
|
|
293
|
+
logoUrl: meta?.logo ?? ""
|
|
294
|
+
};
|
|
295
|
+
})
|
|
296
|
+
);
|
|
297
|
+
const tokens = metaResults.filter(
|
|
298
|
+
(r) => r.status === "fulfilled"
|
|
299
|
+
).map((r) => r.value);
|
|
300
|
+
const allAddresses = tokens.map((t) => t.contractAddress);
|
|
301
|
+
const wrappedNative = WRAPPED_NATIVE[chain.chainId];
|
|
302
|
+
if (wrappedNative) allAddresses.push(wrappedNative);
|
|
303
|
+
const dexPrices = await fetchDexPrices(chain.chainId, allAddresses);
|
|
304
|
+
for (const tok of tokens) {
|
|
305
|
+
const meta = dexPrices.get(tok.contractAddress.toLowerCase());
|
|
306
|
+
if (meta) {
|
|
307
|
+
tok.valueUsd = computeValueUsd(tok.balance, meta.price);
|
|
308
|
+
if (meta.logoUrl && !tok.logoUrl) tok.logoUrl = meta.logoUrl;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const nativeMeta = wrappedNative ? dexPrices.get(wrappedNative.toLowerCase()) : void 0;
|
|
312
|
+
const nativeValueUsd = nativeMeta ? computeValueUsd(nativeBalance, nativeMeta.price) : "0";
|
|
313
|
+
return {
|
|
314
|
+
chain: chain.name,
|
|
315
|
+
chainId: chain.chainId,
|
|
316
|
+
nativeBalance,
|
|
317
|
+
nativeSymbol: chain.nativeSymbol,
|
|
318
|
+
nativeValueUsd,
|
|
319
|
+
tokens,
|
|
320
|
+
error: null
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
async function fetchAnkrChainBalances(chain, address, ankrKey) {
|
|
324
|
+
const res = await fetch(
|
|
325
|
+
`https://rpc.ankr.com/multichain/${ankrKey}`,
|
|
326
|
+
rpcJsonRequest(
|
|
327
|
+
JSON.stringify({
|
|
328
|
+
jsonrpc: "2.0",
|
|
329
|
+
id: 1,
|
|
330
|
+
method: "ankr_getAccountBalance",
|
|
331
|
+
params: {
|
|
332
|
+
walletAddress: address,
|
|
333
|
+
blockchain: [chain.ankrChain ?? "bsc"],
|
|
334
|
+
onlyWhitelisted: false
|
|
335
|
+
}
|
|
336
|
+
})
|
|
337
|
+
)
|
|
338
|
+
);
|
|
339
|
+
const data = await jsonOrThrow(
|
|
340
|
+
res
|
|
341
|
+
);
|
|
342
|
+
const assets = data.result?.assets ?? [];
|
|
343
|
+
const nativeAsset = assets.find(isAnkrNativeAsset);
|
|
344
|
+
const nativeBalance = nativeAsset ? parseAnkrBalance(
|
|
345
|
+
nativeAsset,
|
|
346
|
+
parseTokenDecimals(nativeAsset.tokenDecimals)
|
|
347
|
+
) : "0";
|
|
348
|
+
const tokens = [];
|
|
349
|
+
for (const asset of assets) {
|
|
350
|
+
if (isAnkrNativeAsset(asset)) continue;
|
|
351
|
+
const decimals = parseTokenDecimals(asset.tokenDecimals);
|
|
352
|
+
const balance = parseAnkrBalance(asset, decimals);
|
|
353
|
+
if (isZeroBalance(balance)) continue;
|
|
354
|
+
tokens.push({
|
|
355
|
+
symbol: asset.tokenSymbol ?? "???",
|
|
356
|
+
name: asset.tokenName ?? "Unknown Token",
|
|
357
|
+
contractAddress: asset.contractAddress ?? "",
|
|
358
|
+
balance,
|
|
359
|
+
decimals,
|
|
360
|
+
valueUsd: "0",
|
|
361
|
+
logoUrl: asset.thumbnail ?? ""
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
const allAddresses = tokens.filter((t) => t.contractAddress).map((t) => t.contractAddress);
|
|
365
|
+
const wrappedNative = WRAPPED_NATIVE[chain.chainId];
|
|
366
|
+
if (wrappedNative) allAddresses.push(wrappedNative);
|
|
367
|
+
logger.info(
|
|
368
|
+
`[wallet] Fetching DEX prices for ${chain.name}: ${allAddresses.length} addresses (native=${nativeBalance})`
|
|
369
|
+
);
|
|
370
|
+
const dexPrices = await fetchDexPrices(chain.chainId, allAddresses);
|
|
371
|
+
logger.info(
|
|
372
|
+
`[wallet] DEX prices result for ${chain.name}: ${dexPrices.size} prices found`
|
|
373
|
+
);
|
|
374
|
+
for (const tok of tokens) {
|
|
375
|
+
const meta = dexPrices.get(tok.contractAddress.toLowerCase());
|
|
376
|
+
if (meta) {
|
|
377
|
+
tok.valueUsd = computeValueUsd(tok.balance, meta.price);
|
|
378
|
+
if (meta.logoUrl && !tok.logoUrl) tok.logoUrl = meta.logoUrl;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const nativeMeta = wrappedNative ? dexPrices.get(wrappedNative.toLowerCase()) : void 0;
|
|
382
|
+
const nativeValueUsd = nativeMeta ? computeValueUsd(nativeBalance, nativeMeta.price) : "0";
|
|
383
|
+
return {
|
|
384
|
+
chain: chain.name,
|
|
385
|
+
chainId: chain.chainId,
|
|
386
|
+
nativeBalance,
|
|
387
|
+
nativeSymbol: chain.nativeSymbol,
|
|
388
|
+
nativeValueUsd,
|
|
389
|
+
tokens,
|
|
390
|
+
error: null
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
async function fetchNativeBalanceViaRpc(rpcUrl, address) {
|
|
394
|
+
const data = await jsonOrThrow(
|
|
395
|
+
await fetch(
|
|
396
|
+
rpcUrl,
|
|
397
|
+
rpcJsonRequest(
|
|
398
|
+
JSON.stringify({
|
|
399
|
+
jsonrpc: "2.0",
|
|
400
|
+
id: 1,
|
|
401
|
+
method: "eth_getBalance",
|
|
402
|
+
params: [address, "latest"]
|
|
403
|
+
})
|
|
404
|
+
)
|
|
405
|
+
)
|
|
406
|
+
);
|
|
407
|
+
if (data.error?.message) {
|
|
408
|
+
throw new Error(data.error.message);
|
|
409
|
+
}
|
|
410
|
+
const raw = typeof data.result === "string" ? data.result : "0x0";
|
|
411
|
+
const wei = raw.startsWith("0x") ? BigInt(raw) : BigInt(raw || "0");
|
|
412
|
+
return formatWei(wei, 18);
|
|
413
|
+
}
|
|
414
|
+
async function fetchEvmNativeBalanceViaRpc(rpcUrl, address) {
|
|
415
|
+
return fetchNativeBalanceViaRpc(rpcUrl, address);
|
|
416
|
+
}
|
|
417
|
+
async function fetchErc20BalanceViaRpc(rpcUrl, walletAddress, contractAddress) {
|
|
418
|
+
const paddedWallet = walletAddress.toLowerCase().replace("0x", "").padStart(64, "0");
|
|
419
|
+
const balanceOfData = `0x70a08231${paddedWallet}`;
|
|
420
|
+
const symbolData = "0x95d89b41";
|
|
421
|
+
const decimalsData = "0x313ce567";
|
|
422
|
+
const makeCall = (to, data) => fetch(rpcUrl, {
|
|
423
|
+
method: "POST",
|
|
424
|
+
headers: { "Content-Type": "application/json" },
|
|
425
|
+
body: JSON.stringify({
|
|
426
|
+
jsonrpc: "2.0",
|
|
427
|
+
id: 1,
|
|
428
|
+
method: "eth_call",
|
|
429
|
+
params: [{ to, data }, "latest"]
|
|
430
|
+
}),
|
|
431
|
+
signal: AbortSignal.timeout(8e3)
|
|
432
|
+
}).then((r) => r.json());
|
|
433
|
+
try {
|
|
434
|
+
const [balRes, symRes, decRes] = await Promise.all([
|
|
435
|
+
makeCall(contractAddress, balanceOfData),
|
|
436
|
+
makeCall(contractAddress, symbolData),
|
|
437
|
+
makeCall(contractAddress, decimalsData)
|
|
438
|
+
]);
|
|
439
|
+
const rawBal = balRes.result;
|
|
440
|
+
if (!rawBal || rawBal === "0x" || rawBal === "0x0" || BigInt(rawBal) === 0n)
|
|
441
|
+
return null;
|
|
442
|
+
let decimals = 18;
|
|
443
|
+
if (decRes.result && decRes.result !== "0x") {
|
|
444
|
+
const d = Number(BigInt(decRes.result));
|
|
445
|
+
if (Number.isFinite(d) && d >= 0 && d <= 36) decimals = d;
|
|
446
|
+
}
|
|
447
|
+
let symbol = "TOKEN";
|
|
448
|
+
if (symRes.result && symRes.result.length > 2) {
|
|
449
|
+
try {
|
|
450
|
+
const hex = symRes.result.slice(2);
|
|
451
|
+
if (hex.length >= 128) {
|
|
452
|
+
const len = Number(BigInt(`0x${hex.slice(64, 128)}`));
|
|
453
|
+
const bytes = Buffer.from(hex.slice(128, 128 + len * 2), "hex");
|
|
454
|
+
const decoded = bytes.toString("utf-8").replace(/\0/g, "").trim();
|
|
455
|
+
if (decoded) symbol = decoded;
|
|
456
|
+
}
|
|
457
|
+
} catch {
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
const balance = formatWei(BigInt(rawBal), decimals);
|
|
461
|
+
return {
|
|
462
|
+
symbol,
|
|
463
|
+
name: symbol,
|
|
464
|
+
contractAddress,
|
|
465
|
+
balance,
|
|
466
|
+
decimals,
|
|
467
|
+
valueUsd: "0",
|
|
468
|
+
logoUrl: ""
|
|
469
|
+
};
|
|
470
|
+
} catch {
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
async function fetchEvmChainBalancesViaRpc(chain, address, rpcUrls, knownTokenAddresses) {
|
|
475
|
+
const errors = [];
|
|
476
|
+
for (const rpcUrl of rpcUrls) {
|
|
477
|
+
try {
|
|
478
|
+
const nativeBalance = await fetchNativeBalanceViaRpc(rpcUrl, address);
|
|
479
|
+
const tokens = [];
|
|
480
|
+
if (knownTokenAddresses && knownTokenAddresses.length > 0) {
|
|
481
|
+
const results = await Promise.allSettled(
|
|
482
|
+
knownTokenAddresses.slice(0, 30).map((addr) => fetchErc20BalanceViaRpc(rpcUrl, address, addr))
|
|
483
|
+
);
|
|
484
|
+
for (const r of results) {
|
|
485
|
+
if (r.status === "fulfilled" && r.value) tokens.push(r.value);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
const wrappedNative = WRAPPED_NATIVE[chain.chainId];
|
|
489
|
+
const priceAddresses = tokens.map((t) => t.contractAddress);
|
|
490
|
+
if (wrappedNative) priceAddresses.push(wrappedNative);
|
|
491
|
+
const dexPrices = priceAddresses.length > 0 ? await fetchDexPrices(chain.chainId, priceAddresses) : /* @__PURE__ */ new Map();
|
|
492
|
+
let nativeValueUsd = "0";
|
|
493
|
+
if (wrappedNative) {
|
|
494
|
+
const nativeMeta = dexPrices.get(wrappedNative.toLowerCase());
|
|
495
|
+
if (nativeMeta)
|
|
496
|
+
nativeValueUsd = computeValueUsd(nativeBalance, nativeMeta.price);
|
|
497
|
+
logger.info(
|
|
498
|
+
`[wallet] RPC path: ${chain.name} native=${nativeBalance} price=${nativeMeta?.price ?? "none"} value=$${nativeValueUsd}`
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
for (const tok of tokens) {
|
|
502
|
+
const meta = dexPrices.get(tok.contractAddress.toLowerCase());
|
|
503
|
+
if (meta) {
|
|
504
|
+
tok.valueUsd = computeValueUsd(tok.balance, meta.price);
|
|
505
|
+
if (meta.logoUrl) tok.logoUrl = meta.logoUrl;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
if (tokens.length > 0) {
|
|
509
|
+
logger.info(
|
|
510
|
+
`[wallet] RPC path: ${chain.name} found ${tokens.length} tokens with balance`
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
chain: chain.name,
|
|
515
|
+
chainId: chain.chainId,
|
|
516
|
+
nativeBalance,
|
|
517
|
+
nativeSymbol: chain.nativeSymbol,
|
|
518
|
+
nativeValueUsd,
|
|
519
|
+
tokens,
|
|
520
|
+
error: null
|
|
521
|
+
};
|
|
522
|
+
} catch (err) {
|
|
523
|
+
const msg = String(err);
|
|
524
|
+
errors.push(`${describeRpcEndpoint(rpcUrl)}: ${msg}`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
throw new Error(
|
|
528
|
+
errors.join(" | ").slice(0, 400) || `${chain.name} RPC unavailable`
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
async function fetchAlchemyChainNfts(chain, address, alchemyKey) {
|
|
532
|
+
const res = await fetch(
|
|
533
|
+
`https://${chain.subdomain}.g.alchemy.com/nft/v3/${alchemyKey}/getNFTsForOwner?owner=${address}&withMetadata=true&pageSize=50`,
|
|
534
|
+
{ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) }
|
|
535
|
+
);
|
|
536
|
+
const data = await jsonOrThrow(res);
|
|
537
|
+
return {
|
|
538
|
+
chain: chain.name,
|
|
539
|
+
nfts: (data.ownedNfts ?? []).map((nft) => ({
|
|
540
|
+
contractAddress: nft.contract?.address ?? "",
|
|
541
|
+
tokenId: nft.tokenId ?? "",
|
|
542
|
+
name: nft.name ?? "Untitled",
|
|
543
|
+
description: (nft.description ?? "").slice(0, 200),
|
|
544
|
+
imageUrl: nft.image?.cachedUrl ?? nft.image?.thumbnailUrl ?? nft.image?.originalUrl ?? "",
|
|
545
|
+
collectionName: nft.contract?.openSeaMetadata?.collectionName ?? nft.contract?.name ?? "",
|
|
546
|
+
tokenType: nft.tokenType ?? "ERC721"
|
|
547
|
+
}))
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
async function fetchAnkrChainNfts(chain, address, ankrKey) {
|
|
551
|
+
const res = await fetch(
|
|
552
|
+
`https://rpc.ankr.com/multichain/${ankrKey}`,
|
|
553
|
+
rpcJsonRequest(
|
|
554
|
+
JSON.stringify({
|
|
555
|
+
jsonrpc: "2.0",
|
|
556
|
+
id: 1,
|
|
557
|
+
method: "ankr_getNFTsByOwner",
|
|
558
|
+
params: {
|
|
559
|
+
walletAddress: address,
|
|
560
|
+
blockchain: [chain.ankrChain ?? "bsc"],
|
|
561
|
+
pageSize: 50
|
|
562
|
+
}
|
|
563
|
+
})
|
|
564
|
+
)
|
|
565
|
+
);
|
|
566
|
+
const data = await jsonOrThrow(res);
|
|
567
|
+
return {
|
|
568
|
+
chain: chain.name,
|
|
569
|
+
nfts: (data.result?.assets ?? []).map((nft) => ({
|
|
570
|
+
contractAddress: nft.contractAddress ?? "",
|
|
571
|
+
tokenId: String(nft.tokenId ?? ""),
|
|
572
|
+
name: nft.name ?? "Untitled",
|
|
573
|
+
description: (nft.description ?? "").slice(0, 200),
|
|
574
|
+
imageUrl: nft.imageUrl ?? nft.imagePreviewUrl ?? nft.imageOriginalUrl ?? "",
|
|
575
|
+
collectionName: nft.collectionName ?? nft.contractName ?? "",
|
|
576
|
+
tokenType: nft.tokenType ?? "ERC721"
|
|
577
|
+
}))
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
async function fetchEvmBalances(address, alchemyOrKeys, maybeAnkrKey, knownTokenAddresses) {
|
|
581
|
+
const keys = resolveEvmProviderKeys(alchemyOrKeys, maybeAnkrKey);
|
|
582
|
+
const bscRpcUrls = keys.bscRpcUrls;
|
|
583
|
+
const ethRpcUrls = keys.ethereumRpcUrls;
|
|
584
|
+
const baseRpcUrls = keys.baseRpcUrls;
|
|
585
|
+
const avaxRpcUrls = keys.avaxRpcUrls;
|
|
586
|
+
const hasManagedBscRpc = bscRpcUrls.length > 0;
|
|
587
|
+
const activeChains = DEFAULT_EVM_CHAINS.filter((chain) => {
|
|
588
|
+
if (chain.provider === "ankr") {
|
|
589
|
+
return Boolean(keys.ankrKey) || isBscChain(chain) && hasManagedBscRpc;
|
|
590
|
+
}
|
|
591
|
+
if (keys.alchemyKey) return true;
|
|
592
|
+
if (chain.chainId === 1) return ethRpcUrls.length > 0;
|
|
593
|
+
if (chain.chainId === 8453) return baseRpcUrls.length > 0;
|
|
594
|
+
if (chain.chainId === 56) return hasManagedBscRpc;
|
|
595
|
+
if (chain.chainId === 43114) return avaxRpcUrls.length > 0;
|
|
596
|
+
return false;
|
|
597
|
+
});
|
|
598
|
+
return Promise.all(
|
|
599
|
+
activeChains.map(async (chain) => {
|
|
600
|
+
try {
|
|
601
|
+
if (chain.provider === "ankr") {
|
|
602
|
+
if (keys.ankrKey) {
|
|
603
|
+
return await fetchAnkrChainBalances(chain, address, keys.ankrKey);
|
|
604
|
+
}
|
|
605
|
+
if (isBscChain(chain) && hasManagedBscRpc) {
|
|
606
|
+
return await fetchEvmChainBalancesViaRpc(
|
|
607
|
+
chain,
|
|
608
|
+
address,
|
|
609
|
+
bscRpcUrls,
|
|
610
|
+
knownTokenAddresses
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
return makeEvmChainFailure(chain, "Missing ANKR_API_KEY");
|
|
614
|
+
}
|
|
615
|
+
if (!keys.alchemyKey) {
|
|
616
|
+
if (chain.chainId === 1 && ethRpcUrls.length > 0) {
|
|
617
|
+
return await fetchEvmChainBalancesViaRpc(
|
|
618
|
+
chain,
|
|
619
|
+
address,
|
|
620
|
+
ethRpcUrls,
|
|
621
|
+
knownTokenAddresses
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
if (chain.chainId === 8453 && baseRpcUrls.length > 0) {
|
|
625
|
+
return await fetchEvmChainBalancesViaRpc(
|
|
626
|
+
chain,
|
|
627
|
+
address,
|
|
628
|
+
baseRpcUrls,
|
|
629
|
+
knownTokenAddresses
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
if (chain.chainId === 56 && hasManagedBscRpc) {
|
|
633
|
+
return await fetchEvmChainBalancesViaRpc(
|
|
634
|
+
chain,
|
|
635
|
+
address,
|
|
636
|
+
bscRpcUrls,
|
|
637
|
+
knownTokenAddresses
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
if (chain.chainId === 43114 && avaxRpcUrls.length > 0) {
|
|
641
|
+
return await fetchEvmChainBalancesViaRpc(
|
|
642
|
+
chain,
|
|
643
|
+
address,
|
|
644
|
+
avaxRpcUrls,
|
|
645
|
+
knownTokenAddresses
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
return makeEvmChainFailure(chain, "Missing ALCHEMY_API_KEY");
|
|
649
|
+
}
|
|
650
|
+
return await fetchAlchemyChainBalances(chain, address, keys.alchemyKey);
|
|
651
|
+
} catch (err) {
|
|
652
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
653
|
+
logger.warn(`EVM balance fetch failed for ${chain.name}: ${msg}`);
|
|
654
|
+
return makeEvmChainFailure(chain, msg);
|
|
655
|
+
}
|
|
656
|
+
})
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
async function fetchEvmNfts(address, alchemyOrKeys, maybeAnkrKey) {
|
|
660
|
+
const keys = resolveEvmProviderKeys(alchemyOrKeys, maybeAnkrKey);
|
|
661
|
+
const hasManagedBscRpc = keys.bscRpcUrls.length > 0;
|
|
662
|
+
const activeChains = DEFAULT_EVM_CHAINS.filter((chain) => {
|
|
663
|
+
if (chain.provider === "ankr") {
|
|
664
|
+
return isBscChain(chain) && hasManagedBscRpc || Boolean(keys.ankrKey);
|
|
665
|
+
}
|
|
666
|
+
if (keys.alchemyKey) return true;
|
|
667
|
+
if (chain.chainId === 56) return hasManagedBscRpc;
|
|
668
|
+
return false;
|
|
669
|
+
});
|
|
670
|
+
return Promise.all(
|
|
671
|
+
activeChains.map(
|
|
672
|
+
async (chain) => {
|
|
673
|
+
try {
|
|
674
|
+
if (chain.provider === "ankr") {
|
|
675
|
+
if (!keys.ankrKey) {
|
|
676
|
+
return { chain: chain.name, nfts: [] };
|
|
677
|
+
}
|
|
678
|
+
return await fetchAnkrChainNfts(chain, address, keys.ankrKey);
|
|
679
|
+
}
|
|
680
|
+
if (!keys.alchemyKey) return { chain: chain.name, nfts: [] };
|
|
681
|
+
return await fetchAlchemyChainNfts(chain, address, keys.alchemyKey);
|
|
682
|
+
} catch (err) {
|
|
683
|
+
logger.warn(`EVM NFT fetch failed for ${chain.name}: ${err}`);
|
|
684
|
+
return { chain: chain.name, nfts: [] };
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
)
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
export {
|
|
691
|
+
DEFAULT_EVM_CHAINS,
|
|
692
|
+
fetchEvmBalances,
|
|
693
|
+
fetchEvmNativeBalanceViaRpc,
|
|
694
|
+
fetchEvmNfts,
|
|
695
|
+
resolveEvmProviderKeys
|
|
696
|
+
};
|
|
697
|
+
//# sourceMappingURL=wallet-evm-balance.js.map
|