@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.
Files changed (219) hide show
  1. package/dist/ApprovalQueue.d.ts +18 -0
  2. package/dist/ApprovalQueue.d.ts.map +1 -0
  3. package/dist/ApprovalQueue.js +420 -0
  4. package/dist/ApprovalQueue.js.map +1 -0
  5. package/dist/StewardLogo.d.ts +11 -0
  6. package/dist/StewardLogo.d.ts.map +1 -0
  7. package/dist/StewardLogo.js +36 -0
  8. package/dist/StewardLogo.js.map +1 -0
  9. package/dist/StewardView.d.ts +13 -0
  10. package/dist/StewardView.d.ts.map +1 -0
  11. package/dist/StewardView.helpers.d.ts +15 -0
  12. package/dist/StewardView.helpers.d.ts.map +1 -0
  13. package/dist/StewardView.helpers.js +45 -0
  14. package/dist/StewardView.helpers.js.map +1 -0
  15. package/dist/StewardView.interact.d.ts +2 -0
  16. package/dist/StewardView.interact.d.ts.map +1 -0
  17. package/dist/StewardView.interact.js +54 -0
  18. package/dist/StewardView.interact.js.map +1 -0
  19. package/dist/StewardView.js +249 -0
  20. package/dist/StewardView.js.map +1 -0
  21. package/dist/TransactionHistory.d.ts +22 -0
  22. package/dist/TransactionHistory.d.ts.map +1 -0
  23. package/dist/TransactionHistory.js +361 -0
  24. package/dist/TransactionHistory.js.map +1 -0
  25. package/dist/__fixtures__/steward-sdk-fixtures.d.ts +10 -0
  26. package/dist/__fixtures__/steward-sdk-fixtures.d.ts.map +1 -0
  27. package/dist/__fixtures__/steward-sdk-fixtures.js +60 -0
  28. package/dist/__fixtures__/steward-sdk-fixtures.js.map +1 -0
  29. package/dist/actions/wallet-action-shared.d.ts +15 -0
  30. package/dist/actions/wallet-action-shared.d.ts.map +1 -0
  31. package/dist/actions/wallet-action-shared.js +16 -0
  32. package/dist/actions/wallet-action-shared.js.map +1 -0
  33. package/dist/api/binance-skill-helpers.d.ts +21 -0
  34. package/dist/api/binance-skill-helpers.d.ts.map +1 -0
  35. package/dist/api/binance-skill-helpers.js +790 -0
  36. package/dist/api/binance-skill-helpers.js.map +1 -0
  37. package/dist/api/bsc-trade.d.ts +36 -0
  38. package/dist/api/bsc-trade.d.ts.map +1 -0
  39. package/dist/api/bsc-trade.js +796 -0
  40. package/dist/api/bsc-trade.js.map +1 -0
  41. package/dist/api/trade-safety.d.ts +35 -0
  42. package/dist/api/trade-safety.d.ts.map +1 -0
  43. package/dist/api/trade-safety.js +56 -0
  44. package/dist/api/trade-safety.js.map +1 -0
  45. package/dist/api/tx-service.d.ts +53 -0
  46. package/dist/api/tx-service.d.ts.map +1 -0
  47. package/dist/api/tx-service.js +206 -0
  48. package/dist/api/tx-service.js.map +1 -0
  49. package/dist/api/wallet-bsc-routes.d.ts +63 -0
  50. package/dist/api/wallet-bsc-routes.d.ts.map +1 -0
  51. package/dist/api/wallet-bsc-routes.js +337 -0
  52. package/dist/api/wallet-bsc-routes.js.map +1 -0
  53. package/dist/api/wallet-capability.d.ts +2 -0
  54. package/dist/api/wallet-capability.d.ts.map +1 -0
  55. package/dist/api/wallet-capability.js +15 -0
  56. package/dist/api/wallet-capability.js.map +1 -0
  57. package/dist/api/wallet-dex-prices.d.ts +43 -0
  58. package/dist/api/wallet-dex-prices.d.ts.map +1 -0
  59. package/dist/api/wallet-dex-prices.js +132 -0
  60. package/dist/api/wallet-dex-prices.js.map +1 -0
  61. package/dist/api/wallet-evm-balance.d.ts +72 -0
  62. package/dist/api/wallet-evm-balance.d.ts.map +1 -0
  63. package/dist/api/wallet-evm-balance.js +697 -0
  64. package/dist/api/wallet-evm-balance.js.map +1 -0
  65. package/dist/api/wallet-routes.d.ts +27 -0
  66. package/dist/api/wallet-routes.d.ts.map +1 -0
  67. package/dist/api/wallet-routes.js +556 -0
  68. package/dist/api/wallet-routes.js.map +1 -0
  69. package/dist/api/wallet-rpc.d.ts +73 -0
  70. package/dist/api/wallet-rpc.d.ts.map +1 -0
  71. package/dist/api/wallet-rpc.js +460 -0
  72. package/dist/api/wallet-rpc.js.map +1 -0
  73. package/dist/api/wallet-trade-routes.d.ts +104 -0
  74. package/dist/api/wallet-trade-routes.d.ts.map +1 -0
  75. package/dist/api/wallet-trade-routes.js +353 -0
  76. package/dist/api/wallet-trade-routes.js.map +1 -0
  77. package/dist/api/wallet-trading-profile.d.ts +31 -0
  78. package/dist/api/wallet-trading-profile.d.ts.map +1 -0
  79. package/dist/api/wallet-trading-profile.js +500 -0
  80. package/dist/api/wallet-trading-profile.js.map +1 -0
  81. package/dist/api/wallet.d.ts +60 -0
  82. package/dist/api/wallet.d.ts.map +1 -0
  83. package/dist/api/wallet.js +617 -0
  84. package/dist/api/wallet.js.map +1 -0
  85. package/dist/chain-utils.d.ts +10 -0
  86. package/dist/chain-utils.d.ts.map +1 -0
  87. package/dist/chain-utils.js +81 -0
  88. package/dist/chain-utils.js.map +1 -0
  89. package/dist/components/StewardSpatialView.d.ts +74 -0
  90. package/dist/components/StewardSpatialView.d.ts.map +1 -0
  91. package/dist/components/StewardSpatialView.js +309 -0
  92. package/dist/components/StewardSpatialView.js.map +1 -0
  93. package/dist/index.d.ts +20 -0
  94. package/dist/index.d.ts.map +1 -0
  95. package/dist/index.js +77 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/plugin.d.ts +21 -0
  98. package/dist/plugin.d.ts.map +1 -0
  99. package/dist/plugin.js +319 -0
  100. package/dist/plugin.js.map +1 -0
  101. package/dist/providers/steward-balance.d.ts +12 -0
  102. package/dist/providers/steward-balance.d.ts.map +1 -0
  103. package/dist/providers/steward-balance.js +85 -0
  104. package/dist/providers/steward-balance.js.map +1 -0
  105. package/dist/providers/steward-receive-address.d.ts +12 -0
  106. package/dist/providers/steward-receive-address.d.ts.map +1 -0
  107. package/dist/providers/steward-receive-address.js +47 -0
  108. package/dist/providers/steward-receive-address.js.map +1 -0
  109. package/dist/register-routes.d.ts +2 -0
  110. package/dist/register-routes.d.ts.map +1 -0
  111. package/dist/register-routes.js +6 -0
  112. package/dist/register-routes.js.map +1 -0
  113. package/dist/register-terminal-view.d.ts +15 -0
  114. package/dist/register-terminal-view.d.ts.map +1 -0
  115. package/dist/register-terminal-view.js +34 -0
  116. package/dist/register-terminal-view.js.map +1 -0
  117. package/dist/routes/steward-bridge.d.ts +202 -0
  118. package/dist/routes/steward-bridge.d.ts.map +1 -0
  119. package/dist/routes/steward-bridge.js +776 -0
  120. package/dist/routes/steward-bridge.js.map +1 -0
  121. package/dist/routes/steward-compat-routes.d.ts +21 -0
  122. package/dist/routes/steward-compat-routes.d.ts.map +1 -0
  123. package/dist/routes/steward-compat-routes.js +350 -0
  124. package/dist/routes/steward-compat-routes.js.map +1 -0
  125. package/dist/routes/wallet-browser-compat-routes.d.ts +6 -0
  126. package/dist/routes/wallet-browser-compat-routes.d.ts.map +1 -0
  127. package/dist/routes/wallet-browser-compat-routes.js +402 -0
  128. package/dist/routes/wallet-browser-compat-routes.js.map +1 -0
  129. package/dist/routes/wallet-bsc-core-routes.d.ts +15 -0
  130. package/dist/routes/wallet-bsc-core-routes.d.ts.map +1 -0
  131. package/dist/routes/wallet-bsc-core-routes.js +59 -0
  132. package/dist/routes/wallet-bsc-core-routes.js.map +1 -0
  133. package/dist/routes/wallet-compat-routes.d.ts +13 -0
  134. package/dist/routes/wallet-compat-routes.d.ts.map +1 -0
  135. package/dist/routes/wallet-compat-routes.js +206 -0
  136. package/dist/routes/wallet-compat-routes.js.map +1 -0
  137. package/dist/routes/wallet-core-routes.d.ts +16 -0
  138. package/dist/routes/wallet-core-routes.d.ts.map +1 -0
  139. package/dist/routes/wallet-core-routes.js +48 -0
  140. package/dist/routes/wallet-core-routes.js.map +1 -0
  141. package/dist/routes/wallet-trade-compat-routes.d.ts +11 -0
  142. package/dist/routes/wallet-trade-compat-routes.d.ts.map +1 -0
  143. package/dist/routes/wallet-trade-compat-routes.js +570 -0
  144. package/dist/routes/wallet-trade-compat-routes.js.map +1 -0
  145. package/dist/security/hydrate-wallet-keys-from-platform-store.d.ts +7 -0
  146. package/dist/security/hydrate-wallet-keys-from-platform-store.d.ts.map +1 -0
  147. package/dist/security/hydrate-wallet-keys-from-platform-store.js +43 -0
  148. package/dist/security/hydrate-wallet-keys-from-platform-store.js.map +1 -0
  149. package/dist/security/wallet-os-store-actions.d.ts +14 -0
  150. package/dist/security/wallet-os-store-actions.d.ts.map +1 -0
  151. package/dist/security/wallet-os-store-actions.js +63 -0
  152. package/dist/security/wallet-os-store-actions.js.map +1 -0
  153. package/dist/services/steward-credentials.d.ts +2 -0
  154. package/dist/services/steward-credentials.d.ts.map +1 -0
  155. package/dist/services/steward-credentials.js +2 -0
  156. package/dist/services/steward-credentials.js.map +1 -0
  157. package/dist/services/steward-evm-account.d.ts +75 -0
  158. package/dist/services/steward-evm-account.d.ts.map +1 -0
  159. package/dist/services/steward-evm-account.js +279 -0
  160. package/dist/services/steward-evm-account.js.map +1 -0
  161. package/dist/services/steward-evm-bridge.d.ts +36 -0
  162. package/dist/services/steward-evm-bridge.d.ts.map +1 -0
  163. package/dist/services/steward-evm-bridge.js +78 -0
  164. package/dist/services/steward-evm-bridge.js.map +1 -0
  165. package/dist/services/steward-sidecar/health-check.d.ts +2 -0
  166. package/dist/services/steward-sidecar/health-check.d.ts.map +1 -0
  167. package/dist/services/steward-sidecar/health-check.js +2 -0
  168. package/dist/services/steward-sidecar/health-check.js.map +1 -0
  169. package/dist/services/steward-sidecar/helpers.d.ts +2 -0
  170. package/dist/services/steward-sidecar/helpers.d.ts.map +1 -0
  171. package/dist/services/steward-sidecar/helpers.js +2 -0
  172. package/dist/services/steward-sidecar/helpers.js.map +1 -0
  173. package/dist/services/steward-sidecar/process-management.d.ts +2 -0
  174. package/dist/services/steward-sidecar/process-management.d.ts.map +1 -0
  175. package/dist/services/steward-sidecar/process-management.js +2 -0
  176. package/dist/services/steward-sidecar/process-management.js.map +1 -0
  177. package/dist/services/steward-sidecar/types.d.ts +2 -0
  178. package/dist/services/steward-sidecar/types.d.ts.map +1 -0
  179. package/dist/services/steward-sidecar/types.js +2 -0
  180. package/dist/services/steward-sidecar/types.js.map +1 -0
  181. package/dist/services/steward-sidecar/wallet-setup.d.ts +2 -0
  182. package/dist/services/steward-sidecar/wallet-setup.d.ts.map +1 -0
  183. package/dist/services/steward-sidecar/wallet-setup.js +2 -0
  184. package/dist/services/steward-sidecar/wallet-setup.js.map +1 -0
  185. package/dist/services/steward-sidecar.d.ts +2 -0
  186. package/dist/services/steward-sidecar.d.ts.map +1 -0
  187. package/dist/services/steward-sidecar.js +2 -0
  188. package/dist/services/steward-sidecar.js.map +1 -0
  189. package/dist/services/steward-wallet.d.ts +25 -0
  190. package/dist/services/steward-wallet.d.ts.map +1 -0
  191. package/dist/services/steward-wallet.js +333 -0
  192. package/dist/services/steward-wallet.js.map +1 -0
  193. package/dist/steward-ui-state.d.ts +14 -0
  194. package/dist/steward-ui-state.d.ts.map +1 -0
  195. package/dist/steward-ui-state.js +46 -0
  196. package/dist/steward-ui-state.js.map +1 -0
  197. package/dist/steward-view-bundle.d.ts +3 -0
  198. package/dist/steward-view-bundle.d.ts.map +1 -0
  199. package/dist/steward-view-bundle.js +7 -0
  200. package/dist/steward-view-bundle.js.map +1 -0
  201. package/dist/types/bsc-trade.d.ts +180 -0
  202. package/dist/types/bsc-trade.d.ts.map +1 -0
  203. package/dist/types/bsc-trade.js +1 -0
  204. package/dist/types/bsc-trade.js.map +1 -0
  205. package/dist/types/index.d.ts +3 -0
  206. package/dist/types/index.d.ts.map +1 -0
  207. package/dist/types/index.js +3 -0
  208. package/dist/types/index.js.map +1 -0
  209. package/dist/types/steward.d.ts +83 -0
  210. package/dist/types/steward.d.ts.map +1 -0
  211. package/dist/types/steward.js +1 -0
  212. package/dist/types/steward.js.map +1 -0
  213. package/dist/ui.d.ts +7 -0
  214. package/dist/ui.d.ts.map +1 -0
  215. package/dist/ui.js +7 -0
  216. package/dist/ui.js.map +1 -0
  217. package/dist/views/bundle.js +601 -0
  218. package/dist/views/bundle.js.map +1 -0
  219. 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