multi-chain-balance-diff 0.1.0
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/README.md +332 -0
- package/package.json +52 -0
- package/schema/mcbd-output.schema.json +297 -0
- package/src/adapters/baseAdapter.js +121 -0
- package/src/adapters/evmAdapter.js +126 -0
- package/src/adapters/index.js +70 -0
- package/src/adapters/solanaAdapter.js +179 -0
- package/src/config/networks.js +234 -0
- package/src/index.js +1031 -0
- package/src/services/balanceService.js +156 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Network configuration for supported chains.
|
|
3
|
+
*
|
|
4
|
+
* Each network includes:
|
|
5
|
+
* - name: Human-readable network name
|
|
6
|
+
* - chainType: 'evm' or 'solana' (determines which adapter to use)
|
|
7
|
+
* - chainId: Chain ID (EVM) or null (Solana)
|
|
8
|
+
* - rpcUrl: Default public RPC (can be overridden via env vars)
|
|
9
|
+
* - nativeSymbol: Native currency symbol (ETH, SOL, etc.)
|
|
10
|
+
* - nativeDecimals: Decimals for native currency
|
|
11
|
+
* - blockExplorer: Block explorer URL for reference
|
|
12
|
+
* - tokens: Tokens to check balances for
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
require('dotenv').config();
|
|
16
|
+
|
|
17
|
+
const networks = {
|
|
18
|
+
// ==========================================================================
|
|
19
|
+
// EVM Networks
|
|
20
|
+
// ==========================================================================
|
|
21
|
+
mainnet: {
|
|
22
|
+
name: 'Ethereum Mainnet',
|
|
23
|
+
chainType: 'evm',
|
|
24
|
+
chainId: 1,
|
|
25
|
+
rpcUrl: process.env.RPC_URL_ETH || 'https://eth.llamarpc.com',
|
|
26
|
+
nativeSymbol: 'ETH',
|
|
27
|
+
nativeDecimals: 18,
|
|
28
|
+
blockExplorer: 'https://etherscan.io',
|
|
29
|
+
tokens: [
|
|
30
|
+
{ symbol: 'USDC', address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', decimals: 6 },
|
|
31
|
+
{ symbol: 'USDT', address: '0xdAC17F958D2ee523a2206206994597C13D831ec7', decimals: 6 },
|
|
32
|
+
{ symbol: 'UNI', address: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', decimals: 18 },
|
|
33
|
+
{ symbol: 'LINK', address: '0x514910771AF9Ca656af840dff83E8264EcF986CA', decimals: 18 },
|
|
34
|
+
{ symbol: 'stETH', address: '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84', decimals: 18 },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
polygon: {
|
|
39
|
+
name: 'Polygon Mainnet',
|
|
40
|
+
chainType: 'evm',
|
|
41
|
+
chainId: 137,
|
|
42
|
+
rpcUrl: process.env.RPC_URL_POLYGON || 'https://polygon.llamarpc.com',
|
|
43
|
+
nativeSymbol: 'MATIC',
|
|
44
|
+
nativeDecimals: 18,
|
|
45
|
+
blockExplorer: 'https://polygonscan.com',
|
|
46
|
+
tokens: [
|
|
47
|
+
{ symbol: 'USDC', address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', decimals: 6 },
|
|
48
|
+
{ symbol: 'USDT', address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', decimals: 6 },
|
|
49
|
+
{ symbol: 'WETH', address: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', decimals: 18 },
|
|
50
|
+
{ symbol: 'LINK', address: '0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39', decimals: 18 },
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
sepolia: {
|
|
55
|
+
name: 'Sepolia Testnet',
|
|
56
|
+
chainType: 'evm',
|
|
57
|
+
chainId: 11155111,
|
|
58
|
+
rpcUrl: process.env.RPC_URL_SEPOLIA || 'https://rpc.sepolia.org',
|
|
59
|
+
nativeSymbol: 'ETH',
|
|
60
|
+
nativeDecimals: 18,
|
|
61
|
+
blockExplorer: 'https://sepolia.etherscan.io',
|
|
62
|
+
tokens: [
|
|
63
|
+
{ symbol: 'LINK', address: '0x779877A7B0D9E8603169DdbD7836e478b4624789', decimals: 18 },
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
// ==========================================================================
|
|
68
|
+
// Layer 2 Networks
|
|
69
|
+
// ==========================================================================
|
|
70
|
+
|
|
71
|
+
base: {
|
|
72
|
+
name: 'Base',
|
|
73
|
+
chainType: 'evm',
|
|
74
|
+
chainId: 8453,
|
|
75
|
+
rpcUrl: process.env.RPC_URL_BASE || 'https://mainnet.base.org',
|
|
76
|
+
nativeSymbol: 'ETH',
|
|
77
|
+
nativeDecimals: 18,
|
|
78
|
+
blockExplorer: 'https://basescan.org',
|
|
79
|
+
tokens: [
|
|
80
|
+
{ symbol: 'USDC', address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', decimals: 6 },
|
|
81
|
+
{ symbol: 'USDbC', address: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA', decimals: 6 },
|
|
82
|
+
{ symbol: 'cbETH', address: '0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22', decimals: 18 },
|
|
83
|
+
{ symbol: 'DAI', address: '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', decimals: 18 },
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
arbitrum: {
|
|
88
|
+
name: 'Arbitrum One',
|
|
89
|
+
chainType: 'evm',
|
|
90
|
+
chainId: 42161,
|
|
91
|
+
rpcUrl: process.env.RPC_URL_ARBITRUM || 'https://arb1.arbitrum.io/rpc',
|
|
92
|
+
nativeSymbol: 'ETH',
|
|
93
|
+
nativeDecimals: 18,
|
|
94
|
+
blockExplorer: 'https://arbiscan.io',
|
|
95
|
+
tokens: [
|
|
96
|
+
{ symbol: 'USDC', address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', decimals: 6 },
|
|
97
|
+
{ symbol: 'USDT', address: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', decimals: 6 },
|
|
98
|
+
{ symbol: 'ARB', address: '0x912CE59144191C1204E64559FE8253a0e49E6548', decimals: 18 },
|
|
99
|
+
{ symbol: 'GMX', address: '0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a', decimals: 18 },
|
|
100
|
+
{ symbol: 'WETH', address: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', decimals: 18 },
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
optimism: {
|
|
105
|
+
name: 'Optimism',
|
|
106
|
+
chainType: 'evm',
|
|
107
|
+
chainId: 10,
|
|
108
|
+
rpcUrl: process.env.RPC_URL_OPTIMISM || 'https://mainnet.optimism.io',
|
|
109
|
+
nativeSymbol: 'ETH',
|
|
110
|
+
nativeDecimals: 18,
|
|
111
|
+
blockExplorer: 'https://optimistic.etherscan.io',
|
|
112
|
+
tokens: [
|
|
113
|
+
{ symbol: 'USDC', address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', decimals: 6 },
|
|
114
|
+
{ symbol: 'USDT', address: '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58', decimals: 6 },
|
|
115
|
+
{ symbol: 'OP', address: '0x4200000000000000000000000000000000000042', decimals: 18 },
|
|
116
|
+
{ symbol: 'SNX', address: '0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4', decimals: 18 },
|
|
117
|
+
{ symbol: 'WETH', address: '0x4200000000000000000000000000000000000006', decimals: 18 },
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
// ==========================================================================
|
|
122
|
+
// Solana Networks
|
|
123
|
+
// ==========================================================================
|
|
124
|
+
|
|
125
|
+
solana: {
|
|
126
|
+
name: 'Solana Mainnet',
|
|
127
|
+
chainType: 'solana',
|
|
128
|
+
chainId: null,
|
|
129
|
+
rpcUrl: process.env.RPC_URL_SOLANA || 'https://api.mainnet-beta.solana.com',
|
|
130
|
+
nativeSymbol: 'SOL',
|
|
131
|
+
nativeDecimals: 9,
|
|
132
|
+
blockExplorer: 'https://explorer.solana.com',
|
|
133
|
+
tokens: [
|
|
134
|
+
// Popular Solana SPL tokens
|
|
135
|
+
{ symbol: 'USDC', mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', decimals: 6 },
|
|
136
|
+
{ symbol: 'BONK', mint: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263', decimals: 5 },
|
|
137
|
+
{ symbol: 'JUP', mint: 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN', decimals: 6 },
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Helium Network (on Solana)
|
|
143
|
+
*
|
|
144
|
+
* Helium migrated from its own L1 to Solana in April 2023.
|
|
145
|
+
* The HNT, MOBILE, and IOT tokens are now SPL tokens on Solana.
|
|
146
|
+
*
|
|
147
|
+
* For Nebra hotspot operators, this enables:
|
|
148
|
+
* - Tracking mining rewards over time
|
|
149
|
+
* - Monitoring HNT/MOBILE/IOT earning rates
|
|
150
|
+
* - Correlating rewards with network coverage data
|
|
151
|
+
*
|
|
152
|
+
* @see https://docs.helium.com/solana/
|
|
153
|
+
* @see https://github.com/helium/helium-program-library
|
|
154
|
+
*/
|
|
155
|
+
helium: {
|
|
156
|
+
name: 'Helium (Solana)',
|
|
157
|
+
chainType: 'solana',
|
|
158
|
+
chainId: null,
|
|
159
|
+
rpcUrl: process.env.RPC_URL_SOLANA || 'https://api.mainnet-beta.solana.com',
|
|
160
|
+
nativeSymbol: 'SOL', // Native is still SOL, HNT is a token
|
|
161
|
+
nativeDecimals: 9,
|
|
162
|
+
blockExplorer: 'https://explorer.solana.com',
|
|
163
|
+
// Helium ecosystem tokens
|
|
164
|
+
tokens: [
|
|
165
|
+
{ symbol: 'HNT', mint: 'hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux', decimals: 8 },
|
|
166
|
+
{ symbol: 'MOBILE', mint: 'mb1eu7TzEc71KxDpsmsKoucSSuuoGLv1drys1oP2jh6', decimals: 6 },
|
|
167
|
+
{ symbol: 'IOT', mint: 'iotEVVZLEywoTn1QdwNPddxPWszn3zFhEot3MfL9fns', decimals: 6 },
|
|
168
|
+
{ symbol: 'DC', mint: 'dcuc8Amr83Wz27ZkQ2K9NS6r8zRpf1J6cvArEBDZDmm', decimals: 0 }, // Data Credits
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
'solana-devnet': {
|
|
173
|
+
name: 'Solana Devnet',
|
|
174
|
+
chainType: 'solana',
|
|
175
|
+
chainId: null,
|
|
176
|
+
rpcUrl: process.env.RPC_URL_SOLANA_DEVNET || 'https://api.devnet.solana.com',
|
|
177
|
+
nativeSymbol: 'SOL',
|
|
178
|
+
nativeDecimals: 9,
|
|
179
|
+
blockExplorer: 'https://explorer.solana.com',
|
|
180
|
+
tokens: [],
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// ==========================================================================
|
|
185
|
+
// Helper Functions
|
|
186
|
+
// ==========================================================================
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Get network configuration by key.
|
|
190
|
+
* @param {string} networkKey - Network identifier
|
|
191
|
+
* @returns {object|null} Network config or null if not found
|
|
192
|
+
*/
|
|
193
|
+
function getNetwork(networkKey) {
|
|
194
|
+
const key = networkKey.toLowerCase();
|
|
195
|
+
return networks[key] || null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Get list of all network keys.
|
|
200
|
+
* @returns {string[]}
|
|
201
|
+
*/
|
|
202
|
+
function getSupportedNetworks() {
|
|
203
|
+
return Object.keys(networks);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Get networks filtered by chain type.
|
|
208
|
+
* @param {string} chainType - 'evm' or 'solana'
|
|
209
|
+
* @returns {string[]} Network keys matching the chain type
|
|
210
|
+
*/
|
|
211
|
+
function getNetworksByType(chainType) {
|
|
212
|
+
return Object.keys(networks).filter(
|
|
213
|
+
key => networks[key].chainType === chainType
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Get chain type for a network.
|
|
219
|
+
* @param {string} networkKey - Network key
|
|
220
|
+
* @returns {string|null} Chain type or null
|
|
221
|
+
*/
|
|
222
|
+
function getChainType(networkKey) {
|
|
223
|
+
const network = getNetwork(networkKey);
|
|
224
|
+
return network?.chainType || null;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
module.exports = {
|
|
228
|
+
networks,
|
|
229
|
+
getNetwork,
|
|
230
|
+
getSupportedNetworks,
|
|
231
|
+
getNetworksByType,
|
|
232
|
+
getChainType,
|
|
233
|
+
};
|
|
234
|
+
|