aether-hub 1.2.6 → 1.2.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/commands/account.js +10 -34
- package/commands/balance.js +276 -0
- package/commands/blockhash.js +181 -0
- package/commands/broadcast.js +323 -323
- package/commands/claim.js +292 -0
- package/commands/emergency.js +657 -657
- package/commands/epoch.js +12 -94
- package/commands/fees.js +276 -0
- package/commands/info.js +38 -79
- package/commands/network.js +34 -108
- package/commands/ping.js +11 -65
- package/commands/price.js +253 -253
- package/commands/sdk-test.js +477 -0
- package/commands/stake-info.js +139 -0
- package/commands/status.js +113 -157
- package/commands/supply.js +34 -82
- package/commands/tps.js +238 -0
- package/commands/transfer.js +495 -0
- package/commands/tx-history.js +462 -508
- package/commands/validator-info.js +10 -4
- package/commands/validator-start.js +1 -1
- package/commands/validator-status.js +32 -73
- package/commands/validators.js +36 -75
- package/commands/wallet.js +5 -29
- package/index.js +54 -6
- package/package.json +1 -3
package/commands/status.js
CHANGED
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
* Requires AETHER_RPC env var (default: http://127.0.0.1:8899)
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
const http = require('http');
|
|
19
|
-
const https = require('https');
|
|
20
18
|
const os = require('os');
|
|
19
|
+
const path = require('path');
|
|
21
20
|
|
|
22
21
|
// ANSI colours
|
|
23
22
|
const C = {
|
|
@@ -33,66 +32,20 @@ const C = {
|
|
|
33
32
|
|
|
34
33
|
const CLI_VERSION = '1.0.0';
|
|
35
34
|
|
|
35
|
+
// Import SDK for real blockchain RPC calls
|
|
36
|
+
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
37
|
+
const aether = require(sdkPath);
|
|
38
|
+
|
|
36
39
|
// ---------------------------------------------------------------------------
|
|
37
40
|
// Helpers
|
|
38
41
|
// ---------------------------------------------------------------------------
|
|
39
42
|
|
|
40
43
|
function getDefaultRpc() {
|
|
41
|
-
return process.env.AETHER_RPC || 'http://127.0.0.1:8899';
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function httpRequest(rpcUrl, pathStr, timeoutMs = 10000) {
|
|
45
|
-
return new Promise((resolve, reject) => {
|
|
46
|
-
const url = new URL(pathStr, rpcUrl);
|
|
47
|
-
const lib = url.protocol === 'https:' ? https : http;
|
|
48
|
-
const req = lib.request({
|
|
49
|
-
hostname: url.hostname,
|
|
50
|
-
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
51
|
-
path: url.pathname + url.search,
|
|
52
|
-
method: 'GET',
|
|
53
|
-
timeout: timeoutMs,
|
|
54
|
-
headers: { 'Content-Type': 'application/json' },
|
|
55
|
-
}, (res) => {
|
|
56
|
-
let data = '';
|
|
57
|
-
res.on('data', (chunk) => data += chunk);
|
|
58
|
-
res.on('end', () => {
|
|
59
|
-
try { resolve(JSON.parse(data)); }
|
|
60
|
-
catch { resolve({ raw: data }); }
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
req.on('error', reject);
|
|
64
|
-
req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout after ' + timeoutMs + 'ms')); });
|
|
65
|
-
req.end();
|
|
66
|
-
});
|
|
44
|
+
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
67
45
|
}
|
|
68
46
|
|
|
69
|
-
function
|
|
70
|
-
return new
|
|
71
|
-
const url = new URL(pathStr, rpcUrl);
|
|
72
|
-
const lib = url.protocol === 'https:' ? https : http;
|
|
73
|
-
const bodyStr = JSON.stringify(body);
|
|
74
|
-
const req = lib.request({
|
|
75
|
-
hostname: url.hostname,
|
|
76
|
-
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
77
|
-
path: url.pathname + url.search,
|
|
78
|
-
method: 'POST',
|
|
79
|
-
timeout: timeoutMs,
|
|
80
|
-
headers: {
|
|
81
|
-
'Content-Type': 'application/json',
|
|
82
|
-
'Content-Length': Buffer.byteLength(bodyStr),
|
|
83
|
-
},
|
|
84
|
-
}, (res) => {
|
|
85
|
-
let data = '';
|
|
86
|
-
res.on('data', (chunk) => data += chunk);
|
|
87
|
-
res.on('end', () => {
|
|
88
|
-
try { resolve(JSON.parse(data)); }
|
|
89
|
-
catch { resolve(data); }
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
req.on('error', reject);
|
|
93
|
-
req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout after ' + timeoutMs + 'ms')); });
|
|
94
|
-
req.end();
|
|
95
|
-
});
|
|
47
|
+
function createClient(rpc) {
|
|
48
|
+
return new aether.AetherClient({ rpcUrl: rpc });
|
|
96
49
|
}
|
|
97
50
|
|
|
98
51
|
function formatAether(lamports) {
|
|
@@ -124,7 +77,7 @@ function loadIdentity() {
|
|
|
124
77
|
// ---------------------------------------------------------------------------
|
|
125
78
|
|
|
126
79
|
async function statusCommand() {
|
|
127
|
-
const args = process.argv.slice(
|
|
80
|
+
const args = process.argv.slice(2); // [node, status.js, ...]
|
|
128
81
|
const isJson = args.includes('--json') || args.includes('-j');
|
|
129
82
|
const isCompact = args.includes('--compact');
|
|
130
83
|
const includeValidator = args.includes('--validator');
|
|
@@ -168,130 +121,133 @@ async function statusCommand() {
|
|
|
168
121
|
return;
|
|
169
122
|
}
|
|
170
123
|
|
|
171
|
-
printDashboard(data, errors, includeValidator);
|
|
124
|
+
printDashboard(data, errors, includeValidator, rpc);
|
|
172
125
|
}
|
|
173
126
|
|
|
174
127
|
async function fetchEpochInfo(rpc) {
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
128
|
+
const client = createClient(rpc);
|
|
129
|
+
try {
|
|
130
|
+
const epoch = await client.getEpochInfo();
|
|
131
|
+
const currentSlot = epoch.absoluteSlot || epoch.slot || 0;
|
|
132
|
+
const slotsInEpoch = epoch.slotsInEpoch || 432000;
|
|
133
|
+
const slotIndex = epoch.slotIndex || (currentSlot % slotsInEpoch);
|
|
134
|
+
const epochProgress = slotsInEpoch > 0 ? (slotIndex / slotsInEpoch * 100).toFixed(1) : '0';
|
|
135
|
+
|
|
136
|
+
// Estimate time remaining (assuming 400ms slots)
|
|
137
|
+
const slotsRemaining = slotsInEpoch - slotIndex;
|
|
138
|
+
const secsRemaining = Math.round(slotsRemaining * 0.4);
|
|
139
|
+
const minsRemaining = Math.round(secsRemaining / 60);
|
|
140
|
+
const timeStr = minsRemaining >= 60
|
|
141
|
+
? `${Math.floor(minsRemaining / 60)}h ${minsRemaining % 60}m`
|
|
142
|
+
: `${minsRemaining}m`;
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
epoch: epoch.epoch || 0,
|
|
146
|
+
absoluteSlot: currentSlot,
|
|
147
|
+
slotIndex,
|
|
148
|
+
slotsInEpoch,
|
|
149
|
+
progress: epochProgress,
|
|
150
|
+
timeRemaining: timeStr,
|
|
151
|
+
totalSlots: epoch.totalSlots || 0,
|
|
152
|
+
};
|
|
153
|
+
} catch (e) {
|
|
154
|
+
throw new Error('Epoch info fetch failed: ' + e.message);
|
|
155
|
+
}
|
|
203
156
|
}
|
|
204
157
|
|
|
205
158
|
async function fetchSupplyInfo(rpc) {
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
159
|
+
const client = createClient(rpc);
|
|
160
|
+
try {
|
|
161
|
+
const supply = await client.getSupply();
|
|
162
|
+
const total = BigInt(supply.total || 0);
|
|
163
|
+
const circulating = BigInt(supply.circulating || 0);
|
|
164
|
+
const nonCirculating = BigInt(supply.nonCirculating || 0);
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
total: total.toString(),
|
|
168
|
+
totalFormatted: formatAether(total.toString()),
|
|
169
|
+
circulating: circulating.toString(),
|
|
170
|
+
circulatingFormatted: formatAether(circulating.toString()),
|
|
171
|
+
nonCirculating: nonCirculating.toString(),
|
|
172
|
+
nonCirculatingFormatted: formatAether(nonCirculating.toString()),
|
|
173
|
+
};
|
|
174
|
+
} catch (e) {
|
|
175
|
+
throw new Error('Supply info fetch failed: ' + e.message);
|
|
176
|
+
}
|
|
220
177
|
}
|
|
221
178
|
|
|
222
179
|
async function fetchNetworkInfo(rpc) {
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
180
|
+
const client = createClient(rpc);
|
|
181
|
+
try {
|
|
182
|
+
const [slot, blockHeight, peers] = await Promise.all([
|
|
183
|
+
client.getSlot(),
|
|
184
|
+
client.getBlockHeight(),
|
|
185
|
+
client.getClusterPeers(),
|
|
186
|
+
]);
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
blockHeight: blockHeight || slot || 0,
|
|
190
|
+
blockTime: null,
|
|
191
|
+
peerCount: Array.isArray(peers) ? peers.length : 0,
|
|
192
|
+
peers: (Array.isArray(peers) ? peers : []).slice(0, 5),
|
|
193
|
+
};
|
|
194
|
+
} catch (e) {
|
|
195
|
+
throw new Error('Network info fetch failed: ' + e.message);
|
|
196
|
+
}
|
|
239
197
|
}
|
|
240
198
|
|
|
241
199
|
async function fetchVersionInfo(rpc) {
|
|
200
|
+
const client = createClient(rpc);
|
|
242
201
|
try {
|
|
243
|
-
|
|
244
|
-
return resp?.result || {};
|
|
202
|
+
return await client.getVersion();
|
|
245
203
|
} catch {
|
|
246
204
|
return {};
|
|
247
205
|
}
|
|
248
206
|
}
|
|
249
207
|
|
|
250
208
|
async function fetchRewardsSummary(rpc, address) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
total += BigInt(r.estimatedReward || 0);
|
|
209
|
+
const client = createClient(rpc);
|
|
210
|
+
try {
|
|
211
|
+
// Get stake positions for the address (real RPC call via SDK)
|
|
212
|
+
const stakePositions = await client.getStakePositions(address);
|
|
213
|
+
|
|
214
|
+
if (!stakePositions || stakePositions.length === 0) return null;
|
|
215
|
+
|
|
216
|
+
const rewardsResults = await Promise.all(
|
|
217
|
+
stakePositions.slice(0, 10).map(async (stake) => {
|
|
218
|
+
try {
|
|
219
|
+
const stakeAccount = stake.stakeAccount || stake.account || stake.pubkey || stake;
|
|
220
|
+
const rewards = await client.getRewards(stakeAccount);
|
|
221
|
+
const total = BigInt(rewards.total || rewards.amount || 0);
|
|
222
|
+
return {
|
|
223
|
+
stakeAccount,
|
|
224
|
+
estimatedRewards: total.toString(),
|
|
225
|
+
estimatedRewardsFormatted: formatAether(total.toString())
|
|
226
|
+
};
|
|
227
|
+
} catch {
|
|
228
|
+
return { stakeAccount: stake.stakeAccount || stake, estimatedRewards: '0', estimatedRewardsFormatted: '0 AETH' };
|
|
272
229
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
let totalRewards = BigInt(0);
|
|
281
|
-
for (const r of rewardsResults) {
|
|
282
|
-
totalRewards += BigInt(r.estimatedRewards);
|
|
283
|
-
}
|
|
230
|
+
})
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
let totalRewards = BigInt(0);
|
|
234
|
+
for (const r of rewardsResults) {
|
|
235
|
+
totalRewards += BigInt(r.estimatedRewards);
|
|
236
|
+
}
|
|
284
237
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
238
|
+
return {
|
|
239
|
+
address,
|
|
240
|
+
totalRewards: totalRewards.toString(),
|
|
241
|
+
totalRewardsFormatted: formatAether(totalRewards.toString()),
|
|
242
|
+
activeAccounts: rewardsResults.filter(r => BigInt(r.estimatedRewards) > 0n).length,
|
|
243
|
+
totalAccounts: rewardsResults.length,
|
|
244
|
+
};
|
|
245
|
+
} catch (e) {
|
|
246
|
+
throw new Error('Rewards fetch failed: ' + e.message);
|
|
247
|
+
}
|
|
292
248
|
}
|
|
293
249
|
|
|
294
|
-
function printDashboard(data, errors, includeValidator) {
|
|
250
|
+
function printDashboard(data, errors, includeValidator, rpc) {
|
|
295
251
|
const { epoch, supply, network, version, validator, rewards, defaultWallet } = data;
|
|
296
252
|
|
|
297
253
|
console.log(`\n${C.bright}${C.cyan} ╔══════════════════════════════════════════════════════════╗${C.reset}`);
|
package/commands/supply.js
CHANGED
|
@@ -17,8 +17,7 @@
|
|
|
17
17
|
* Requires AETHER_RPC env var (default: http://127.0.0.1:8899)
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
const
|
|
21
|
-
const https = require('https');
|
|
20
|
+
const path = require('path');
|
|
22
21
|
|
|
23
22
|
// ANSI colours
|
|
24
23
|
const C = {
|
|
@@ -36,63 +35,19 @@ const C = {
|
|
|
36
35
|
const CLI_VERSION = '1.0.0';
|
|
37
36
|
|
|
38
37
|
// ---------------------------------------------------------------------------
|
|
39
|
-
//
|
|
38
|
+
// SDK Import - Real blockchain RPC calls via @jellylegsai/aether-sdk
|
|
40
39
|
// ---------------------------------------------------------------------------
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
41
|
+
const sdkPath = path.join(__dirname, '..', 'sdk', 'index.js');
|
|
42
|
+
const aether = require(sdkPath);
|
|
45
43
|
|
|
46
|
-
function
|
|
47
|
-
return
|
|
48
|
-
const url = new URL(pathStr, rpcUrl);
|
|
49
|
-
const lib = url.protocol === 'https:' ? https : http;
|
|
50
|
-
const req = lib.request({
|
|
51
|
-
hostname: url.hostname,
|
|
52
|
-
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
53
|
-
path: url.pathname + url.search,
|
|
54
|
-
method: 'GET',
|
|
55
|
-
timeout: timeoutMs,
|
|
56
|
-
headers: { 'Content-Type': 'application/json' },
|
|
57
|
-
}, (res) => {
|
|
58
|
-
let data = '';
|
|
59
|
-
res.on('data', (chunk) => data += chunk);
|
|
60
|
-
res.on('end', () => {
|
|
61
|
-
try { resolve(JSON.parse(data)); }
|
|
62
|
-
catch { resolve({ raw: data }); }
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
req.on('error', reject);
|
|
66
|
-
req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout after ' + timeoutMs + 'ms')); });
|
|
67
|
-
req.end();
|
|
68
|
-
});
|
|
44
|
+
function getDefaultRpc() {
|
|
45
|
+
return process.env.AETHER_RPC || aether.DEFAULT_RPC_URL || 'http://127.0.0.1:8899';
|
|
69
46
|
}
|
|
70
47
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const lib = url.protocol === 'https:' ? https : http;
|
|
75
|
-
const bodyStr = JSON.stringify(body);
|
|
76
|
-
const req = lib.request({
|
|
77
|
-
hostname: url.hostname,
|
|
78
|
-
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
79
|
-
path: url.pathname + url.search,
|
|
80
|
-
method: 'POST',
|
|
81
|
-
timeout: timeoutMs,
|
|
82
|
-
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(bodyStr) },
|
|
83
|
-
}, (res) => {
|
|
84
|
-
let data = '';
|
|
85
|
-
res.on('data', (chunk) => data += chunk);
|
|
86
|
-
res.on('end', () => {
|
|
87
|
-
try { resolve(JSON.parse(data)); }
|
|
88
|
-
catch { resolve({ raw: data }); }
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
req.on('error', reject);
|
|
92
|
-
req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout after ' + timeoutMs + 'ms')); });
|
|
93
|
-
req.write(bodyStr);
|
|
94
|
-
req.end();
|
|
95
|
-
});
|
|
48
|
+
/** Create SDK client */
|
|
49
|
+
function createClient(rpcUrl) {
|
|
50
|
+
return new aether.AetherClient({ rpcUrl });
|
|
96
51
|
}
|
|
97
52
|
|
|
98
53
|
function formatAether(lamports) {
|
|
@@ -110,22 +65,23 @@ function formatLargeNum(n) {
|
|
|
110
65
|
}
|
|
111
66
|
|
|
112
67
|
// ---------------------------------------------------------------------------
|
|
113
|
-
// Core supply fetchers
|
|
68
|
+
// Core supply fetchers using SDK
|
|
114
69
|
// ---------------------------------------------------------------------------
|
|
115
70
|
|
|
116
71
|
/**
|
|
117
|
-
* Fetch the total supply of AETH from the chain.
|
|
118
|
-
*
|
|
72
|
+
* Fetch the total supply of AETH from the chain using SDK.
|
|
73
|
+
* Makes real RPC call: GET /v1/supply
|
|
119
74
|
*/
|
|
120
75
|
async function fetchTotalSupply(rpc) {
|
|
76
|
+
const client = createClient(rpc);
|
|
121
77
|
try {
|
|
122
|
-
// Primary:
|
|
123
|
-
const res = await
|
|
124
|
-
if (res &&
|
|
78
|
+
// Primary: SDK getSupply() → GET /v1/supply
|
|
79
|
+
const res = await client.getSupply();
|
|
80
|
+
if (res && (res.total !== undefined || res.supply !== undefined)) {
|
|
125
81
|
return {
|
|
126
82
|
total: BigInt(res.total || res.supply?.total || 0),
|
|
127
83
|
circulating: BigInt(res.circulating || res.supply?.circulating || 0),
|
|
128
|
-
nonCirculating: BigInt(res.non_circulating || res.supply?.non_circulating || 0),
|
|
84
|
+
nonCirculating: BigInt(res.non_circulating || res.nonCirculating || res.supply?.non_circulating || 0),
|
|
129
85
|
source: 'rpc_v1_supply',
|
|
130
86
|
};
|
|
131
87
|
}
|
|
@@ -133,8 +89,8 @@ async function fetchTotalSupply(rpc) {
|
|
|
133
89
|
|
|
134
90
|
// Fallback: fetch epoch info which contains total token count
|
|
135
91
|
try {
|
|
136
|
-
const epochInfo = await
|
|
137
|
-
if (epochInfo
|
|
92
|
+
const epochInfo = await client.getEpochInfo();
|
|
93
|
+
if (epochInfo) {
|
|
138
94
|
const totalStaked = BigInt(epochInfo.total_staked || 0);
|
|
139
95
|
const rewardsPerEpoch = BigInt(epochInfo.rewards_per_epoch || '2000000000');
|
|
140
96
|
const currentEpoch = BigInt(epochInfo.epoch || 0);
|
|
@@ -159,33 +115,27 @@ async function fetchTotalSupply(rpc) {
|
|
|
159
115
|
}
|
|
160
116
|
|
|
161
117
|
/**
|
|
162
|
-
* Fetch staked supply by querying stake program accounts.
|
|
118
|
+
* Fetch staked supply by querying stake program accounts using SDK.
|
|
119
|
+
* Makes real RPC call: GET /v1/validators
|
|
163
120
|
*/
|
|
164
121
|
async function fetchStakedSupply(rpc) {
|
|
122
|
+
const client = createClient(rpc);
|
|
165
123
|
try {
|
|
166
|
-
//
|
|
167
|
-
const
|
|
168
|
-
if (res && !res.error && res.total_staked !== undefined) {
|
|
169
|
-
return BigInt(res.total_staked);
|
|
170
|
-
}
|
|
171
|
-
} catch { /* fall through */ }
|
|
172
|
-
|
|
173
|
-
try {
|
|
174
|
-
// Fallback: sum delegated stake across top validators
|
|
175
|
-
const validators = await httpRequest(rpc, '/v1/validators?limit=50');
|
|
124
|
+
// SDK getValidators() → GET /v1/validators
|
|
125
|
+
const validators = await client.getValidators();
|
|
176
126
|
if (validators && Array.isArray(validators)) {
|
|
177
127
|
let total = BigInt(0);
|
|
178
128
|
for (const v of validators) {
|
|
179
|
-
total += BigInt(v.delegated_stake || v.stake || 0);
|
|
129
|
+
total += BigInt(v.delegated_stake || v.stake || v.delegatedStake || 0);
|
|
180
130
|
}
|
|
181
131
|
return total;
|
|
182
132
|
}
|
|
183
133
|
} catch { /* fall through */ }
|
|
184
134
|
|
|
185
135
|
try {
|
|
186
|
-
// Last resort: epoch info staked amount
|
|
187
|
-
const epochInfo = await
|
|
188
|
-
if (epochInfo &&
|
|
136
|
+
// Last resort: epoch info staked amount via SDK
|
|
137
|
+
const epochInfo = await client.getEpochInfo();
|
|
138
|
+
if (epochInfo && epochInfo.total_staked) {
|
|
189
139
|
return BigInt(epochInfo.total_staked);
|
|
190
140
|
}
|
|
191
141
|
} catch { /* fall through */ }
|
|
@@ -194,10 +144,11 @@ async function fetchStakedSupply(rpc) {
|
|
|
194
144
|
}
|
|
195
145
|
|
|
196
146
|
/**
|
|
197
|
-
* Estimate burned supply by querying accounts at known burn/mint addresses.
|
|
198
|
-
*
|
|
147
|
+
* Estimate burned supply by querying accounts at known burn/mint addresses using SDK.
|
|
148
|
+
* Makes real RPC calls: GET /v1/account/<address>
|
|
199
149
|
*/
|
|
200
150
|
async function fetchBurnedSupply(rpc) {
|
|
151
|
+
const client = createClient(rpc);
|
|
201
152
|
const BURN_ADDRESSES = [
|
|
202
153
|
'ATH1111111111111111111111111111111111111', // mint authority burn
|
|
203
154
|
'ATH2222222222222222222222222222222222222', // zero authority
|
|
@@ -209,8 +160,9 @@ async function fetchBurnedSupply(rpc) {
|
|
|
209
160
|
for (const addr of BURN_ADDRESSES) {
|
|
210
161
|
try {
|
|
211
162
|
const rawAddr = addr.startsWith('ATH') ? addr.slice(3) : addr;
|
|
212
|
-
|
|
213
|
-
|
|
163
|
+
// SDK getAccountInfo() → GET /v1/account/<address>
|
|
164
|
+
const account = await client.getAccountInfo(rawAddr);
|
|
165
|
+
if (account && account.lamports !== undefined && Number(account.lamports) > 0) {
|
|
214
166
|
totalBurned += BigInt(account.lamports);
|
|
215
167
|
}
|
|
216
168
|
} catch { /* skip inaccessible addresses */ }
|