@ar.io/sdk 4.0.0-solana.7 → 4.0.0-solana.8
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/lib/esm/solana/constants.js +6 -0
- package/lib/esm/solana/delegation-math.js +63 -0
- package/lib/esm/solana/deserialize.js +38 -8
- package/lib/esm/solana/io-readable.js +85 -19
- package/lib/esm/version.js +1 -1
- package/lib/types/solana/constants.d.ts +6 -0
- package/lib/types/solana/delegation-math.d.ts +20 -0
- package/lib/types/solana/deserialize.d.ts +34 -2
- package/lib/types/solana/io-readable.d.ts +11 -0
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -16,6 +16,12 @@ export const MPL_CORE_PROGRAM_ID = address('CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH
|
|
|
16
16
|
export const TOKEN_DECIMALS = 6;
|
|
17
17
|
export const ONE_TOKEN = 1_000_000; // 1 ARIO = 1,000,000 mARIO
|
|
18
18
|
export const RATE_SCALE = 1_000_000;
|
|
19
|
+
/**
|
|
20
|
+
* Scaling factor for the per-share reward accumulator
|
|
21
|
+
* `Gateway.cumulative_reward_per_token` in `ario-gar`. Must match the
|
|
22
|
+
* `REWARD_PRECISION` constant in `programs/ario-gar/src/state/mod.rs`.
|
|
23
|
+
*/
|
|
24
|
+
export const REWARD_PRECISION = 1000000000000000000n; // 1e18
|
|
19
25
|
// =========================================
|
|
20
26
|
// PDA Seeds — ario-core
|
|
21
27
|
// =========================================
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegation balance math.
|
|
3
|
+
*
|
|
4
|
+
* On-chain, `Delegation.amount` is the last-settled principal. Pending rewards
|
|
5
|
+
* are tracked separately via the gateway's per-share accumulator
|
|
6
|
+
* (`Gateway.cumulative_reward_per_token`) and the delegate's snapshot of that
|
|
7
|
+
* accumulator at the last settlement (`Delegation.reward_debt`). The
|
|
8
|
+
* `distribute_epoch` instruction advances the accumulator but does NOT touch
|
|
9
|
+
* per-`Delegation.amount` — that field is updated lazily on the next
|
|
10
|
+
* delegation interaction (or via the permissionless
|
|
11
|
+
* `compound_delegation_rewards` instruction).
|
|
12
|
+
*
|
|
13
|
+
* Off-chain readers (indexers, wallets, the network portal) that want to show
|
|
14
|
+
* a delegate's current balance must therefore compute the live value from the
|
|
15
|
+
* accumulator + reward_debt; reading `Delegation.amount` directly under-reports
|
|
16
|
+
* every epoch of pending rewards.
|
|
17
|
+
*
|
|
18
|
+
* This module mirrors the on-chain `settle_delegate_rewards` math from
|
|
19
|
+
* `programs/ario-gar/src/state/mod.rs` so the SDK can return live values from
|
|
20
|
+
* its read-side methods (`getGatewayDelegates`, `getDelegations`,
|
|
21
|
+
* `getAllDelegates`) without needing an on-chain settlement call.
|
|
22
|
+
*
|
|
23
|
+
* See `INVARIANTS.md` in the contracts repo for the broader stake-pool
|
|
24
|
+
* invariant context.
|
|
25
|
+
*/
|
|
26
|
+
import { REWARD_PRECISION } from './constants.js';
|
|
27
|
+
const U64_MAX = (1n << 64n) - 1n;
|
|
28
|
+
/**
|
|
29
|
+
* Compute the live delegation balance: the last-settled principal plus any
|
|
30
|
+
* pending rewards accrued since the last settlement.
|
|
31
|
+
*
|
|
32
|
+
* Mirrors `settle_delegate_rewards` in
|
|
33
|
+
* `programs/ario-gar/src/state/mod.rs` — including the u128 overflow-safe
|
|
34
|
+
* quotient/remainder split and the saturating-to-`u64::MAX` cap at the end —
|
|
35
|
+
* so a value computed here matches what the on-chain instruction would write
|
|
36
|
+
* if it were called right now.
|
|
37
|
+
*
|
|
38
|
+
* @param delegatedStake - `Delegation.amount` (u64 → number).
|
|
39
|
+
* @param rewardDebt - `Delegation.reward_debt` (u128 → bigint).
|
|
40
|
+
* @param cumulativeRewardPerToken - `Gateway.cumulative_reward_per_token` (u128 → bigint).
|
|
41
|
+
* @returns The delegate's live balance in mARIO, saturating-capped at `u64::MAX`.
|
|
42
|
+
*/
|
|
43
|
+
export function computeLiveDelegationBalance({ delegatedStake, rewardDebt, cumulativeRewardPerToken, }) {
|
|
44
|
+
// Fast paths matching the on-chain `if` guards: zero principal or no
|
|
45
|
+
// accumulator delta means no pending rewards to settle.
|
|
46
|
+
if (delegatedStake <= 0 || cumulativeRewardPerToken <= rewardDebt) {
|
|
47
|
+
return delegatedStake;
|
|
48
|
+
}
|
|
49
|
+
const amount = BigInt(delegatedStake);
|
|
50
|
+
const delta = cumulativeRewardPerToken - rewardDebt;
|
|
51
|
+
// Quotient / remainder split mirrors the on-chain `checked_mul ... unwrap_or_else`
|
|
52
|
+
// fallback. BigInt has no native overflow, so we always take the split path
|
|
53
|
+
// for parity; the result is identical either way.
|
|
54
|
+
const quot = delta / REWARD_PRECISION;
|
|
55
|
+
const rem = delta % REWARD_PRECISION;
|
|
56
|
+
const fromQuot = amount * quot; // saturating not needed — BigInt is unbounded
|
|
57
|
+
const fromRem = (amount * rem) / REWARD_PRECISION;
|
|
58
|
+
const pending = fromQuot + fromRem;
|
|
59
|
+
// Saturating cap at u64::MAX to match the on-chain `u64::try_from(...).unwrap_or(u64::MAX)`.
|
|
60
|
+
const live = amount + pending;
|
|
61
|
+
const capped = live > U64_MAX ? U64_MAX : live;
|
|
62
|
+
return Number(capped);
|
|
63
|
+
}
|
|
@@ -281,12 +281,18 @@ function scaleToFloat(value, scale = RATE_SCALE) {
|
|
|
281
281
|
// Gateway deserialization
|
|
282
282
|
// =========================================
|
|
283
283
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
284
|
+
* Internal variant of {@link deserializeGateway} that additionally surfaces
|
|
285
|
+
* the on-chain `cumulative_reward_per_token` u128 accumulator. Used by the
|
|
286
|
+
* live delegation balance pipeline ({@link computeLiveDelegationBalance} via
|
|
287
|
+
* `getGatewayAccumulators` in `io-readable.ts`).
|
|
288
|
+
*
|
|
289
|
+
* Not part of the public AoGateway shape — `bigint` is not JSON-serializable
|
|
290
|
+
* and would leak through `getGateway` / `getGateways`. Prefer
|
|
291
|
+
* {@link deserializeGateway} everywhere except inside live-balance plumbing.
|
|
286
292
|
*
|
|
287
|
-
*
|
|
293
|
+
* PDA: ["gateway", operator_pubkey] in ario-gar program.
|
|
288
294
|
*/
|
|
289
|
-
export function
|
|
295
|
+
export function deserializeGatewayWithAccumulator(data) {
|
|
290
296
|
const r = new BorshReader(data, 8); // skip 8-byte discriminator
|
|
291
297
|
const operator = r.readPubkey();
|
|
292
298
|
const label = r.readString();
|
|
@@ -329,8 +335,12 @@ export function deserializeGateway(data) {
|
|
|
329
335
|
r.readU8(); // _reserved (layout-preserving placeholder for the legacy is_registered byte)
|
|
330
336
|
// observer_address
|
|
331
337
|
const observerAddress = r.readPubkey();
|
|
332
|
-
// cumulative_reward_per_token
|
|
333
|
-
|
|
338
|
+
// cumulative_reward_per_token: u128 — per-share accumulator advanced by
|
|
339
|
+
// distribute_epoch. Combined with each Delegation.reward_debt, this lets
|
|
340
|
+
// off-chain readers compute the live delegate balance without an on-chain
|
|
341
|
+
// settlement call. Not part of the public AoGateway type but surfaced as
|
|
342
|
+
// an extra field on this function's return so internal readers can use it.
|
|
343
|
+
const cumulativeRewardPerToken = r.readU128();
|
|
334
344
|
// bump
|
|
335
345
|
r.skip(1);
|
|
336
346
|
const stats = {
|
|
@@ -378,8 +388,24 @@ export function deserializeGateway(data) {
|
|
|
378
388
|
operatorStake,
|
|
379
389
|
status: statusIdx === 0 ? 'joined' : 'leaving',
|
|
380
390
|
weights,
|
|
391
|
+
cumulativeRewardPerToken,
|
|
381
392
|
};
|
|
382
393
|
}
|
|
394
|
+
/**
|
|
395
|
+
* Deserialize a Gateway account from raw bytes.
|
|
396
|
+
*
|
|
397
|
+
* Returns the SDK-compatible AoGateway type (plus `operator: string`).
|
|
398
|
+
* The on-chain `cumulative_reward_per_token` u128 is intentionally NOT
|
|
399
|
+
* surfaced on the returned object — `bigint` is not JSON-serializable,
|
|
400
|
+
* and leaking it through `getGateway` / `getGateways` would break
|
|
401
|
+
* downstream consumers that call `JSON.stringify` on results. Use
|
|
402
|
+
* {@link deserializeGatewayWithAccumulator} from within the live-balance
|
|
403
|
+
* pipeline when the accumulator value is actually needed.
|
|
404
|
+
*/
|
|
405
|
+
export function deserializeGateway(data) {
|
|
406
|
+
const { cumulativeRewardPerToken: _unused, ...publicShape } = deserializeGatewayWithAccumulator(data);
|
|
407
|
+
return publicShape;
|
|
408
|
+
}
|
|
383
409
|
// =========================================
|
|
384
410
|
// ArNS Record deserialization
|
|
385
411
|
// =========================================
|
|
@@ -477,13 +503,17 @@ export function deserializeDelegation(data) {
|
|
|
477
503
|
const delegator = r.readPubkey();
|
|
478
504
|
const amount = r.readU64AsNumber();
|
|
479
505
|
const startTimestamp = r.readI64AsNumber();
|
|
480
|
-
// reward_debt: u128
|
|
481
|
-
|
|
506
|
+
// reward_debt: u128 — snapshot of gateway.cumulative_reward_per_token at last
|
|
507
|
+
// settlement. Needed (together with the gateway's current accumulator) to
|
|
508
|
+
// compute the live delegate balance via computeLiveDelegationBalance().
|
|
509
|
+
const rewardDebt = r.readU128();
|
|
510
|
+
r.skip(1); // bump
|
|
482
511
|
return {
|
|
483
512
|
gateway: gateway,
|
|
484
513
|
delegator: delegator,
|
|
485
514
|
delegatedStake: amount,
|
|
486
515
|
startTimestamp,
|
|
516
|
+
rewardDebt,
|
|
487
517
|
};
|
|
488
518
|
}
|
|
489
519
|
// =========================================
|
|
@@ -14,7 +14,8 @@ import { Logger } from '../common/logger.js';
|
|
|
14
14
|
import { SolanaANTRegistryReadable } from './ant-registry-readable.js';
|
|
15
15
|
import { getAssociatedTokenAddressKit } from './ata.js';
|
|
16
16
|
import { ARIO_ANT_PROGRAM_ID, ARIO_ARNS_PROGRAM_ID, ARIO_CORE_PROGRAM_ID, ARIO_GAR_PROGRAM_ID, ARNS_RECORD_ANT_OFFSET, RATE_SCALE, } from './constants.js';
|
|
17
|
-
import {
|
|
17
|
+
import { computeLiveDelegationBalance } from './delegation-math.js';
|
|
18
|
+
import { deserializeAllowlist, deserializeArioConfig, deserializeArnsRecord, deserializeDelegation, deserializeDemandFactor, deserializeEpoch, deserializeEpochSettings, deserializeEpochSettingsFull, deserializeGarSettings, deserializeGarSupplyCounters, deserializeGateway, deserializeGatewayWithAccumulator, deserializeObservation, deserializePrimaryName, deserializePrimaryNameRequest, deserializeRedelegationRecord, deserializeReservedName, deserializeReturnedName, deserializeVault, deserializeWithdrawal, } from './deserialize.js';
|
|
18
19
|
import { TOKEN_PROGRAM_ADDRESS } from './instruction.js';
|
|
19
20
|
import { getArioConfigPDA, getArnsRecordPDA, getArnsRecordPDAFromHash, getArnsSettingsPDA, getDemandFactorPDA, getEpochPDA, getEpochSettingsPDA, getGarSettingsPDA, getGatewayPDA, getGatewayRegistryPDA, getObserverLookupPDA, getPrimaryNamePDA, getPrimaryNameRequestPDA, getReservedNamePDA, getReturnedNamePDA, getVaultPDA, } from './pda.js';
|
|
20
21
|
const addressDecoder = getAddressDecoder();
|
|
@@ -179,6 +180,42 @@ export class SolanaARIOReadable {
|
|
|
179
180
|
data: Buffer.from(entry.account.data[0], 'base64'),
|
|
180
181
|
}));
|
|
181
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Batch-fetch the `cumulative_reward_per_token` accumulator for every gateway
|
|
185
|
+
* in `operatorAddresses`. Returns a Map keyed by base58 operator address.
|
|
186
|
+
* Used by the delegate readers below to compute the live delegation balance
|
|
187
|
+
* without an on-chain settlement call (see {@link computeLiveDelegationBalance}
|
|
188
|
+
* and `INVARIANTS.md` in the contracts repo). Missing gateways are silently
|
|
189
|
+
* skipped — callers fall back to the stale `Delegation.amount` for those
|
|
190
|
+
* (the accumulator delta is 0 and live == stored anyway when the gateway
|
|
191
|
+
* has no rewards to distribute).
|
|
192
|
+
*/
|
|
193
|
+
async getGatewayAccumulators(operatorAddresses) {
|
|
194
|
+
const unique = Array.from(new Set(operatorAddresses));
|
|
195
|
+
if (unique.length === 0)
|
|
196
|
+
return new Map();
|
|
197
|
+
const pdas = await Promise.all(unique.map(async (op) => (await getGatewayPDA(address(op), this.garProgram))[0]));
|
|
198
|
+
const accounts = await fetchEncodedAccounts(this.rpc, pdas, {
|
|
199
|
+
commitment: this.commitment,
|
|
200
|
+
});
|
|
201
|
+
const out = new Map();
|
|
202
|
+
for (let i = 0; i < accounts.length; i++) {
|
|
203
|
+
const acct = accounts[i];
|
|
204
|
+
if (!acct.exists)
|
|
205
|
+
continue;
|
|
206
|
+
try {
|
|
207
|
+
// Internal variant: surfaces the u128 accumulator that the public
|
|
208
|
+
// `deserializeGateway` deliberately drops (BigInt is not
|
|
209
|
+
// JSON-serializable and would leak through getGateway).
|
|
210
|
+
const gw = deserializeGatewayWithAccumulator(Buffer.from(acct.data));
|
|
211
|
+
out.set(unique[i], gw.cumulativeRewardPerToken);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
// Skip malformed; the caller will fall back to the raw delegation amount.
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return out;
|
|
218
|
+
}
|
|
182
219
|
/** Read the gateway registry and return addresses in registry index order */
|
|
183
220
|
async getRegistryGatewayAddresses() {
|
|
184
221
|
const [registryPda] = await getGatewayRegistryPDA(this.garProgram);
|
|
@@ -480,13 +517,22 @@ export class SolanaARIOReadable {
|
|
|
480
517
|
memcmp: { offset: 8n, bytes: gateway, encoding: 'base58' },
|
|
481
518
|
},
|
|
482
519
|
]);
|
|
520
|
+
// Fetch this gateway's current reward accumulator so we can return live
|
|
521
|
+
// balances (raw `Delegation.amount` is stale between settlements — see
|
|
522
|
+
// INVARIANTS.md and `computeLiveDelegationBalance`).
|
|
523
|
+
const accumulators = await this.getGatewayAccumulators([gateway]);
|
|
524
|
+
const cumulative = accumulators.get(gateway) ?? 0n;
|
|
483
525
|
const items = [];
|
|
484
526
|
for (const { data } of accounts) {
|
|
485
527
|
try {
|
|
486
528
|
const del = deserializeDelegation(data);
|
|
487
529
|
items.push({
|
|
488
530
|
address: del.delegator,
|
|
489
|
-
delegatedStake:
|
|
531
|
+
delegatedStake: computeLiveDelegationBalance({
|
|
532
|
+
delegatedStake: del.delegatedStake,
|
|
533
|
+
rewardDebt: del.rewardDebt,
|
|
534
|
+
cumulativeRewardPerToken: cumulative,
|
|
535
|
+
}),
|
|
490
536
|
startTimestamp: secToMs(del.startTimestamp),
|
|
491
537
|
});
|
|
492
538
|
}
|
|
@@ -528,22 +574,32 @@ export class SolanaARIOReadable {
|
|
|
528
574
|
},
|
|
529
575
|
},
|
|
530
576
|
]);
|
|
531
|
-
const
|
|
577
|
+
const decoded = [];
|
|
532
578
|
for (const { pubkey, data } of accounts) {
|
|
533
579
|
try {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
gatewayAddress: del.gateway,
|
|
538
|
-
delegationId: pubkey,
|
|
539
|
-
startTimestamp: secToMs(del.startTimestamp),
|
|
540
|
-
balance: del.delegatedStake,
|
|
580
|
+
decoded.push({
|
|
581
|
+
pubkey: pubkey,
|
|
582
|
+
del: deserializeDelegation(data),
|
|
541
583
|
});
|
|
542
584
|
}
|
|
543
585
|
catch {
|
|
544
586
|
// Skip malformed
|
|
545
587
|
}
|
|
546
588
|
}
|
|
589
|
+
// Batch-fetch each referenced gateway's reward accumulator so we can
|
|
590
|
+
// return live balances. See INVARIANTS.md and `computeLiveDelegationBalance`.
|
|
591
|
+
const accumulators = await this.getGatewayAccumulators(decoded.map(({ del }) => del.gateway));
|
|
592
|
+
const items = decoded.map(({ pubkey, del }) => ({
|
|
593
|
+
type: 'stake',
|
|
594
|
+
gatewayAddress: del.gateway,
|
|
595
|
+
delegationId: pubkey,
|
|
596
|
+
startTimestamp: secToMs(del.startTimestamp),
|
|
597
|
+
balance: computeLiveDelegationBalance({
|
|
598
|
+
delegatedStake: del.delegatedStake,
|
|
599
|
+
rewardDebt: del.rewardDebt,
|
|
600
|
+
cumulativeRewardPerToken: accumulators.get(del.gateway) ?? 0n,
|
|
601
|
+
}),
|
|
602
|
+
}));
|
|
547
603
|
return paginate(items, params);
|
|
548
604
|
}
|
|
549
605
|
async getAllowedDelegates(params) {
|
|
@@ -1290,23 +1346,33 @@ export class SolanaARIOReadable {
|
|
|
1290
1346
|
// =========================================
|
|
1291
1347
|
async getAllDelegates(params) {
|
|
1292
1348
|
const accounts = await this.getAccountsByDiscriminator(this.garProgram, DELEGATION_DISCRIMINATOR);
|
|
1293
|
-
const
|
|
1349
|
+
const decoded = [];
|
|
1294
1350
|
for (const { pubkey, data } of accounts) {
|
|
1295
1351
|
try {
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
gatewayAddress: del.gateway,
|
|
1300
|
-
delegatedStake: del.delegatedStake,
|
|
1301
|
-
startTimestamp: secToMs(del.startTimestamp),
|
|
1302
|
-
vaultedStake: 0,
|
|
1303
|
-
cursorId: pubkey,
|
|
1352
|
+
decoded.push({
|
|
1353
|
+
pubkey: pubkey,
|
|
1354
|
+
del: deserializeDelegation(data),
|
|
1304
1355
|
});
|
|
1305
1356
|
}
|
|
1306
1357
|
catch {
|
|
1307
1358
|
// Skip malformed
|
|
1308
1359
|
}
|
|
1309
1360
|
}
|
|
1361
|
+
// Batch-fetch each referenced gateway's reward accumulator so we can
|
|
1362
|
+
// return live balances. See INVARIANTS.md and `computeLiveDelegationBalance`.
|
|
1363
|
+
const accumulators = await this.getGatewayAccumulators(decoded.map(({ del }) => del.gateway));
|
|
1364
|
+
const items = decoded.map(({ pubkey, del }) => ({
|
|
1365
|
+
address: del.delegator,
|
|
1366
|
+
gatewayAddress: del.gateway,
|
|
1367
|
+
delegatedStake: computeLiveDelegationBalance({
|
|
1368
|
+
delegatedStake: del.delegatedStake,
|
|
1369
|
+
rewardDebt: del.rewardDebt,
|
|
1370
|
+
cumulativeRewardPerToken: accumulators.get(del.gateway) ?? 0n,
|
|
1371
|
+
}),
|
|
1372
|
+
startTimestamp: secToMs(del.startTimestamp),
|
|
1373
|
+
vaultedStake: 0,
|
|
1374
|
+
cursorId: pubkey,
|
|
1375
|
+
}));
|
|
1310
1376
|
return paginate(items, params);
|
|
1311
1377
|
}
|
|
1312
1378
|
async getAllGatewayVaults(params) {
|
package/lib/esm/version.js
CHANGED
|
@@ -14,6 +14,12 @@ export declare const MPL_CORE_PROGRAM_ID: Address;
|
|
|
14
14
|
export declare const TOKEN_DECIMALS = 6;
|
|
15
15
|
export declare const ONE_TOKEN = 1000000;
|
|
16
16
|
export declare const RATE_SCALE = 1000000;
|
|
17
|
+
/**
|
|
18
|
+
* Scaling factor for the per-share reward accumulator
|
|
19
|
+
* `Gateway.cumulative_reward_per_token` in `ario-gar`. Must match the
|
|
20
|
+
* `REWARD_PRECISION` constant in `programs/ario-gar/src/state/mod.rs`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const REWARD_PRECISION = 1000000000000000000n;
|
|
17
23
|
export declare const ARIO_CONFIG_SEED: Buffer<ArrayBuffer>;
|
|
18
24
|
export declare const VAULT_SEED: Buffer<ArrayBuffer>;
|
|
19
25
|
export declare const VAULT_COUNTER_SEED: Buffer<ArrayBuffer>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the live delegation balance: the last-settled principal plus any
|
|
3
|
+
* pending rewards accrued since the last settlement.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors `settle_delegate_rewards` in
|
|
6
|
+
* `programs/ario-gar/src/state/mod.rs` — including the u128 overflow-safe
|
|
7
|
+
* quotient/remainder split and the saturating-to-`u64::MAX` cap at the end —
|
|
8
|
+
* so a value computed here matches what the on-chain instruction would write
|
|
9
|
+
* if it were called right now.
|
|
10
|
+
*
|
|
11
|
+
* @param delegatedStake - `Delegation.amount` (u64 → number).
|
|
12
|
+
* @param rewardDebt - `Delegation.reward_debt` (u128 → bigint).
|
|
13
|
+
* @param cumulativeRewardPerToken - `Gateway.cumulative_reward_per_token` (u128 → bigint).
|
|
14
|
+
* @returns The delegate's live balance in mARIO, saturating-capped at `u64::MAX`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function computeLiveDelegationBalance({ delegatedStake, rewardDebt, cumulativeRewardPerToken, }: {
|
|
17
|
+
delegatedStake: number;
|
|
18
|
+
rewardDebt: bigint;
|
|
19
|
+
cumulativeRewardPerToken: bigint;
|
|
20
|
+
}): number;
|
|
@@ -81,10 +81,31 @@ declare class BorshWriter {
|
|
|
81
81
|
getOffset(): number;
|
|
82
82
|
}
|
|
83
83
|
/**
|
|
84
|
-
*
|
|
84
|
+
* Internal variant of {@link deserializeGateway} that additionally surfaces
|
|
85
|
+
* the on-chain `cumulative_reward_per_token` u128 accumulator. Used by the
|
|
86
|
+
* live delegation balance pipeline ({@link computeLiveDelegationBalance} via
|
|
87
|
+
* `getGatewayAccumulators` in `io-readable.ts`).
|
|
88
|
+
*
|
|
89
|
+
* Not part of the public AoGateway shape — `bigint` is not JSON-serializable
|
|
90
|
+
* and would leak through `getGateway` / `getGateways`. Prefer
|
|
91
|
+
* {@link deserializeGateway} everywhere except inside live-balance plumbing.
|
|
92
|
+
*
|
|
85
93
|
* PDA: ["gateway", operator_pubkey] in ario-gar program.
|
|
94
|
+
*/
|
|
95
|
+
export declare function deserializeGatewayWithAccumulator(data: Buffer): AoGateway & {
|
|
96
|
+
operator: string;
|
|
97
|
+
cumulativeRewardPerToken: bigint;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Deserialize a Gateway account from raw bytes.
|
|
86
101
|
*
|
|
87
|
-
* Returns the SDK-compatible AoGateway type.
|
|
102
|
+
* Returns the SDK-compatible AoGateway type (plus `operator: string`).
|
|
103
|
+
* The on-chain `cumulative_reward_per_token` u128 is intentionally NOT
|
|
104
|
+
* surfaced on the returned object — `bigint` is not JSON-serializable,
|
|
105
|
+
* and leaking it through `getGateway` / `getGateways` would break
|
|
106
|
+
* downstream consumers that call `JSON.stringify` on results. Use
|
|
107
|
+
* {@link deserializeGatewayWithAccumulator} from within the live-balance
|
|
108
|
+
* pipeline when the accumulator value is actually needed.
|
|
88
109
|
*/
|
|
89
110
|
export declare function deserializeGateway(data: Buffer): AoGateway & {
|
|
90
111
|
operator: string;
|
|
@@ -119,8 +140,19 @@ export declare function deserializeVault(data: Buffer): AoVaultData & {
|
|
|
119
140
|
export type DeserializedDelegation = {
|
|
120
141
|
gateway: string;
|
|
121
142
|
delegator: string;
|
|
143
|
+
/**
|
|
144
|
+
* Last-settled principal (raw `Delegation.amount` from on-chain state).
|
|
145
|
+
* This value is stale between epochs — see `INVARIANTS.md` in the contracts
|
|
146
|
+
* repo. Use `computeLiveDelegationBalance` (with the gateway's current
|
|
147
|
+
* `cumulativeRewardPerToken`) to get the actual current balance.
|
|
148
|
+
*/
|
|
122
149
|
delegatedStake: number;
|
|
123
150
|
startTimestamp: number;
|
|
151
|
+
/**
|
|
152
|
+
* Snapshot of `gateway.cumulative_reward_per_token` at the last settlement.
|
|
153
|
+
* Required input to `computeLiveDelegationBalance`.
|
|
154
|
+
*/
|
|
155
|
+
rewardDebt: bigint;
|
|
124
156
|
};
|
|
125
157
|
/**
|
|
126
158
|
* Deserialize a Delegation account from raw bytes.
|
|
@@ -52,6 +52,17 @@ export declare class SolanaARIOReadable {
|
|
|
52
52
|
* keep the IDL-derived bytes as the single source of truth).
|
|
53
53
|
*/
|
|
54
54
|
private getAccountsByDiscriminator;
|
|
55
|
+
/**
|
|
56
|
+
* Batch-fetch the `cumulative_reward_per_token` accumulator for every gateway
|
|
57
|
+
* in `operatorAddresses`. Returns a Map keyed by base58 operator address.
|
|
58
|
+
* Used by the delegate readers below to compute the live delegation balance
|
|
59
|
+
* without an on-chain settlement call (see {@link computeLiveDelegationBalance}
|
|
60
|
+
* and `INVARIANTS.md` in the contracts repo). Missing gateways are silently
|
|
61
|
+
* skipped — callers fall back to the stale `Delegation.amount` for those
|
|
62
|
+
* (the accumulator delta is 0 and live == stored anyway when the gateway
|
|
63
|
+
* has no rewards to distribute).
|
|
64
|
+
*/
|
|
65
|
+
protected getGatewayAccumulators(operatorAddresses: string[]): Promise<Map<string, bigint>>;
|
|
55
66
|
/** Read the gateway registry and return addresses in registry index order */
|
|
56
67
|
protected getRegistryGatewayAddresses(): Promise<string[]>;
|
|
57
68
|
getInfo(): Promise<{
|
package/lib/types/version.d.ts
CHANGED