@ar.io/sdk 3.24.0 → 4.0.0-alpha.1
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 +682 -600
- package/lib/esm/cli/cli.js +188 -152
- package/lib/esm/cli/commands/antCommands.js +23 -58
- package/lib/esm/cli/commands/arnsPurchaseCommands.js +48 -30
- package/lib/esm/cli/commands/escrowCommands.js +221 -0
- package/lib/esm/cli/commands/gatewayWriteCommands.js +142 -23
- package/lib/esm/cli/commands/pruneCommands.js +150 -0
- package/lib/esm/cli/commands/readCommands.js +22 -3
- package/lib/esm/cli/commands/transfer.js +6 -6
- package/lib/esm/cli/options.js +124 -58
- package/lib/esm/cli/utils.js +280 -174
- package/lib/esm/common/ant-registry.js +17 -143
- package/lib/esm/common/ant.js +44 -1167
- package/lib/esm/common/faucet.js +11 -6
- package/lib/esm/common/index.js +0 -4
- package/lib/esm/common/io.js +25 -1412
- package/lib/esm/constants.js +13 -19
- package/lib/esm/solana/ant-readable.js +724 -0
- package/lib/esm/solana/ant-registry-readable.js +133 -0
- package/lib/esm/solana/ant-registry-writeable.js +472 -0
- package/lib/esm/solana/ant-writeable.js +384 -0
- package/lib/esm/solana/ata.js +70 -0
- package/lib/esm/solana/canonical-message.js +128 -0
- package/lib/esm/solana/clusters.js +111 -0
- package/lib/esm/solana/constants.js +146 -0
- package/lib/esm/solana/delegation-math.js +112 -0
- package/lib/esm/solana/deserialize.js +711 -0
- package/lib/esm/solana/escrow.js +839 -0
- package/lib/{cjs/utils/json.js → esm/solana/events.js} +15 -10
- package/lib/esm/solana/funding-plan.js +699 -0
- package/lib/esm/solana/index.js +126 -0
- package/lib/esm/solana/instruction.js +39 -0
- package/lib/esm/solana/io-readable.js +2182 -0
- package/lib/esm/solana/io-writeable.js +3196 -0
- package/lib/esm/solana/json-rpc.js +90 -0
- package/lib/esm/solana/metadata.js +81 -0
- package/lib/esm/solana/mpl-core.js +192 -0
- package/lib/esm/solana/pda.js +332 -0
- package/lib/esm/solana/predict-prescribed-observers.js +110 -0
- package/lib/esm/solana/retry.js +117 -0
- package/lib/esm/solana/rpc-circuit-breaker.js +258 -0
- package/lib/esm/solana/send.js +372 -0
- package/lib/esm/solana/spawn-ant.js +224 -0
- package/lib/esm/solana/types.js +1 -0
- package/lib/esm/types/ant.js +27 -15
- package/lib/esm/types/io.js +8 -11
- package/lib/esm/utils/ant.js +0 -63
- package/lib/esm/utils/index.js +0 -3
- package/lib/esm/version.js +1 -1
- package/lib/types/cli/commands/antCommands.d.ts +5 -13
- package/lib/types/cli/commands/arnsPurchaseCommands.d.ts +33 -7
- package/lib/types/cli/commands/escrowCommands.d.ts +68 -0
- package/lib/types/cli/commands/gatewayWriteCommands.d.ts +12 -11
- package/lib/types/cli/commands/pruneCommands.d.ts +31 -0
- package/lib/types/cli/commands/readCommands.d.ts +27 -22
- package/lib/types/cli/commands/transfer.d.ts +9 -9
- package/lib/types/cli/options.d.ts +76 -21
- package/lib/types/cli/types.d.ts +11 -13
- package/lib/types/cli/utils.d.ts +71 -31
- package/lib/types/common/ant-registry.d.ts +49 -47
- package/lib/types/common/ant.d.ts +54 -539
- package/lib/types/common/faucet.d.ts +20 -8
- package/lib/types/common/index.d.ts +0 -3
- package/lib/types/common/io.d.ts +51 -263
- package/lib/types/constants.d.ts +11 -18
- package/lib/types/solana/ant-readable.d.ts +180 -0
- package/lib/types/solana/ant-registry-readable.d.ts +105 -0
- package/lib/types/solana/ant-registry-writeable.d.ts +249 -0
- package/lib/types/solana/ant-writeable.d.ts +177 -0
- package/lib/types/solana/ata.d.ts +44 -0
- package/lib/types/solana/canonical-message.d.ts +121 -0
- package/lib/types/solana/clusters.d.ts +109 -0
- package/lib/types/solana/constants.d.ts +119 -0
- package/lib/types/solana/delegation-math.d.ts +45 -0
- package/lib/types/solana/deserialize.d.ts +262 -0
- package/lib/types/solana/escrow.d.ts +480 -0
- package/lib/types/solana/events.d.ts +38 -0
- package/lib/types/solana/funding-plan.d.ts +225 -0
- package/lib/types/solana/index.d.ts +87 -0
- package/lib/types/solana/instruction.d.ts +39 -0
- package/lib/types/solana/io-readable.d.ts +499 -0
- package/lib/types/solana/io-writeable.d.ts +893 -0
- package/lib/types/solana/json-rpc.d.ts +47 -0
- package/lib/types/solana/metadata.d.ts +84 -0
- package/lib/types/solana/mpl-core.d.ts +120 -0
- package/lib/types/solana/pda.d.ts +95 -0
- package/lib/types/solana/predict-prescribed-observers.d.ts +28 -0
- package/lib/types/solana/retry.d.ts +62 -0
- package/lib/types/solana/rpc-circuit-breaker.d.ts +78 -0
- package/lib/types/solana/send.d.ts +94 -0
- package/lib/types/solana/spawn-ant.d.ts +145 -0
- package/lib/types/solana/types.d.ts +82 -0
- package/lib/types/types/ant-registry.d.ts +43 -4
- package/lib/types/types/ant.d.ts +114 -96
- package/lib/types/types/common.d.ts +18 -74
- package/lib/types/types/faucet.d.ts +2 -2
- package/lib/types/types/io.d.ts +244 -158
- package/lib/types/types/token.d.ts +0 -12
- package/lib/types/utils/ant.d.ts +1 -12
- package/lib/types/utils/index.d.ts +0 -3
- package/lib/types/version.d.ts +1 -1
- package/package.json +36 -33
- package/lib/cjs/cli/cli.js +0 -822
- package/lib/cjs/cli/commands/antCommands.js +0 -113
- package/lib/cjs/cli/commands/arnsPurchaseCommands.js +0 -212
- package/lib/cjs/cli/commands/gatewayWriteCommands.js +0 -210
- package/lib/cjs/cli/commands/readCommands.js +0 -215
- package/lib/cjs/cli/commands/transfer.js +0 -159
- package/lib/cjs/cli/options.js +0 -470
- package/lib/cjs/cli/types.js +0 -2
- package/lib/cjs/cli/utils.js +0 -639
- package/lib/cjs/common/ant-registry.js +0 -155
- package/lib/cjs/common/ant-versions.js +0 -93
- package/lib/cjs/common/ant.js +0 -1182
- package/lib/cjs/common/arweave.js +0 -27
- package/lib/cjs/common/contracts/ao-process.js +0 -224
- package/lib/cjs/common/error.js +0 -64
- package/lib/cjs/common/faucet.js +0 -150
- package/lib/cjs/common/hyperbeam/hb.js +0 -173
- package/lib/cjs/common/index.js +0 -42
- package/lib/cjs/common/io.js +0 -1423
- package/lib/cjs/common/logger.js +0 -83
- package/lib/cjs/common/loggers/winston.js +0 -68
- package/lib/cjs/common/marketplace.js +0 -731
- package/lib/cjs/common/turbo.js +0 -223
- package/lib/cjs/constants.js +0 -41
- package/lib/cjs/node/index.js +0 -39
- package/lib/cjs/package.json +0 -1
- package/lib/cjs/types/ant-registry.js +0 -2
- package/lib/cjs/types/ant.js +0 -168
- package/lib/cjs/types/common.js +0 -2
- package/lib/cjs/types/faucet.js +0 -2
- package/lib/cjs/types/index.js +0 -37
- package/lib/cjs/types/io.js +0 -51
- package/lib/cjs/types/token.js +0 -116
- package/lib/cjs/utils/ant.js +0 -108
- package/lib/cjs/utils/ao.js +0 -432
- package/lib/cjs/utils/arweave.js +0 -285
- package/lib/cjs/utils/base64.js +0 -62
- package/lib/cjs/utils/hash.js +0 -56
- package/lib/cjs/utils/index.js +0 -38
- package/lib/cjs/utils/processes.js +0 -173
- package/lib/cjs/utils/random.js +0 -30
- package/lib/cjs/utils/schema.js +0 -15
- package/lib/cjs/utils/url.js +0 -37
- package/lib/cjs/version.js +0 -20
- package/lib/cjs/web/index.js +0 -41
- package/lib/esm/common/ant-versions.js +0 -87
- package/lib/esm/common/arweave.js +0 -21
- package/lib/esm/common/contracts/ao-process.js +0 -220
- package/lib/esm/common/hyperbeam/hb.js +0 -169
- package/lib/esm/common/marketplace.js +0 -724
- package/lib/esm/common/turbo.js +0 -215
- package/lib/esm/node/index.js +0 -20
- package/lib/esm/utils/ao.js +0 -420
- package/lib/esm/utils/arweave.js +0 -271
- package/lib/esm/utils/processes.js +0 -167
- package/lib/esm/web/index.js +0 -20
- package/lib/types/common/ant-versions.d.ts +0 -39
- package/lib/types/common/arweave.d.ts +0 -17
- package/lib/types/common/contracts/ao-process.d.ts +0 -47
- package/lib/types/common/hyperbeam/hb.d.ts +0 -88
- package/lib/types/common/marketplace.d.ts +0 -568
- package/lib/types/common/turbo.d.ts +0 -61
- package/lib/types/node/index.d.ts +0 -20
- package/lib/types/utils/ao.d.ts +0 -80
- package/lib/types/utils/arweave.d.ts +0 -79
- package/lib/types/utils/processes.d.ts +0 -39
- package/lib/types/web/index.d.ts +0 -20
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import prompts from 'prompts';
|
|
17
|
-
import { mARIOToken } from '../../
|
|
17
|
+
import { mARIOToken } from '../../types/token.js';
|
|
18
18
|
import { assertConfirmationPrompt, assertEnoughMARIOBalance, customTagsFromOptions, formatARIOWithCommas, gatewaySettingsFromOptions, redelegateParamsFromOptions, requiredAddressFromOptions, requiredMARIOFromOptions, requiredStringArrayFromOptions, requiredStringFromOptions, requiredTargetAndQuantityFromOptions, stringifyJsonForCLIDisplay, writeARIOFromOptions, } from '../utils.js';
|
|
19
19
|
export async function joinNetwork(options) {
|
|
20
|
-
const { ario, signerAddress } = writeARIOFromOptions(options);
|
|
20
|
+
const { ario, signerAddress } = await writeARIOFromOptions(options);
|
|
21
21
|
const mARIOQuantity = requiredMARIOFromOptions(options, 'operatorStake');
|
|
22
22
|
const settings = {
|
|
23
23
|
...gatewaySettingsFromOptions(options),
|
|
@@ -50,7 +50,7 @@ export async function joinNetwork(options) {
|
|
|
50
50
|
return output;
|
|
51
51
|
}
|
|
52
52
|
export async function updateGatewaySettings(options) {
|
|
53
|
-
const { ario, signerAddress } = writeARIOFromOptions(options);
|
|
53
|
+
const { ario, signerAddress } = await writeARIOFromOptions(options);
|
|
54
54
|
const gatewaySettings = gatewaySettingsFromOptions(options);
|
|
55
55
|
if (Object.keys(gatewaySettings).length === 0) {
|
|
56
56
|
// TODO: The contract accepts empty Update-Gateway-Settings actions, but we'll throw in the CLI for now
|
|
@@ -66,7 +66,7 @@ export async function updateGatewaySettings(options) {
|
|
|
66
66
|
return output;
|
|
67
67
|
}
|
|
68
68
|
export async function leaveNetwork(options) {
|
|
69
|
-
const { ario, signerAddress } = writeARIOFromOptions(options);
|
|
69
|
+
const { ario, signerAddress } = await writeARIOFromOptions(options);
|
|
70
70
|
if (!options.skipConfirmation) {
|
|
71
71
|
const gateway = await ario.getGateway({ address: signerAddress });
|
|
72
72
|
await assertConfirmationPrompt('Gateway Details:\n\n' +
|
|
@@ -74,13 +74,13 @@ export async function leaveNetwork(options) {
|
|
|
74
74
|
'\n\n' +
|
|
75
75
|
'Are you sure you want to leave the AR.IO network?', options);
|
|
76
76
|
}
|
|
77
|
-
return writeARIOFromOptions(options).ario.leaveNetwork(customTagsFromOptions(options));
|
|
77
|
+
return (await writeARIOFromOptions(options)).ario.leaveNetwork(customTagsFromOptions(options));
|
|
78
78
|
}
|
|
79
79
|
export async function saveObservations(o) {
|
|
80
80
|
const failedGateways = requiredStringArrayFromOptions(o, 'failedGateways');
|
|
81
81
|
const reportTxId = requiredStringFromOptions(o, 'transactionId');
|
|
82
82
|
await assertConfirmationPrompt(`You are about to save the following failed gateways to the AR.IO network:\n\n${failedGateways.join('\n')}\n\nTransaction ID: ${reportTxId}\n\nAre you sure?`, o);
|
|
83
|
-
return writeARIOFromOptions(o).ario.saveObservations({
|
|
83
|
+
return (await writeARIOFromOptions(o)).ario.saveObservations({
|
|
84
84
|
failedGateways: requiredStringArrayFromOptions(o, 'failedGateways'),
|
|
85
85
|
reportTxId: requiredStringFromOptions(o, 'transactionId'),
|
|
86
86
|
}, customTagsFromOptions(o));
|
|
@@ -88,23 +88,47 @@ export async function saveObservations(o) {
|
|
|
88
88
|
export async function increaseOperatorStake(o) {
|
|
89
89
|
const increaseQty = requiredMARIOFromOptions(o, 'operatorStake');
|
|
90
90
|
await assertConfirmationPrompt(`You are about to increase your operator stake by ${formatARIOWithCommas(increaseQty.toARIO())} ARIO\nAre you sure?`, o);
|
|
91
|
-
return writeARIOFromOptions(o).ario.increaseOperatorStake({
|
|
91
|
+
return (await writeARIOFromOptions(o)).ario.increaseOperatorStake({
|
|
92
92
|
increaseQty,
|
|
93
93
|
}, customTagsFromOptions(o));
|
|
94
94
|
}
|
|
95
95
|
export async function decreaseOperatorStake(o) {
|
|
96
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
96
97
|
const decreaseQty = requiredMARIOFromOptions(o, 'operatorStake');
|
|
97
|
-
|
|
98
|
+
if (!o.skipConfirmation) {
|
|
99
|
+
const gateway = await ario.getGateway({ address: signerAddress });
|
|
100
|
+
if (gateway === undefined) {
|
|
101
|
+
throw new Error(`No gateway found for address ${signerAddress}. You must be a gateway operator to decrease stake.`);
|
|
102
|
+
}
|
|
103
|
+
const settings = await ario.getGatewayRegistrySettings();
|
|
104
|
+
const currentStake = gateway.operatorStake;
|
|
105
|
+
const remaining = currentStake - decreaseQty.valueOf();
|
|
106
|
+
if (remaining < 0) {
|
|
107
|
+
throw new Error(`Insufficient operator stake. Current: ${formatARIOWithCommas(new mARIOToken(currentStake).toARIO())} ARIO, requested decrease: ${formatARIOWithCommas(decreaseQty.toARIO())} ARIO`);
|
|
108
|
+
}
|
|
109
|
+
if (remaining > 0 && remaining < settings.operators.minStake) {
|
|
110
|
+
throw new Error(`Remaining stake (${formatARIOWithCommas(new mARIOToken(remaining).toARIO())} ARIO) would be below minimum (${formatARIOWithCommas(new mARIOToken(settings.operators.minStake).toARIO())} ARIO). Decrease to exactly 0 (after calling leave-network) or keep above the minimum.`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
98
113
|
await assertConfirmationPrompt(`You are about to decrease your operator stake by ${formatARIOWithCommas(decreaseQty.toARIO())} ARIO\nAre you sure?`, o);
|
|
99
|
-
return
|
|
114
|
+
return ario.decreaseOperatorStake({
|
|
100
115
|
decreaseQty,
|
|
101
116
|
}, customTagsFromOptions(o));
|
|
102
117
|
}
|
|
118
|
+
export async function claimWithdrawal(o) {
|
|
119
|
+
const vaultId = requiredStringFromOptions(o, 'vaultId');
|
|
120
|
+
await assertConfirmationPrompt(`You are about to claim matured withdrawal vault ${vaultId}. Tokens will be transferred to your wallet.\nAre you sure?`, o);
|
|
121
|
+
// claimWithdrawal is Solana-only — surface it through the SolanaARIOWriteable
|
|
122
|
+
// class rather than the shared ARIOWrite interface (see the comment in
|
|
123
|
+
// src/types/io.ts above syncAttributes).
|
|
124
|
+
const { ario } = await writeARIOFromOptions(o);
|
|
125
|
+
return ario.claimWithdrawal({ withdrawalId: vaultId }, customTagsFromOptions(o));
|
|
126
|
+
}
|
|
103
127
|
export async function instantWithdrawal(o) {
|
|
104
128
|
const vaultId = requiredStringFromOptions(o, 'vaultId');
|
|
105
129
|
const gatewayAddress = requiredAddressFromOptions(o);
|
|
106
130
|
await assertConfirmationPrompt(`You are about to instantly withdraw from vault ${vaultId} for with gateway address ${gatewayAddress}\nAre you sure?`, o);
|
|
107
|
-
return writeARIOFromOptions(o).ario.instantWithdrawal({
|
|
131
|
+
return (await writeARIOFromOptions(o)).ario.instantWithdrawal({
|
|
108
132
|
vaultId,
|
|
109
133
|
gatewayAddress,
|
|
110
134
|
}, customTagsFromOptions(o));
|
|
@@ -113,13 +137,13 @@ export async function cancelWithdrawal(o) {
|
|
|
113
137
|
const vaultId = requiredStringFromOptions(o, 'vaultId');
|
|
114
138
|
const gatewayAddress = requiredAddressFromOptions(o);
|
|
115
139
|
await assertConfirmationPrompt(`You are about to cancel the pending withdrawal from vault ${vaultId} for with gateway address ${gatewayAddress}\nAre you sure?`, o);
|
|
116
|
-
return writeARIOFromOptions(o).ario.cancelWithdrawal({
|
|
140
|
+
return (await writeARIOFromOptions(o)).ario.cancelWithdrawal({
|
|
117
141
|
vaultId,
|
|
118
142
|
gatewayAddress,
|
|
119
143
|
}, customTagsFromOptions(o));
|
|
120
144
|
}
|
|
121
145
|
export async function delegateStake(options) {
|
|
122
|
-
const { ario, signerAddress } = writeARIOFromOptions(options);
|
|
146
|
+
const { ario, signerAddress } = await writeARIOFromOptions(options);
|
|
123
147
|
const { target, arioQuantity } = requiredTargetAndQuantityFromOptions(options);
|
|
124
148
|
const mARIOQuantity = arioQuantity.toMARIO();
|
|
125
149
|
if (!options.skipConfirmation) {
|
|
@@ -134,8 +158,59 @@ export async function delegateStake(options) {
|
|
|
134
158
|
if (targetGateway.settings.allowDelegatedStaking === false) {
|
|
135
159
|
throw new Error(`Gateway does not allow delegated staking: ${target}`);
|
|
136
160
|
}
|
|
137
|
-
//
|
|
138
|
-
//
|
|
161
|
+
// Check allowlist if gateway restricts delegation. `allowDelegatedStaking`
|
|
162
|
+
// is `boolean | 'allowlist'`; the SDK maps `allowlist_enabled = true` on
|
|
163
|
+
// Solana to the `'allowlist'` variant (see deserialize.ts).
|
|
164
|
+
//
|
|
165
|
+
// `getGatewayDelegateAllowList` returns `PaginationResult<WalletAddress>`,
|
|
166
|
+
// so we walk pages by cursor — the previous shape (plain `string[]`) was
|
|
167
|
+
// never the actual return type and made the membership check dead code.
|
|
168
|
+
//
|
|
169
|
+
// Note: the on-chain delegate handler also lets you bypass the allowlist
|
|
170
|
+
// if you already have stake > 0 with this gateway (delegate.rs). We
|
|
171
|
+
// can't easily check that client-side, so this preflight surfaces the
|
|
172
|
+
// most common case (new-delegator-not-on-list) but falls through any
|
|
173
|
+
// unexpected error to let the on-chain check arbitrate.
|
|
174
|
+
if (targetGateway.settings.allowDelegatedStaking === 'allowlist') {
|
|
175
|
+
try {
|
|
176
|
+
let cursor;
|
|
177
|
+
let onAllowlist = false;
|
|
178
|
+
let allowlistHasEntries = false;
|
|
179
|
+
do {
|
|
180
|
+
const page = await ario.getGatewayDelegateAllowList({
|
|
181
|
+
address: target,
|
|
182
|
+
limit: 1_000,
|
|
183
|
+
cursor,
|
|
184
|
+
});
|
|
185
|
+
if (page.items.length > 0)
|
|
186
|
+
allowlistHasEntries = true;
|
|
187
|
+
if (page.items.includes(signerAddress)) {
|
|
188
|
+
onAllowlist = true;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
cursor = page.nextCursor;
|
|
192
|
+
} while (cursor);
|
|
193
|
+
if (allowlistHasEntries && !onAllowlist) {
|
|
194
|
+
throw new Error(`You (${signerAddress}) are not on the delegation allowlist for gateway ${target}.`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (e) {
|
|
198
|
+
// Re-throw our own "not on allowlist" error; swallow anything else
|
|
199
|
+
// so the on-chain check can produce the canonical failure.
|
|
200
|
+
if (e instanceof Error &&
|
|
201
|
+
e.message.includes('not on the delegation allowlist')) {
|
|
202
|
+
throw e;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// Validate minimum delegation amount
|
|
207
|
+
const settings = await ario.getGatewayRegistrySettings();
|
|
208
|
+
const contractMinDelegation = settings.delegates.minStake;
|
|
209
|
+
const gatewayMinDelegation = targetGateway.settings.minDelegatedStake ?? contractMinDelegation;
|
|
210
|
+
const effectiveMin = Math.max(contractMinDelegation, gatewayMinDelegation);
|
|
211
|
+
if (mARIOQuantity.valueOf() < effectiveMin) {
|
|
212
|
+
throw new Error(`Delegation amount (${formatARIOWithCommas(arioQuantity)} ARIO) is below minimum (${formatARIOWithCommas(new mARIOToken(effectiveMin).toARIO())} ARIO).`);
|
|
213
|
+
}
|
|
139
214
|
const { confirm } = await prompts({
|
|
140
215
|
type: 'confirm',
|
|
141
216
|
name: 'confirm',
|
|
@@ -157,13 +232,40 @@ export async function delegateStake(options) {
|
|
|
157
232
|
return output;
|
|
158
233
|
}
|
|
159
234
|
export async function decreaseDelegateStake(options) {
|
|
160
|
-
const ario = writeARIOFromOptions(options).ario;
|
|
235
|
+
const ario = await (await writeARIOFromOptions(options)).ario;
|
|
161
236
|
const { target, arioQuantity } = requiredTargetAndQuantityFromOptions(options);
|
|
162
237
|
const instant = options.instant ?? false;
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
238
|
+
if (!options.skipConfirmation) {
|
|
239
|
+
// Verify the target gateway exists and look up delegation
|
|
240
|
+
const signerAddr = (await writeARIOFromOptions(options)).signerAddress;
|
|
241
|
+
const targetGateway = await ario.getGateway({ address: target });
|
|
242
|
+
if (targetGateway === undefined) {
|
|
243
|
+
throw new Error(`Gateway not found: ${target}`);
|
|
244
|
+
}
|
|
245
|
+
// Find delegation to this gateway
|
|
246
|
+
const delegations = await ario.getDelegations({ address: signerAddr });
|
|
247
|
+
const delegation = delegations.items.find((d) => d.gatewayAddress === target && d.type === 'stake');
|
|
248
|
+
if (!delegation) {
|
|
249
|
+
throw new Error(`No active delegation found for you on gateway ${target}.`);
|
|
250
|
+
}
|
|
251
|
+
if (arioQuantity.toMARIO().valueOf() > delegation.balance) {
|
|
252
|
+
throw new Error(`Cannot decrease by ${formatARIOWithCommas(arioQuantity)} ARIO — you only have ${formatARIOWithCommas(new mARIOToken(delegation.balance).toARIO())} ARIO delegated.`);
|
|
253
|
+
}
|
|
254
|
+
const remaining = delegation.balance - arioQuantity.toMARIO().valueOf();
|
|
255
|
+
if (remaining > 0) {
|
|
256
|
+
const registrySettings = await ario.getGatewayRegistrySettings();
|
|
257
|
+
const contractMin = registrySettings.delegates.minStake;
|
|
258
|
+
if (remaining < contractMin) {
|
|
259
|
+
throw new Error(`Remaining delegation (${formatARIOWithCommas(new mARIOToken(remaining).toARIO())} ARIO) would be below minimum (${formatARIOWithCommas(new mARIOToken(contractMin).toARIO())} ARIO). Decrease to exactly 0 or keep above the minimum.`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (instant) {
|
|
264
|
+
await assertConfirmationPrompt(`WARNING: Instant withdrawal incurs a penalty.\nAre you sure you'd like to instantly decrease delegated stake of ${formatARIOWithCommas(arioQuantity)} ARIO on gateway ${target}?`, options);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
await assertConfirmationPrompt(`Are you sure you'd like to decrease delegated stake of ${formatARIOWithCommas(arioQuantity)} ARIO on gateway ${target}?`, options);
|
|
268
|
+
}
|
|
167
269
|
const result = await ario.decreaseDelegateStake({
|
|
168
270
|
target,
|
|
169
271
|
decreaseQty: arioQuantity.toMARIO(),
|
|
@@ -177,11 +279,28 @@ export async function decreaseDelegateStake(options) {
|
|
|
177
279
|
return output;
|
|
178
280
|
}
|
|
179
281
|
export async function redelegateStake(options) {
|
|
180
|
-
const ario = writeARIOFromOptions(options).ario;
|
|
282
|
+
const ario = await (await writeARIOFromOptions(options)).ario;
|
|
181
283
|
const params = redelegateParamsFromOptions(options);
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
284
|
+
if (!options.skipConfirmation) {
|
|
285
|
+
const targetGateway = await ario.getGateway({ address: params.target });
|
|
286
|
+
if (targetGateway === undefined) {
|
|
287
|
+
throw new Error(`Target gateway not found: ${params.target}`);
|
|
288
|
+
}
|
|
289
|
+
if (targetGateway.settings.allowDelegatedStaking === false) {
|
|
290
|
+
throw new Error(`Target gateway ${params.target} does not allow delegated staking.`);
|
|
291
|
+
}
|
|
292
|
+
const sourceGateway = await ario.getGateway({ address: params.source });
|
|
293
|
+
if (sourceGateway === undefined) {
|
|
294
|
+
throw new Error(`Source gateway not found: ${params.source}`);
|
|
295
|
+
}
|
|
296
|
+
const signerAddr = (await writeARIOFromOptions(options)).signerAddress;
|
|
297
|
+
const delegations = await ario.getDelegations({ address: signerAddr });
|
|
298
|
+
const delegation = delegations.items.find((d) => d.gatewayAddress === params.source && d.type === 'stake');
|
|
299
|
+
if (!delegation || delegation.balance < params.stakeQty.valueOf()) {
|
|
300
|
+
const available = delegation?.balance ?? 0;
|
|
301
|
+
throw new Error(`Insufficient delegated stake on source gateway ${params.source}. Available: ${formatARIOWithCommas(new mARIOToken(available).toARIO())} ARIO, requested: ${formatARIOWithCommas(params.stakeQty.toARIO())} ARIO`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
185
304
|
await assertConfirmationPrompt(`Are you sure you'd like to redelegate stake of ${formatARIOWithCommas(params.stakeQty.toARIO())} ARIO from ${params.source} to ${params.target}?`, options);
|
|
186
305
|
const result = await ario.redelegateStake(params);
|
|
187
306
|
const output = {
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { assertConfirmationPrompt, requiredStringFromOptions, writeARIOFromOptions, } from '../utils.js';
|
|
2
|
+
async function getSolanaWriter(o) {
|
|
3
|
+
const { ario } = await writeARIOFromOptions(o);
|
|
4
|
+
return ario;
|
|
5
|
+
}
|
|
6
|
+
function parseMaxNames(o) {
|
|
7
|
+
const raw = o.max;
|
|
8
|
+
if (raw === undefined) {
|
|
9
|
+
throw new Error('--max <count> is required (u8 batch size, 1-255)');
|
|
10
|
+
}
|
|
11
|
+
const n = Number(raw);
|
|
12
|
+
if (!Number.isInteger(n) || n < 1 || n > 255) {
|
|
13
|
+
throw new Error(`--max must be an integer 1-255 (got ${raw})`);
|
|
14
|
+
}
|
|
15
|
+
return n;
|
|
16
|
+
}
|
|
17
|
+
// =========================================
|
|
18
|
+
// ArNS prune
|
|
19
|
+
// =========================================
|
|
20
|
+
export async function pruneExpiredNamesCLICommand(o) {
|
|
21
|
+
const max = parseMaxNames(o);
|
|
22
|
+
const ario = await getSolanaWriter(o);
|
|
23
|
+
// If `--arns-records` wasn't provided, discover them via the readable's
|
|
24
|
+
// helper. Cap at `max` so we never overshoot the ix's u8 batch parameter.
|
|
25
|
+
let records = o.arnsRecords ?? [];
|
|
26
|
+
if (records.length === 0) {
|
|
27
|
+
const now = Math.floor(Date.now() / 1000);
|
|
28
|
+
const expired = await ario.getExpiredArnsRecords(now);
|
|
29
|
+
records = expired.slice(0, max).map((r) => r.pubkey);
|
|
30
|
+
if (records.length === 0) {
|
|
31
|
+
return { message: 'No expired ArnsRecords to prune' };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
records = records.slice(0, max);
|
|
36
|
+
}
|
|
37
|
+
await assertConfirmationPrompt(`Prune ${records.length} expired ArnsRecord(s)?`, o);
|
|
38
|
+
return ario.pruneExpiredNames({ maxNames: max, arnsRecords: records });
|
|
39
|
+
}
|
|
40
|
+
export async function pruneNameToReturnedCLICommand(o) {
|
|
41
|
+
const name = requiredStringFromOptions(o, 'name');
|
|
42
|
+
const ario = await getSolanaWriter(o);
|
|
43
|
+
await assertConfirmationPrompt(`Convert expired lease for "${name}" to a ReturnedName (Dutch auction)?`, o);
|
|
44
|
+
return ario.pruneNameToReturned({ name });
|
|
45
|
+
}
|
|
46
|
+
export async function pruneReturnedNamesCLICommand(o) {
|
|
47
|
+
const max = parseMaxNames(o);
|
|
48
|
+
const ario = await getSolanaWriter(o);
|
|
49
|
+
let returned = o.returnedNames ?? [];
|
|
50
|
+
if (returned.length === 0) {
|
|
51
|
+
const now = Math.floor(Date.now() / 1000);
|
|
52
|
+
const expired = await ario.getExpiredReturnedNames(now);
|
|
53
|
+
returned = expired.slice(0, max).map((r) => r.pubkey);
|
|
54
|
+
if (returned.length === 0) {
|
|
55
|
+
return { message: 'No expired ReturnedNames to prune' };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
returned = returned.slice(0, max);
|
|
60
|
+
}
|
|
61
|
+
await assertConfirmationPrompt(`Prune ${returned.length} expired ReturnedName(s)?`, o);
|
|
62
|
+
return ario.pruneReturnedNames({
|
|
63
|
+
maxNames: max,
|
|
64
|
+
returnedNames: returned,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export async function pruneExpiredReservationCLICommand(o) {
|
|
68
|
+
const name = requiredStringFromOptions(o, 'name');
|
|
69
|
+
const ario = await getSolanaWriter(o);
|
|
70
|
+
await assertConfirmationPrompt(`Close expired reservation for "${name}"?`, o);
|
|
71
|
+
return ario.pruneExpiredReservation({ name });
|
|
72
|
+
}
|
|
73
|
+
// =========================================
|
|
74
|
+
// Gateway prune
|
|
75
|
+
// =========================================
|
|
76
|
+
export async function pruneGatewayCLICommand(o) {
|
|
77
|
+
const gateway = requiredStringFromOptions(o, 'gateway');
|
|
78
|
+
const ario = await getSolanaWriter(o);
|
|
79
|
+
await assertConfirmationPrompt(`Slash + remove deficient gateway ${gateway}?`, o);
|
|
80
|
+
return ario.pruneGateway({ gateway });
|
|
81
|
+
}
|
|
82
|
+
export async function finalizeGoneCLICommand(o) {
|
|
83
|
+
const gateway = requiredStringFromOptions(o, 'gateway');
|
|
84
|
+
const ario = await getSolanaWriter(o);
|
|
85
|
+
await assertConfirmationPrompt(`Finalize-GC departed gateway ${gateway} (reclaim PDA rent)?`, o);
|
|
86
|
+
return ario.finalizeGone({ gateway });
|
|
87
|
+
}
|
|
88
|
+
// =========================================
|
|
89
|
+
// Rent reclaim
|
|
90
|
+
// =========================================
|
|
91
|
+
export async function closeObservationCLICommand(o) {
|
|
92
|
+
const epochIndexStr = requiredStringFromOptions(o, 'epochIndex');
|
|
93
|
+
const observer = requiredStringFromOptions(o, 'observer');
|
|
94
|
+
const epochIndex = Number(epochIndexStr);
|
|
95
|
+
if (!Number.isInteger(epochIndex) || epochIndex < 0) {
|
|
96
|
+
throw new Error(`--epoch-index must be a non-negative integer (got ${epochIndexStr})`);
|
|
97
|
+
}
|
|
98
|
+
const ario = await getSolanaWriter(o);
|
|
99
|
+
await assertConfirmationPrompt(`Close Observation PDA (epoch ${epochIndex}, observer ${observer})?`, o);
|
|
100
|
+
return ario.closeObservation({ epochIndex, observer });
|
|
101
|
+
}
|
|
102
|
+
export async function closeEmptyDelegationCLICommand(o) {
|
|
103
|
+
const gateway = requiredStringFromOptions(o, 'gateway');
|
|
104
|
+
const delegator = requiredStringFromOptions(o, 'delegator');
|
|
105
|
+
const ario = await getSolanaWriter(o);
|
|
106
|
+
await assertConfirmationPrompt(`Close empty Delegation PDA (gateway=${gateway}, delegator=${delegator})?`, o);
|
|
107
|
+
return ario.closeEmptyDelegation({ gateway, delegator });
|
|
108
|
+
}
|
|
109
|
+
export async function closeDrainedWithdrawalCLICommand(o) {
|
|
110
|
+
const owner = requiredStringFromOptions(o, 'owner');
|
|
111
|
+
const withdrawalIdStr = requiredStringFromOptions(o, 'withdrawalId');
|
|
112
|
+
// Validate before BigInt() — `BigInt('0xff')` and `BigInt(' 1 ')` succeed
|
|
113
|
+
// and `BigInt('abc')` throws an opaque SyntaxError. Restrict to the u64
|
|
114
|
+
// decimal form the on-chain seed encoder expects so the CLI fails with a
|
|
115
|
+
// clear message instead of a downstream parser error.
|
|
116
|
+
if (!/^\d+$/.test(withdrawalIdStr)) {
|
|
117
|
+
throw new Error(`--withdrawal-id must be a non-negative decimal integer (got "${withdrawalIdStr}")`);
|
|
118
|
+
}
|
|
119
|
+
const withdrawalId = BigInt(withdrawalIdStr);
|
|
120
|
+
const ario = await getSolanaWriter(o);
|
|
121
|
+
await assertConfirmationPrompt(`Close drained Withdrawal PDA (owner=${owner}, id=${withdrawalIdStr})?`, o);
|
|
122
|
+
return ario.closeDrainedWithdrawal({ owner, withdrawalId });
|
|
123
|
+
}
|
|
124
|
+
// =========================================
|
|
125
|
+
// Vault + primary-name request
|
|
126
|
+
// =========================================
|
|
127
|
+
export async function releaseVaultCLICommand(o) {
|
|
128
|
+
// The on-chain handler requires `owner: Signer` — the SDK uses the
|
|
129
|
+
// configured signer as the owner. The `--owner` flag is accepted as
|
|
130
|
+
// documentation but ignored unless it matches the signer; fail loud if
|
|
131
|
+
// it doesn't, so users don't think they can release someone else's vault.
|
|
132
|
+
const ario = await getSolanaWriter(o);
|
|
133
|
+
if (o.owner) {
|
|
134
|
+
const signerAddr = (await writeARIOFromOptions(o)).signerAddress;
|
|
135
|
+
if (o.owner !== signerAddr) {
|
|
136
|
+
throw new Error(`release-vault: --owner ${o.owner} does not match signer ${signerAddr}. ` +
|
|
137
|
+
`release_vault is owner-signed; use the owner's wallet to call it.`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const vaultIdStr = requiredStringFromOptions(o, 'vaultId');
|
|
141
|
+
const vaultId = vaultIdStr;
|
|
142
|
+
await assertConfirmationPrompt(`Release expired vault id=${vaultIdStr} (transfer tokens back to owner)?`, o);
|
|
143
|
+
return ario.releaseVault({ vaultId });
|
|
144
|
+
}
|
|
145
|
+
export async function closeExpiredRequestCLICommand(o) {
|
|
146
|
+
const initiator = requiredStringFromOptions(o, 'initiator');
|
|
147
|
+
const ario = await getSolanaWriter(o);
|
|
148
|
+
await assertConfirmationPrompt(`Close expired primary-name request from ${initiator}?`, o);
|
|
149
|
+
return ario.closeExpiredRequest({ initiator });
|
|
150
|
+
}
|
|
@@ -67,7 +67,6 @@ export async function listArNSRecordsForAddress(o) {
|
|
|
67
67
|
const names = await readARIOFromOptions(o).getArNSRecordsForAddress({
|
|
68
68
|
...paginationParams,
|
|
69
69
|
address,
|
|
70
|
-
antRegistryProcessId: o.antRegistryProcessId,
|
|
71
70
|
});
|
|
72
71
|
return names.items.length ? names : { message: 'No names found' };
|
|
73
72
|
}
|
|
@@ -165,6 +164,18 @@ export async function getAllGatewayVaults(o) {
|
|
|
165
164
|
message: `No vaults found`,
|
|
166
165
|
};
|
|
167
166
|
}
|
|
167
|
+
export async function getWithdrawals(o) {
|
|
168
|
+
const address = requiredAddressFromOptions(o);
|
|
169
|
+
const result = await readARIOFromOptions(o).getWithdrawals({
|
|
170
|
+
address,
|
|
171
|
+
...paginationParamsFromOptions(o),
|
|
172
|
+
});
|
|
173
|
+
return result.items?.length
|
|
174
|
+
? result
|
|
175
|
+
: {
|
|
176
|
+
message: `No pending withdrawals found for address ${address}`,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
168
179
|
export async function getVault(o) {
|
|
169
180
|
return readARIOFromOptions(o)
|
|
170
181
|
.getVault({
|
|
@@ -182,8 +193,16 @@ export async function resolveArNSName(o) {
|
|
|
182
193
|
}
|
|
183
194
|
export async function listAntsForAddress(o) {
|
|
184
195
|
const address = requiredAddressFromOptions(o);
|
|
185
|
-
|
|
196
|
+
// Both AO and Solana backends expose `accessControlList({ address })`.
|
|
197
|
+
// Solana is backed by the paginated per-user ACL (ADR-012): a head
|
|
198
|
+
// `AclConfig` PDA at ["acl_config", user] plus N `AclPage` PDAs at
|
|
199
|
+
// ["acl_page", user, page_idx_le]. The ario-ant program maintains them
|
|
200
|
+
// alongside `initialize`, `add_controller`, `remove_controller`,
|
|
201
|
+
// `transfer_record`, and the marketplace reconcile path.
|
|
202
|
+
const registry = await readANTRegistryFromOptions(o);
|
|
203
|
+
const result = await registry.accessControlList({
|
|
186
204
|
address,
|
|
187
205
|
});
|
|
188
|
-
|
|
206
|
+
const hasAny = result && (result.Owned.length > 0 || result.Controlled.length > 0);
|
|
207
|
+
return hasAny ? result : { message: `No ANTs found for address ${address}` };
|
|
189
208
|
}
|
|
@@ -2,7 +2,7 @@ import { mARIOToken } from '../../types/token.js';
|
|
|
2
2
|
import { assertEnoughMARIOBalance, assertLockLengthInRange, confirmationPrompt, customTagsFromOptions, formatARIOWithCommas, formatMARIOToARIOWithCommas, requiredMARIOFromOptions, requiredPositiveIntegerFromOptions, requiredStringFromOptions, requiredTargetAndQuantityFromOptions, writeARIOFromOptions, } from '../utils.js';
|
|
3
3
|
export async function transferCLICommand(options) {
|
|
4
4
|
const { target, arioQuantity } = requiredTargetAndQuantityFromOptions(options);
|
|
5
|
-
const { ario, signerAddress } = writeARIOFromOptions(options);
|
|
5
|
+
const { ario, signerAddress } = await writeARIOFromOptions(options);
|
|
6
6
|
if (!options.skipConfirmation) {
|
|
7
7
|
await assertEnoughMARIOBalance({
|
|
8
8
|
ario,
|
|
@@ -28,7 +28,7 @@ export async function transferCLICommand(options) {
|
|
|
28
28
|
export async function vaultedTransferCLICommand(o) {
|
|
29
29
|
const mARIOQuantity = requiredMARIOFromOptions(o, 'quantity');
|
|
30
30
|
const recipient = requiredStringFromOptions(o, 'recipient');
|
|
31
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
31
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
32
32
|
const lockLengthMs = requiredPositiveIntegerFromOptions(o, 'lockLengthMs');
|
|
33
33
|
assertLockLengthInRange(lockLengthMs);
|
|
34
34
|
if (!o.skipConfirmation) {
|
|
@@ -56,7 +56,7 @@ export async function vaultedTransferCLICommand(o) {
|
|
|
56
56
|
return output;
|
|
57
57
|
}
|
|
58
58
|
export async function revokeVaultCLICommand(o) {
|
|
59
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
59
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
60
60
|
const vaultId = requiredStringFromOptions(o, 'vaultId');
|
|
61
61
|
const recipient = requiredStringFromOptions(o, 'recipient');
|
|
62
62
|
if (!o.skipConfirmation) {
|
|
@@ -79,7 +79,7 @@ export async function revokeVaultCLICommand(o) {
|
|
|
79
79
|
}
|
|
80
80
|
export async function createVaultCLICommand(o) {
|
|
81
81
|
const mARIOQuantity = requiredMARIOFromOptions(o, 'quantity');
|
|
82
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
82
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
83
83
|
const lockLengthMs = requiredPositiveIntegerFromOptions(o, 'lockLengthMs');
|
|
84
84
|
assertLockLengthInRange(lockLengthMs);
|
|
85
85
|
if (!o.skipConfirmation) {
|
|
@@ -105,7 +105,7 @@ export async function createVaultCLICommand(o) {
|
|
|
105
105
|
return output;
|
|
106
106
|
}
|
|
107
107
|
export async function extendVaultCLICommand(o) {
|
|
108
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
108
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
109
109
|
const vaultId = requiredStringFromOptions(o, 'vaultId');
|
|
110
110
|
const extendLengthMs = requiredPositiveIntegerFromOptions(o, 'extendLengthMs');
|
|
111
111
|
assertLockLengthInRange(extendLengthMs, false);
|
|
@@ -129,7 +129,7 @@ export async function extendVaultCLICommand(o) {
|
|
|
129
129
|
}
|
|
130
130
|
export async function increaseVaultCLICommand(o) {
|
|
131
131
|
const mARIOQuantity = requiredMARIOFromOptions(o, 'quantity');
|
|
132
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
132
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
133
133
|
const vaultId = requiredStringFromOptions(o, 'vaultId');
|
|
134
134
|
if (!o.skipConfirmation) {
|
|
135
135
|
const vault = await ario.getVault({ vaultId, address: signerAddress });
|