@ar.io/sdk 4.0.0-solana.24 → 4.0.0-solana.25
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/deserialize.js +17 -0
- package/lib/esm/solana/io-readable.js +33 -0
- package/lib/esm/solana/io-writeable.js +42 -1
- package/lib/esm/version.js +1 -1
- package/lib/types/solana/deserialize.d.ts +1 -0
- package/lib/types/solana/io-readable.d.ts +15 -0
- package/lib/types/solana/io-writeable.d.ts +20 -0
- package/lib/types/types/io.d.ts +16 -0
- package/lib/types/version.d.ts +1 -1
- package/package.json +2 -2
|
@@ -108,6 +108,12 @@ class BorshReader {
|
|
|
108
108
|
return undefined;
|
|
109
109
|
return this.readU32();
|
|
110
110
|
}
|
|
111
|
+
readOptionU16() {
|
|
112
|
+
const tag = this.readU8();
|
|
113
|
+
if (tag === 0)
|
|
114
|
+
return undefined;
|
|
115
|
+
return this.readU16();
|
|
116
|
+
}
|
|
111
117
|
skip(bytes) {
|
|
112
118
|
this.offset += bytes;
|
|
113
119
|
}
|
|
@@ -332,6 +338,15 @@ export function deserializeGatewayWithAccumulator(data) {
|
|
|
332
338
|
const delegateRewardShareRatio = r.readU16() / 100;
|
|
333
339
|
const minDelegatedStake = r.readU64AsNumber();
|
|
334
340
|
const allowlistEnabled = r.readBool();
|
|
341
|
+
// GATEWAY_VERSION 1.1.0 added two fields to GatewaySettings2 — MUST read them
|
|
342
|
+
// here to keep the byte stream aligned for every field after `settings`.
|
|
343
|
+
// - pending_delegate_reward_share_ratio: Option<u16> (Fix #7) — basis points
|
|
344
|
+
// of a deferred reward-share change applied at the next epoch's tally.
|
|
345
|
+
// - delegation_disabled_at: Option<i64> (Fix #6) — unix seconds the operator
|
|
346
|
+
// disabled delegation; starts the re-enable cooldown.
|
|
347
|
+
const pendingRatioRaw = r.readOptionU16();
|
|
348
|
+
const pendingDelegateRewardShareRatio = pendingRatioRaw === undefined ? undefined : pendingRatioRaw / 100;
|
|
349
|
+
const delegationDisabledAt = r.readOptionI64();
|
|
335
350
|
// RegistryIndex (index: u32, _reserved: u8 — was is_registered:bool)
|
|
336
351
|
r.readU32(); // registryIndex
|
|
337
352
|
r.readU8(); // _reserved (layout-preserving placeholder for the legacy is_registered byte)
|
|
@@ -378,6 +393,8 @@ export function deserializeGatewayWithAccumulator(data) {
|
|
|
378
393
|
fqdn,
|
|
379
394
|
port,
|
|
380
395
|
protocol: 'https', // protocolIdx: 0=Http, 1=Https — only HTTPS in practice
|
|
396
|
+
pendingDelegateRewardShareRatio, // Fix #7: undefined when no change is queued
|
|
397
|
+
delegationDisabledAt, // Fix #6: undefined when delegation is enabled
|
|
381
398
|
};
|
|
382
399
|
return {
|
|
383
400
|
operator: operator,
|
|
@@ -1743,6 +1743,39 @@ export class SolanaARIOReadable {
|
|
|
1743
1743
|
}
|
|
1744
1744
|
return out;
|
|
1745
1745
|
}
|
|
1746
|
+
/**
|
|
1747
|
+
* Enumerate Joined Gateway PDAs whose delegation has been DISABLED
|
|
1748
|
+
* (`allow_delegated_staking == false`) yet still hold delegated stake
|
|
1749
|
+
* (`total_delegated_stake > 0`) — i.e. delegates that an operator's disable
|
|
1750
|
+
* left stranded (WP §6.3 / Fix #6). Each such gateway's delegates must be
|
|
1751
|
+
* cranked out via
|
|
1752
|
+
* {@link SolanaARIOWriteable.claimDelegateFromDisabledGateway} (enumerate
|
|
1753
|
+
* them with {@link getGatewayDelegates}) before the operator can re-enable
|
|
1754
|
+
* delegation. This is the discovery primitive a cranker uses to sweep them.
|
|
1755
|
+
*/
|
|
1756
|
+
async getDisabledGatewaysWithDelegatedStake() {
|
|
1757
|
+
const accounts = await this.getAccountsByDiscriminator(this.garProgram, GATEWAY_DISCRIMINATOR);
|
|
1758
|
+
const decoder = getGatewayDecoder();
|
|
1759
|
+
const out = [];
|
|
1760
|
+
for (const { pubkey, data } of accounts) {
|
|
1761
|
+
try {
|
|
1762
|
+
const g = decoder.decode(data);
|
|
1763
|
+
if (g.status !== GatewayStatus.Joined)
|
|
1764
|
+
continue;
|
|
1765
|
+
if (!g.settings.allowDelegatedStaking && g.totalDelegatedStake > 0n) {
|
|
1766
|
+
out.push({
|
|
1767
|
+
pubkey,
|
|
1768
|
+
operator: g.operator,
|
|
1769
|
+
totalDelegatedStake: g.totalDelegatedStake,
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
catch {
|
|
1774
|
+
// skip malformed
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
return out;
|
|
1778
|
+
}
|
|
1746
1779
|
/**
|
|
1747
1780
|
* Enumerate Delegation PDAs with `amount == 0`. Eligible for
|
|
1748
1781
|
* `closeEmptyDelegation` (rent refund to the original delegator).
|
|
@@ -38,7 +38,7 @@ function toGeneratedFundingSourceSpec(s) {
|
|
|
38
38
|
import { getSyncAttributesInstruction } from '@ar.io/solana-contracts/ant';
|
|
39
39
|
import { getApprovePrimaryNameInstructionAsync, getCloseExpiredRequestInstruction, getCreateVaultInstructionAsync, getExtendVaultInstructionAsync, getIncreaseVaultInstructionAsync, getReleaseVaultInstructionAsync, getRemovePrimaryNameInstructionAsync, getRequestAndSetPrimaryNameFromFundingPlanInstructionAsync, getRequestAndSetPrimaryNameInstructionAsync, getRequestPrimaryNameFromFundingPlanInstructionAsync, getRequestPrimaryNameInstructionAsync, getRevokeVaultInstructionAsync, getVaultedTransferInstructionAsync, } from '@ar.io/solana-contracts/core';
|
|
40
40
|
import { getDelegationDecoder, getGatewayDecoder, } from '@ar.io/solana-contracts/gar';
|
|
41
|
-
import { Protocol, getAllowDelegateInstructionAsync, getCancelWithdrawalInstruction, getClaimDelegateFromLeavingGatewayInstructionAsync, getClaimWithdrawalInstructionAsync, getCloseDrainedWithdrawalInstruction, getCloseEmptyDelegationInstruction, getCloseEpochInstructionAsync, getCloseObservationInstructionAsync, getCreateEpochInstructionAsync, getDecreaseDelegateStakeInstructionAsync, getDecreaseOperatorStakeInstructionAsync, getDelegateStakeInstructionAsync, getDisallowDelegateInstructionAsync, getDistributeEpochInstructionAsync, getFinalizeGoneInstructionAsync, getIncreaseOperatorStakeInstructionAsync, getInstantWithdrawalInstructionAsync, getJoinNetworkInstructionAsync, getLeaveNetworkInstructionAsync, getPrescribeEpochInstructionAsync, getPruneGatewayInstructionAsync, getRedelegateStakeInstructionAsync, getSaveObservationsInstructionAsync, getSetAllowlistEnabledInstructionAsync, getTallyWeightsInstructionAsync, getUpdateGatewaySettingsInstructionAsync, } from '@ar.io/solana-contracts/gar';
|
|
41
|
+
import { Protocol, getAllowDelegateInstructionAsync, getCancelWithdrawalInstruction, getClaimDelegateFromDisabledGatewayInstructionAsync, getClaimDelegateFromLeavingGatewayInstructionAsync, getClaimWithdrawalInstructionAsync, getCloseDrainedWithdrawalInstruction, getCloseEmptyDelegationInstruction, getCloseEpochInstructionAsync, getCloseObservationInstructionAsync, getCreateEpochInstructionAsync, getDecreaseDelegateStakeInstructionAsync, getDecreaseOperatorStakeInstructionAsync, getDelegateStakeInstructionAsync, getDisallowDelegateInstructionAsync, getDistributeEpochInstructionAsync, getFinalizeGoneInstructionAsync, getIncreaseOperatorStakeInstructionAsync, getInstantWithdrawalInstructionAsync, getJoinNetworkInstructionAsync, getLeaveNetworkInstructionAsync, getPrescribeEpochInstructionAsync, getPruneGatewayInstructionAsync, getRedelegateStakeInstructionAsync, getSaveObservationsInstructionAsync, getSetAllowlistEnabledInstructionAsync, getTallyWeightsInstructionAsync, getUpdateGatewaySettingsInstructionAsync, } from '@ar.io/solana-contracts/gar';
|
|
42
42
|
import { getTransferCheckedInstruction } from '@solana-program/token';
|
|
43
43
|
import { ARIO_ANT_PROGRAM_ID, TOKEN_DECIMALS } from './constants.js';
|
|
44
44
|
import { SolanaARIOReadable } from './io-readable.js';
|
|
@@ -1771,6 +1771,47 @@ export class SolanaARIOWriteable extends SolanaARIOReadable {
|
|
|
1771
1771
|
return { id: sig };
|
|
1772
1772
|
}
|
|
1773
1773
|
// =========================================
|
|
1774
|
+
// Claim delegation from gateway with delegation DISABLED (ario-gar, Fix #6)
|
|
1775
|
+
// =========================================
|
|
1776
|
+
/**
|
|
1777
|
+
* Claim a delegate's stake out of a gateway that has DISABLED delegation
|
|
1778
|
+
* (`allow_delegated_staking == false`), moving it into the delegate's own
|
|
1779
|
+
* withdrawal vault (WP §6.3 / Fix #6). This is the disabled-gateway analog of
|
|
1780
|
+
* {@link claimDelegateFromLeavingGateway}: the on-chain instruction is
|
|
1781
|
+
* permissionless, so a cranker can sweep delegates out (the operator cannot
|
|
1782
|
+
* re-enable delegation until `total_delegated_stake == 0` and the cooldown
|
|
1783
|
+
* elapses). The withdrawal-counter and withdrawal PDAs are seeded by the
|
|
1784
|
+
* DELEGATOR, so a cranker must pass that delegate's `delegatorAddress`.
|
|
1785
|
+
*
|
|
1786
|
+
* @param params.gatewayAddress The gateway whose delegation was disabled.
|
|
1787
|
+
* @param params.delegatorAddress The delegate to claim for. Defaults to the
|
|
1788
|
+
* signer (self-claim). Pass another address to crank on a delegate's behalf;
|
|
1789
|
+
* the signer covers rent (`payer`) but stake still routes to the delegate's
|
|
1790
|
+
* own vault (the delegator key is bound by the delegation PDA seeds).
|
|
1791
|
+
*/
|
|
1792
|
+
async claimDelegateFromDisabledGateway(params, _options) {
|
|
1793
|
+
const gateway = address(params.gatewayAddress);
|
|
1794
|
+
const delegator = params.delegatorAddress
|
|
1795
|
+
? address(params.delegatorAddress)
|
|
1796
|
+
: this.signer.address;
|
|
1797
|
+
const [gatewayPda] = await getGatewayPDA(gateway, this.garProgram);
|
|
1798
|
+
const [delegationPda] = await getDelegationPDA(gateway, delegator, this.garProgram);
|
|
1799
|
+
// Withdrawal counter + vault are PDA-seeded by the delegator, not the payer.
|
|
1800
|
+
const nextId = await this.getNextWithdrawalId(delegator);
|
|
1801
|
+
const [withdrawalPda] = await getWithdrawalPDA(delegator, nextId, this.garProgram);
|
|
1802
|
+
const ix = await getClaimDelegateFromDisabledGatewayInstructionAsync({
|
|
1803
|
+
gateway: gatewayPda,
|
|
1804
|
+
delegation: delegationPda,
|
|
1805
|
+
withdrawal: withdrawalPda,
|
|
1806
|
+
// `delegator` is an unsigned seeds-derivation key; `payer` (the signer)
|
|
1807
|
+
// covers rent on the init_if_needed counter + the new withdrawal.
|
|
1808
|
+
delegator,
|
|
1809
|
+
payer: this.signer,
|
|
1810
|
+
}, { programAddress: this.garProgram });
|
|
1811
|
+
const sig = await this.sendTransaction([ix], 1_000_000);
|
|
1812
|
+
return { id: sig };
|
|
1813
|
+
}
|
|
1814
|
+
// =========================================
|
|
1774
1815
|
// Delegation allowlist (ario-gar)
|
|
1775
1816
|
// =========================================
|
|
1776
1817
|
/** Add an address to the gateway's delegation allowlist. */
|
package/lib/esm/version.js
CHANGED
|
@@ -309,6 +309,21 @@ export declare class SolanaARIOReadable {
|
|
|
309
309
|
pubkey: Address;
|
|
310
310
|
operator: Address;
|
|
311
311
|
}>>;
|
|
312
|
+
/**
|
|
313
|
+
* Enumerate Joined Gateway PDAs whose delegation has been DISABLED
|
|
314
|
+
* (`allow_delegated_staking == false`) yet still hold delegated stake
|
|
315
|
+
* (`total_delegated_stake > 0`) — i.e. delegates that an operator's disable
|
|
316
|
+
* left stranded (WP §6.3 / Fix #6). Each such gateway's delegates must be
|
|
317
|
+
* cranked out via
|
|
318
|
+
* {@link SolanaARIOWriteable.claimDelegateFromDisabledGateway} (enumerate
|
|
319
|
+
* them with {@link getGatewayDelegates}) before the operator can re-enable
|
|
320
|
+
* delegation. This is the discovery primitive a cranker uses to sweep them.
|
|
321
|
+
*/
|
|
322
|
+
getDisabledGatewaysWithDelegatedStake(): Promise<Array<{
|
|
323
|
+
pubkey: Address;
|
|
324
|
+
operator: Address;
|
|
325
|
+
totalDelegatedStake: bigint;
|
|
326
|
+
}>>;
|
|
312
327
|
/**
|
|
313
328
|
* Enumerate Delegation PDAs with `amount == 0`. Eligible for
|
|
314
329
|
* `closeEmptyDelegation` (rent refund to the original delegator).
|
|
@@ -422,6 +422,26 @@ export declare class SolanaARIOWriteable extends SolanaARIOReadable {
|
|
|
422
422
|
claimDelegateFromLeavingGateway(params: {
|
|
423
423
|
gatewayAddress: string;
|
|
424
424
|
}, _options?: WriteOptions): Promise<MessageResult>;
|
|
425
|
+
/**
|
|
426
|
+
* Claim a delegate's stake out of a gateway that has DISABLED delegation
|
|
427
|
+
* (`allow_delegated_staking == false`), moving it into the delegate's own
|
|
428
|
+
* withdrawal vault (WP §6.3 / Fix #6). This is the disabled-gateway analog of
|
|
429
|
+
* {@link claimDelegateFromLeavingGateway}: the on-chain instruction is
|
|
430
|
+
* permissionless, so a cranker can sweep delegates out (the operator cannot
|
|
431
|
+
* re-enable delegation until `total_delegated_stake == 0` and the cooldown
|
|
432
|
+
* elapses). The withdrawal-counter and withdrawal PDAs are seeded by the
|
|
433
|
+
* DELEGATOR, so a cranker must pass that delegate's `delegatorAddress`.
|
|
434
|
+
*
|
|
435
|
+
* @param params.gatewayAddress The gateway whose delegation was disabled.
|
|
436
|
+
* @param params.delegatorAddress The delegate to claim for. Defaults to the
|
|
437
|
+
* signer (self-claim). Pass another address to crank on a delegate's behalf;
|
|
438
|
+
* the signer covers rent (`payer`) but stake still routes to the delegate's
|
|
439
|
+
* own vault (the delegator key is bound by the delegation PDA seeds).
|
|
440
|
+
*/
|
|
441
|
+
claimDelegateFromDisabledGateway(params: {
|
|
442
|
+
gatewayAddress: string;
|
|
443
|
+
delegatorAddress?: string;
|
|
444
|
+
}, _options?: WriteOptions): Promise<MessageResult>;
|
|
425
445
|
/** Add an address to the gateway's delegation allowlist. */
|
|
426
446
|
allowDelegate(params: {
|
|
427
447
|
delegate: string;
|
package/lib/types/types/io.d.ts
CHANGED
|
@@ -232,6 +232,22 @@ export type GatewaySettings = {
|
|
|
232
232
|
fqdn: string;
|
|
233
233
|
port: number;
|
|
234
234
|
protocol: 'https';
|
|
235
|
+
/**
|
|
236
|
+
* Solana only (GATEWAY_VERSION 1.1.0+). A `delegateRewardShareRatio` change
|
|
237
|
+
* requested mid-epoch is staged here and applied at the next epoch's
|
|
238
|
+
* `tally_weights` (WP §6.3 / Fix #7), so the active value stays epoch-stable.
|
|
239
|
+
* When set, render the active `delegateRewardShareRatio` as the current rate
|
|
240
|
+
* and this as "pending until next epoch". Percent (0-95), same scale as
|
|
241
|
+
* `delegateRewardShareRatio`. Undefined when no change is queued.
|
|
242
|
+
*/
|
|
243
|
+
pendingDelegateRewardShareRatio?: number;
|
|
244
|
+
/**
|
|
245
|
+
* Solana only (GATEWAY_VERSION 1.1.0+). Unix seconds when the operator
|
|
246
|
+
* disabled delegation (WP §6.3 / Fix #6). Re-enabling is blocked until every
|
|
247
|
+
* delegate has been withdrawn AND the withdrawal-period cooldown has elapsed
|
|
248
|
+
* since this time. Undefined when delegation is enabled.
|
|
249
|
+
*/
|
|
250
|
+
delegationDisabledAt?: number;
|
|
235
251
|
};
|
|
236
252
|
export type BalanceWithAddress = {
|
|
237
253
|
address: WalletAddress;
|
package/lib/types/version.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ar.io/sdk",
|
|
3
|
-
"version": "4.0.0-solana.
|
|
3
|
+
"version": "4.0.0-solana.25",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/ar-io/ar-io-sdk.git"
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
"typescript": "^5.1.6"
|
|
124
124
|
},
|
|
125
125
|
"dependencies": {
|
|
126
|
-
"@ar.io/solana-contracts": "0.
|
|
126
|
+
"@ar.io/solana-contracts": "0.5.0-staging.15",
|
|
127
127
|
"@solana-program/address-lookup-table": "^0.11.0",
|
|
128
128
|
"@solana-program/compute-budget": "^0.15.0",
|
|
129
129
|
"@solana-program/token": "^0.13.0",
|