@ar.io/sdk 2.6.0 → 2.7.0-alpha.2

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.
Files changed (37) hide show
  1. package/bundles/web.bundle.min.js +65 -65
  2. package/lib/cjs/cli/cli.js +712 -0
  3. package/lib/cjs/cli/commands/gatewayWriteCommands.js +211 -0
  4. package/lib/cjs/cli/commands/readCommands.js +219 -0
  5. package/lib/cjs/cli/commands/transfer.js +26 -0
  6. package/lib/cjs/cli/options.js +336 -0
  7. package/lib/cjs/cli/types.js +2 -0
  8. package/lib/cjs/cli/utils.js +406 -0
  9. package/lib/cjs/common/io.js +2 -7
  10. package/lib/cjs/types/io.js +13 -1
  11. package/lib/cjs/utils/ao.js +32 -13
  12. package/lib/cjs/utils/base64.js +1 -1
  13. package/lib/cjs/version.js +1 -1
  14. package/lib/esm/cli/cli.js +710 -0
  15. package/lib/esm/cli/commands/gatewayWriteCommands.js +194 -0
  16. package/lib/esm/cli/commands/readCommands.js +197 -0
  17. package/lib/esm/cli/commands/transfer.js +22 -0
  18. package/lib/esm/cli/options.js +333 -0
  19. package/lib/esm/cli/types.js +1 -0
  20. package/lib/esm/cli/utils.js +366 -0
  21. package/lib/esm/common/io.js +2 -7
  22. package/lib/esm/types/io.js +11 -0
  23. package/lib/esm/utils/ao.js +30 -12
  24. package/lib/esm/utils/base64.js +1 -1
  25. package/lib/esm/version.js +1 -1
  26. package/lib/types/cli/cli.d.ts +2 -0
  27. package/lib/types/cli/commands/gatewayWriteCommands.d.ts +38 -0
  28. package/lib/types/cli/commands/readCommands.d.ts +57 -0
  29. package/lib/types/cli/commands/transfer.d.ts +23 -0
  30. package/lib/types/cli/options.d.ts +326 -0
  31. package/lib/types/cli/types.d.ts +106 -0
  32. package/lib/types/cli/utils.d.ts +66 -0
  33. package/lib/types/common/io.d.ts +4 -7
  34. package/lib/types/types/io.d.ts +81 -60
  35. package/lib/types/utils/ao.d.ts +20 -10
  36. package/lib/types/version.d.ts +1 -1
  37. package/package.json +7 -1
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import prompts from 'prompts';
17
+ import { mIOToken } from '../../node/index.js';
18
+ import { assertConfirmationPrompt, assertEnoughBalance, formatIOWithCommas, gatewaySettingsFromOptions, redelegateParamsFromOptions, requiredAddressFromOptions, requiredMIOFromOptions as requiredMARIOFromOptions, requiredStringArrayFromOptions, requiredStringFromOptions, requiredTargetAndQuantityFromOptions, stringifyJsonForCLIDisplay, writeActionTagsFromOptions, writeIOFromOptions, } from '../utils.js';
19
+ export async function joinNetwork(options) {
20
+ const { io, signerAddress } = writeIOFromOptions(options);
21
+ const mARIOQuantity = requiredMARIOFromOptions(options, 'operatorStake');
22
+ const settings = {
23
+ ...gatewaySettingsFromOptions(options),
24
+ operatorStake: mARIOQuantity.valueOf(),
25
+ };
26
+ if (settings.label === undefined) {
27
+ throw new Error('Label is required. Please provide a --label for your node.');
28
+ }
29
+ if (settings.fqdn === undefined) {
30
+ throw new Error('FQDN is required. Please provide a --fqdn for your node.');
31
+ }
32
+ if (!options.skipConfirmation) {
33
+ const settings = await io.getGatewayRegistrySettings();
34
+ if (settings.operators.minStake > mARIOQuantity.valueOf()) {
35
+ throw new Error(`The minimum operator stake is ${formatIOWithCommas(new mIOToken(settings.operators.minStake).toIO())} IO. Please provide a higher stake.`);
36
+ }
37
+ await assertEnoughBalance(io, signerAddress, mARIOQuantity.toIO());
38
+ await assertConfirmationPrompt(`Gateway Settings:\n\n${JSON.stringify(settings, null, 2)}\n\nYou are about to stake ${formatIOWithCommas(mARIOQuantity.toIO())} IO to join the AR.IO network\nAre you sure?\n`, options);
39
+ }
40
+ const result = await io.joinNetwork(settings, writeActionTagsFromOptions(options));
41
+ const output = {
42
+ joinNetworkResult: result,
43
+ joinedAddress: signerAddress,
44
+ message: `Congratulations! You have successfully joined the AR.IO network (;`,
45
+ };
46
+ return output;
47
+ }
48
+ export async function updateGatewaySettings(options) {
49
+ const { io, signerAddress } = writeIOFromOptions(options);
50
+ const gatewaySettings = gatewaySettingsFromOptions(options);
51
+ if (Object.keys(gatewaySettings).length === 0) {
52
+ // TODO: The contract accepts empty Update-Gateway-Settings actions, but we'll throw in the CLI for now
53
+ throw new Error('No gateway settings provided');
54
+ }
55
+ await assertConfirmationPrompt(`Gateway Settings:\n\n${stringifyJsonForCLIDisplay(gatewaySettings)}\n\nYou are about to update your gateway settings to the above\nAre you sure?\n`, options);
56
+ const result = await io.updateGatewaySettings(gatewaySettings, writeActionTagsFromOptions(options));
57
+ const output = {
58
+ updateGatewaySettingsResult: result,
59
+ updatedGatewayAddress: signerAddress,
60
+ message: `Gateway settings updated successfully`,
61
+ };
62
+ return output;
63
+ }
64
+ export async function leaveNetwork(options) {
65
+ const { io, signerAddress } = writeIOFromOptions(options);
66
+ if (!options.skipConfirmation) {
67
+ const gateway = await io.getGateway({ address: signerAddress });
68
+ if (!gateway) {
69
+ throw new Error(`Gateway not found for address: ${signerAddress}`);
70
+ }
71
+ await assertConfirmationPrompt('Gateway Details:\n\n' +
72
+ stringifyJsonForCLIDisplay(gateway) +
73
+ '\n\n' +
74
+ 'Are you sure you want to leave the AR.IO network?', options);
75
+ }
76
+ return writeIOFromOptions(options).io.leaveNetwork(writeActionTagsFromOptions(options));
77
+ }
78
+ export async function saveObservations(o) {
79
+ const failedGateways = requiredStringArrayFromOptions(o, 'failedGateways');
80
+ const reportTxId = requiredStringFromOptions(o, 'transactionId');
81
+ 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);
82
+ return writeIOFromOptions(o).io.saveObservations({
83
+ failedGateways: requiredStringArrayFromOptions(o, 'failedGateways'),
84
+ reportTxId: requiredStringFromOptions(o, 'transactionId'),
85
+ }, writeActionTagsFromOptions(o));
86
+ }
87
+ export async function increaseOperatorStake(o) {
88
+ const increaseQty = requiredMARIOFromOptions(o, 'operatorStake');
89
+ await assertConfirmationPrompt(`You are about to increase your operator stake by ${formatIOWithCommas(increaseQty.toIO())} IO\nAre you sure?`, o);
90
+ return (writeIOFromOptions(o).io.increaseOperatorStake({
91
+ increaseQty,
92
+ }),
93
+ writeActionTagsFromOptions(o));
94
+ }
95
+ export async function decreaseOperatorStake(o) {
96
+ const decreaseQty = requiredMARIOFromOptions(o, 'operatorStake');
97
+ // TODO: Can assert stake is sufficient for action, and new target stake meets contract minimum
98
+ await assertConfirmationPrompt(`You are about to decrease your operator stake by ${formatIOWithCommas(decreaseQty.toIO())} IO\nAre you sure?`, o);
99
+ return writeIOFromOptions(o).io.decreaseOperatorStake({
100
+ decreaseQty,
101
+ }, writeActionTagsFromOptions(o));
102
+ }
103
+ export async function instantWithdrawal(o) {
104
+ const vaultId = requiredStringFromOptions(o, 'vaultId');
105
+ const gatewayAddress = requiredAddressFromOptions(o);
106
+ await assertConfirmationPrompt(`You are about to instantly withdraw from vault ${vaultId} for with gateway address ${gatewayAddress}\nAre you sure?`, o);
107
+ return writeIOFromOptions(o).io.instantWithdrawal({
108
+ vaultId,
109
+ gatewayAddress,
110
+ }, writeActionTagsFromOptions(o));
111
+ }
112
+ export async function cancelWithdrawal(o) {
113
+ const vaultId = requiredStringFromOptions(o, 'vaultId');
114
+ const gatewayAddress = requiredAddressFromOptions(o);
115
+ await assertConfirmationPrompt(`You are about to cancel the pending withdrawal from vault ${vaultId} for with gateway address ${gatewayAddress}\nAre you sure?`, o);
116
+ return writeIOFromOptions(o).io.cancelWithdrawal({
117
+ vaultId,
118
+ gatewayAddress,
119
+ }, writeActionTagsFromOptions(o));
120
+ }
121
+ export async function delegateStake(options) {
122
+ const { io, signerAddress } = writeIOFromOptions(options);
123
+ const { target, ioQuantity } = requiredTargetAndQuantityFromOptions(options);
124
+ const mIOQuantity = ioQuantity.toMIO();
125
+ if (!options.skipConfirmation) {
126
+ const balance = await io.getBalance({ address: signerAddress });
127
+ if (balance < mIOQuantity.valueOf()) {
128
+ throw new Error(`Insufficient IO balance for delegating stake. Balance available: ${new mIOToken(balance).toIO()} IO`);
129
+ }
130
+ const targetGateway = await io.getGateway({ address: target });
131
+ if (targetGateway === undefined) {
132
+ throw new Error(`Gateway not found for address: ${target}`);
133
+ }
134
+ if (targetGateway.settings.allowDelegatedStaking === false) {
135
+ throw new Error(`Gateway does not allow delegated staking: ${target}`);
136
+ }
137
+ // TODO: could get allow list and assert doesn't exist or user is on it
138
+ // TODO: could read from contract to get current delegated stake if there is none, get contract minimum delegated stake. Then see if the new stake value will satisfy minimum delegated stake for both the target gateway settings min delegate stake and contract min delegated amounts
139
+ const { confirm } = await prompts({
140
+ type: 'confirm',
141
+ name: 'confirm',
142
+ message: `Target Gateway:\n${JSON.stringify(targetGateway, null, 2)}\n\nAre you sure you want to delegate ${formatIOWithCommas(ioQuantity)} IO to ${target}?`,
143
+ });
144
+ if (!confirm) {
145
+ return { message: 'Delegate stake aborted by user' };
146
+ }
147
+ }
148
+ const result = await io.delegateStake({
149
+ target,
150
+ stakeQty: ioQuantity.toMIO(),
151
+ }, writeActionTagsFromOptions(options));
152
+ const output = {
153
+ senderAddress: signerAddress,
154
+ transferResult: result,
155
+ message: `Successfully delegated ${formatIOWithCommas(ioQuantity)} IO to ${target}`,
156
+ };
157
+ return output;
158
+ }
159
+ export async function decreaseDelegateStake(options) {
160
+ const io = writeIOFromOptions(options).io;
161
+ const { target, ioQuantity } = requiredTargetAndQuantityFromOptions(options);
162
+ const instant = options.instant ?? false;
163
+ // TODO: Could assert sender is a delegate with enough stake to decrease
164
+ // TODO: Could assert new target stake meets contract and target gateway minimums
165
+ // TODO: Could present confirmation prompt with any fee for instant withdrawal (50% of the stake is put back into protocol??)
166
+ await assertConfirmationPrompt(`Are you sure you'd like to decrease delegated stake of ${formatIOWithCommas(ioQuantity)} IO on gateway ${target}?`, options);
167
+ const result = await io.decreaseDelegateStake({
168
+ target,
169
+ decreaseQty: ioQuantity.toMIO(),
170
+ instant,
171
+ });
172
+ const output = {
173
+ targetGateway: target,
174
+ decreaseDelegateStakeResult: result,
175
+ message: `Successfully decreased delegated stake of ${formatIOWithCommas(ioQuantity)} IO to ${target}`,
176
+ };
177
+ return output;
178
+ }
179
+ export async function redelegateStake(options) {
180
+ const io = writeIOFromOptions(options).io;
181
+ const params = redelegateParamsFromOptions(options);
182
+ // TODO: Could assert target gateway exists
183
+ // TODO: Could do assertion on source has enough stake to redelegate
184
+ // TODO: Could do assertions on source/target min delegate stakes are met
185
+ await assertConfirmationPrompt(`Are you sure you'd like to redelegate stake of ${formatIOWithCommas(params.stakeQty.toIO())} IO from ${params.source} to ${params.target}?`, options);
186
+ const result = await io.redelegateStake(params);
187
+ const output = {
188
+ sourceGateway: params.source,
189
+ targetGateway: params.target,
190
+ redelegateStakeResult: result,
191
+ message: `Successfully re-delegated stake of ${formatIOWithCommas(params.stakeQty.toIO())} IO from ${params.source} to ${params.target}`,
192
+ };
193
+ return output;
194
+ }
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { intentsUsingYears, isValidIntent, validIntents, } from '../../types/io.js';
17
+ import { mIOToken } from '../../types/token.js';
18
+ import { addressFromOptions, epochInputFromOptions, formatIOWithCommas, paginationParamsFromOptions, positiveIntegerFromOptions, readIOFromOptions, requiredAddressFromOptions, requiredStringFromOptions, } from '../utils.js';
19
+ export async function getGateway(o) {
20
+ const address = requiredAddressFromOptions(o);
21
+ const gateway = await readIOFromOptions(o).getGateway({
22
+ address,
23
+ });
24
+ return gateway ?? { message: `No gateway found for address ${address}` };
25
+ }
26
+ export async function listGateways(o) {
27
+ const gateways = await readIOFromOptions(o).getGateways(paginationParamsFromOptions(o));
28
+ return gateways.items.length ? gateways : { message: 'No gateways found' };
29
+ }
30
+ export async function getGatewayDelegates(o) {
31
+ const address = requiredAddressFromOptions(o);
32
+ const result = await readIOFromOptions(o).getGatewayDelegates({
33
+ address,
34
+ ...paginationParamsFromOptions(o),
35
+ });
36
+ return result.items?.length
37
+ ? result
38
+ : {
39
+ message: `No delegates found for gateway ${address}`,
40
+ };
41
+ }
42
+ export async function getDelegations(o) {
43
+ const address = requiredAddressFromOptions(o);
44
+ const result = await readIOFromOptions(o).getDelegations({
45
+ address,
46
+ ...paginationParamsFromOptions(o),
47
+ });
48
+ return result.items?.length
49
+ ? result
50
+ : {
51
+ message: `No delegations found for address ${address}`,
52
+ };
53
+ }
54
+ export async function getAllowedDelegates(o) {
55
+ const address = requiredAddressFromOptions(o);
56
+ const result = await readIOFromOptions(o).getAllowedDelegates({
57
+ address,
58
+ ...paginationParamsFromOptions(o),
59
+ });
60
+ return result.items?.length
61
+ ? result
62
+ : {
63
+ message: `No allow list found for gateway delegate ${address}`,
64
+ };
65
+ }
66
+ export async function getArNSRecord(o) {
67
+ const name = requiredStringFromOptions(o, 'name');
68
+ return ((await readIOFromOptions(o).getArNSRecord({
69
+ name,
70
+ })) ?? { message: `No record found for name ${name}` });
71
+ }
72
+ export async function listArNSRecords(o) {
73
+ const records = await readIOFromOptions(o).getArNSRecords(paginationParamsFromOptions(o));
74
+ return records.items.length ? records : { message: 'No records found' };
75
+ }
76
+ export async function getArNSReservedName(o) {
77
+ const name = requiredStringFromOptions(o, 'name');
78
+ return ((await readIOFromOptions(o).getArNSReservedName({
79
+ name,
80
+ })) ?? { message: `No reserved name found for name ${name}` });
81
+ }
82
+ export async function listArNSReservedNames(o) {
83
+ const reservedNames = await readIOFromOptions(o).getArNSReservedNames(paginationParamsFromOptions(o));
84
+ return reservedNames.items.length
85
+ ? reservedNames
86
+ : { message: 'No reserved names found' };
87
+ }
88
+ export async function getArNSAuction(o) {
89
+ const name = requiredStringFromOptions(o, 'name');
90
+ const result = await readIOFromOptions(o).getArNSAuction({ name });
91
+ return result ?? { message: `No auction found for name ${name}` };
92
+ }
93
+ export async function listArNSAuctions(o) {
94
+ const auctions = await readIOFromOptions(o).getArNSAuctions(paginationParamsFromOptions(o));
95
+ return auctions.items.length ? auctions : { message: 'No auctions found' };
96
+ }
97
+ export async function getArNSAuctionPrices(o) {
98
+ o.type ??= 'lease';
99
+ if (o.type !== 'lease' && o.type !== 'permabuy') {
100
+ throw new Error(`Invalid type. Valid types are: lease, permabuy`);
101
+ // TODY: type and years helper
102
+ }
103
+ const result = await readIOFromOptions(o).getArNSAuctionPrices({
104
+ name: requiredStringFromOptions(o, 'name'),
105
+ type: o.type,
106
+ // TODO: intervalMS helper, assert and format
107
+ intervalMs: o.intervalMs !== undefined ? +o.intervalMs : undefined,
108
+ // TODO: timestamp helper, assert and format
109
+ timestamp: o.timestamp !== undefined ? +o.timestamp : undefined,
110
+ // todo: assert years if 'lease'
111
+ years: positiveIntegerFromOptions(o, 'years'),
112
+ });
113
+ return result ?? { message: `No auction prices found` };
114
+ }
115
+ export async function getEpoch(o) {
116
+ const epoch = await readIOFromOptions(o).getEpoch(epochInputFromOptions(o));
117
+ return epoch ?? { message: `No epoch found for provided input` };
118
+ }
119
+ export async function getPrescribedObservers(o) {
120
+ const epoch = epochInputFromOptions(o);
121
+ const result = await readIOFromOptions(o).getPrescribedObservers(epoch);
122
+ return result?.length
123
+ ? result
124
+ : { message: `No prescribed observers found for epoch ${epoch}` };
125
+ }
126
+ export async function getPrescribedNames(o) {
127
+ const epoch = epochInputFromOptions(o);
128
+ const result = await readIOFromOptions(o).getPrescribedNames(epochInputFromOptions(o));
129
+ return result?.length
130
+ ? result
131
+ : { message: `No prescribed names found for epoch ${epoch}` };
132
+ }
133
+ export async function getTokenCost(o) {
134
+ o.intent ??= 'Buy-Record';
135
+ o.type ??= 'lease';
136
+ if (!isValidIntent(o.intent)) {
137
+ throw new Error(`Invalid intent. Valid intents are: ${validIntents.join(', ')}`);
138
+ }
139
+ if (o.type !== 'lease' && o.type !== 'permabuy') {
140
+ throw new Error(`Invalid type. Valid types are: lease, permabuy`);
141
+ }
142
+ if (o.type === 'lease' &&
143
+ intentsUsingYears.includes(o.intent) &&
144
+ o.years === undefined) {
145
+ throw new Error('Years is required for lease type');
146
+ }
147
+ const tokenCost = await readIOFromOptions(o).getTokenCost({
148
+ type: o.type,
149
+ quantity: o.quantity !== undefined ? +o.quantity : undefined,
150
+ years: o.years !== undefined ? +o.years : undefined,
151
+ intent: o.intent,
152
+ name: requiredStringFromOptions(o, 'name'),
153
+ });
154
+ const output = {
155
+ mIOTokenCost: tokenCost,
156
+ message: `The cost of the provided action is ${formatIOWithCommas(new mIOToken(tokenCost).toIO())} IO`,
157
+ };
158
+ return output;
159
+ }
160
+ export async function getPrimaryName(o) {
161
+ const address = addressFromOptions(o);
162
+ const name = o.name;
163
+ const params = name !== undefined
164
+ ? { name }
165
+ : address !== undefined
166
+ ? { address }
167
+ : undefined;
168
+ if (params === undefined) {
169
+ throw new Error('Either --address or --name is required');
170
+ }
171
+ const result = await readIOFromOptions(o).getPrimaryName(params);
172
+ return (result ?? {
173
+ message: `No primary name found`,
174
+ });
175
+ }
176
+ export async function getGatewayVaults(o) {
177
+ const address = requiredAddressFromOptions(o);
178
+ const result = await readIOFromOptions(o).getGatewayVaults({
179
+ address,
180
+ ...paginationParamsFromOptions(o),
181
+ });
182
+ return result.items?.length
183
+ ? result
184
+ : {
185
+ message: `No vaults found for gateway ${address}`,
186
+ };
187
+ }
188
+ export async function getVault(o) {
189
+ return readIOFromOptions(o)
190
+ .getVault({
191
+ address: requiredAddressFromOptions(o),
192
+ vaultId: requiredStringFromOptions(o, 'vaultId'),
193
+ })
194
+ .then((r) => r ?? {
195
+ message: `No vault found for provided address and vault ID`,
196
+ });
197
+ }
@@ -0,0 +1,22 @@
1
+ import { assertEnoughBalance, confirmationPrompt, formatIOWithCommas, requiredTargetAndQuantityFromOptions, writeActionTagsFromOptions, writeIOFromOptions, } from '../utils.js';
2
+ export async function transfer(options) {
3
+ const { target, ioQuantity } = requiredTargetAndQuantityFromOptions(options);
4
+ const { io, signerAddress } = writeIOFromOptions(options);
5
+ if (!options.skipConfirmation) {
6
+ await assertEnoughBalance(io, signerAddress, ioQuantity);
7
+ const confirm = await confirmationPrompt(`Are you sure you want to transfer ${formatIOWithCommas(ioQuantity)} IO to ${target}?`);
8
+ if (!confirm) {
9
+ return { message: 'Transfer aborted by user' };
10
+ }
11
+ }
12
+ const result = await io.transfer({
13
+ target,
14
+ qty: ioQuantity.toMIO().valueOf(),
15
+ }, writeActionTagsFromOptions(options));
16
+ const output = {
17
+ senderAddress: signerAddress,
18
+ transferResult: result,
19
+ message: `Successfully transferred ${formatIOWithCommas(ioQuantity)} IO to ${target}`,
20
+ };
21
+ return output;
22
+ }