@ar.io/sdk 3.0.1-alpha.1 → 3.1.0-alpha.10

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 (38) hide show
  1. package/README.md +38 -0
  2. package/bundles/web.bundle.min.js +79 -79
  3. package/lib/cjs/cli/cli.js +27 -71
  4. package/lib/cjs/cli/commands/arnsPurchaseCommands.js +167 -0
  5. package/lib/cjs/cli/commands/gatewayWriteCommands.js +8 -4
  6. package/lib/cjs/cli/commands/readCommands.js +17 -38
  7. package/lib/cjs/cli/commands/transfer.js +5 -1
  8. package/lib/cjs/cli/options.js +14 -7
  9. package/lib/cjs/cli/utils.js +59 -7
  10. package/lib/cjs/common/contracts/ao-process.js +41 -19
  11. package/lib/cjs/common/io.js +107 -101
  12. package/lib/cjs/types/io.js +6 -1
  13. package/lib/cjs/utils/arweave.js +22 -13
  14. package/lib/cjs/version.js +1 -1
  15. package/lib/esm/cli/cli.js +30 -74
  16. package/lib/esm/cli/commands/arnsPurchaseCommands.js +159 -0
  17. package/lib/esm/cli/commands/gatewayWriteCommands.js +6 -2
  18. package/lib/esm/cli/commands/readCommands.js +16 -38
  19. package/lib/esm/cli/commands/transfer.js +6 -2
  20. package/lib/esm/cli/options.js +13 -6
  21. package/lib/esm/cli/utils.js +53 -5
  22. package/lib/esm/common/contracts/ao-process.js +41 -19
  23. package/lib/esm/common/io.js +108 -102
  24. package/lib/esm/types/io.js +4 -0
  25. package/lib/esm/utils/arweave.js +21 -11
  26. package/lib/esm/version.js +1 -1
  27. package/lib/types/cli/commands/arnsPurchaseCommands.d.ts +22 -0
  28. package/lib/types/cli/commands/readCommands.d.ts +24 -2
  29. package/lib/types/cli/options.d.ts +5 -9
  30. package/lib/types/cli/types.d.ts +3 -5
  31. package/lib/types/cli/utils.d.ts +25 -4
  32. package/lib/types/common/contracts/ao-process.d.ts +3 -1
  33. package/lib/types/common/io.d.ts +15 -43
  34. package/lib/types/types/common.d.ts +1 -0
  35. package/lib/types/types/io.d.ts +46 -12
  36. package/lib/types/utils/arweave.d.ts +6 -18
  37. package/lib/types/version.d.ts +1 -1
  38. package/package.json +2 -2
@@ -19,11 +19,12 @@ import { program } from 'commander';
19
19
  import { spawnANT } from '../node/index.js';
20
20
  import { mARIOToken } from '../types/token.js';
21
21
  import { version } from '../version.js';
22
+ import { buyRecordCLICommand, extendLeaseCLICommand, increaseUndernameLimitCLICommand, requestPrimaryNameCLICommand, upgradeRecordCLICommand, } from './commands/arnsPurchaseCommands.js';
22
23
  import { cancelWithdrawal, decreaseDelegateStake, decreaseOperatorStake, delegateStake, increaseOperatorStake, instantWithdrawal, joinNetwork, leaveNetwork, redelegateStake, saveObservations, updateGatewaySettings, } from './commands/gatewayWriteCommands.js';
23
- import { getAllowedDelegates, getArNSRecord, getArNSReservedName, getArNSReturnedName, getDelegations, getEpoch, getGateway, getGatewayDelegates, getGatewayVaults, getPrescribedNames, getPrescribedObservers, getPrimaryName, getTokenCost, getVault, listArNSRecords, listArNSReservedNames, listArNSReturnedNames, listGateways, } from './commands/readCommands.js';
24
+ import { getAllowedDelegates, getArNSRecord, getArNSReservedName, getArNSReturnedName, getCostDetails, getDelegations, getEpoch, getGateway, getGatewayDelegates, getGatewayVaults, getPrescribedNames, getPrescribedObservers, getPrimaryName, getTokenCost, getVault, listArNSRecords, listArNSReservedNames, listArNSReturnedNames, listGateways, } from './commands/readCommands.js';
24
25
  import { transfer } from './commands/transfer.js';
25
- import { addressAndVaultIdOptions, addressOptions, antStateOptions, buyRecordOptions, decreaseDelegateStakeOptions, delegateStakeOptions, epochOptions, getVaultOptions, globalOptions, initiatorOptions, joinNetworkOptions, nameOptions, nameWriteOptions, operatorStakeOptions, optionMap, paginationAddressOptions, paginationOptions, redelegateStakeOptions, tokenCostOptions, transferOptions, updateGatewaySettingsOptions, writeActionOptions, } from './options.js';
26
- import { applyOptions, arioProcessIdFromOptions, assertConfirmationPrompt, epochInputFromOptions, formatARIOWithCommas, getANTStateFromOptions, getLoggerFromOptions, makeCommand, paginationParamsFromOptions, positiveIntegerFromOptions, readANTFromOptions, readARIOFromOptions, recordTypeFromOptions, requiredAddressFromOptions, requiredAoSignerFromOptions, requiredPositiveIntegerFromOptions, requiredStringArrayFromOptions, requiredStringFromOptions, writeANTFromOptions, writeARIOFromOptions, writeActionTagsFromOptions, } from './utils.js';
26
+ import { addressAndVaultIdOptions, antStateOptions, arnsPurchaseOptions, buyRecordOptions, decreaseDelegateStakeOptions, delegateStakeOptions, epochOptions, getVaultOptions, globalOptions, joinNetworkOptions, operatorStakeOptions, optionMap, paginationAddressOptions, paginationOptions, redelegateStakeOptions, tokenCostOptions, transferOptions, updateGatewaySettingsOptions, writeActionOptions, } from './options.js';
27
+ import { applyOptions, arioProcessIdFromOptions, assertConfirmationPrompt, epochInputFromOptions, formatARIOWithCommas, getANTStateFromOptions, getLoggerFromOptions, makeCommand, paginationParamsFromOptions, readANTFromOptions, readARIOFromOptions, requiredAddressFromOptions, requiredAoSignerFromOptions, requiredStringArrayFromOptions, requiredStringFromOptions, writeANTFromOptions, writeActionTagsFromOptions, } from './utils.js';
27
28
  applyOptions(program
28
29
  .name('ar.io')
29
30
  .version(version)
@@ -52,7 +53,7 @@ makeCommand({
52
53
  makeCommand({
53
54
  name: 'get-gateway',
54
55
  description: 'Get the gateway of an address',
55
- options: addressOptions,
56
+ options: [optionMap.address],
56
57
  action: getGateway,
57
58
  });
58
59
  makeCommand({
@@ -70,7 +71,7 @@ makeCommand({
70
71
  makeCommand({
71
72
  name: 'get-delegations',
72
73
  description: 'Get all stake delegated to gateways from this address',
73
- options: addressOptions,
74
+ options: [optionMap.address],
74
75
  action: getDelegations,
75
76
  });
76
77
  makeCommand({
@@ -82,7 +83,7 @@ makeCommand({
82
83
  makeCommand({
83
84
  name: 'get-arns-record',
84
85
  description: 'Get an ArNS record by name',
85
- options: nameOptions,
86
+ options: [optionMap.name],
86
87
  action: getArNSRecord,
87
88
  });
88
89
  makeCommand({
@@ -94,7 +95,7 @@ makeCommand({
94
95
  makeCommand({
95
96
  name: 'get-arns-reserved-name',
96
97
  description: 'Get a reserved ArNS name',
97
- options: nameOptions,
98
+ options: [optionMap.name],
98
99
  action: getArNSReservedName,
99
100
  });
100
101
  makeCommand({
@@ -106,7 +107,7 @@ makeCommand({
106
107
  makeCommand({
107
108
  name: 'get-arns-returned-name',
108
109
  description: 'Get an ArNS returned name by name',
109
- options: nameOptions,
110
+ options: [optionMap.name],
110
111
  action: getArNSReturnedName,
111
112
  });
112
113
  makeCommand({
@@ -152,10 +153,16 @@ makeCommand({
152
153
  });
153
154
  makeCommand({
154
155
  name: 'get-token-cost',
155
- description: 'Get token cost',
156
+ description: 'Get token cost for an intended action',
156
157
  options: tokenCostOptions,
157
158
  action: getTokenCost,
158
159
  });
160
+ makeCommand({
161
+ name: 'get-cost-details',
162
+ description: 'Get expanded cost details for an intended action',
163
+ options: tokenCostOptions,
164
+ action: getCostDetails,
165
+ });
159
166
  makeCommand({
160
167
  name: 'list-vaults',
161
168
  description: 'Get all wallet vaults',
@@ -168,7 +175,7 @@ makeCommand({
168
175
  makeCommand({
169
176
  name: 'get-primary-name-request',
170
177
  description: 'Get primary name request',
171
- options: initiatorOptions,
178
+ options: [optionMap.initiator],
172
179
  action: (o) => readARIOFromOptions(o)
173
180
  .getPrimaryNameRequest({
174
181
  initiator: requiredStringFromOptions(o, 'initiator'),
@@ -188,7 +195,7 @@ makeCommand({
188
195
  makeCommand({
189
196
  name: 'get-primary-name',
190
197
  description: 'Get primary name',
191
- options: [...addressOptions, optionMap.name],
198
+ options: [optionMap.address, optionMap.name],
192
199
  action: getPrimaryName,
193
200
  });
194
201
  makeCommand({
@@ -202,12 +209,12 @@ makeCommand({
202
209
  makeCommand({
203
210
  name: 'balance',
204
211
  description: 'Get the balance of an address',
205
- options: addressOptions,
212
+ options: [optionMap.address],
206
213
  action: (options) => readARIOFromOptions(options)
207
214
  .getBalance({ address: requiredAddressFromOptions(options) })
208
215
  .then((result) => ({
209
216
  address: requiredAddressFromOptions(options),
210
- mIOBalance: result,
217
+ mARIOBalance: result,
211
218
  message: `Provided address current has a balance of ${formatARIOWithCommas(new mARIOToken(result).toARIO())} ARIO`,
212
219
  })),
213
220
  });
@@ -222,7 +229,7 @@ makeCommand({
222
229
  makeCommand({
223
230
  name: 'get-redelegation-fee',
224
231
  description: 'Get redelegation fee',
225
- options: addressOptions,
232
+ options: [optionMap.address],
226
233
  action: (options) => readARIOFromOptions(options).getRedelegationFee({
227
234
  address: requiredAddressFromOptions(options),
228
235
  }),
@@ -318,82 +325,31 @@ makeCommand({
318
325
  name: 'buy-record',
319
326
  description: 'Buy a record',
320
327
  options: buyRecordOptions,
321
- action: async (options) => {
322
- const ario = writeARIOFromOptions(options).ario;
323
- const name = requiredStringFromOptions(options, 'name');
324
- const type = recordTypeFromOptions(options);
325
- const years = positiveIntegerFromOptions(options, 'years');
326
- // TODO: Assert balance is sufficient for action
327
- // TODO: Assert record is not already owned
328
- const processId = options.processId;
329
- if (processId === undefined) {
330
- // TODO: Spawn ANT process, register it to ANT registry, get process ID
331
- throw new Error('Process ID must be provided for buy-record');
332
- }
333
- await assertConfirmationPrompt(`Are you sure you want to ${type} the record ${name}?`, options);
334
- return ario.buyRecord({
335
- name: requiredStringFromOptions(options, 'name'),
336
- processId,
337
- type,
338
- years,
339
- });
340
- },
328
+ action: buyRecordCLICommand,
341
329
  });
342
330
  makeCommand({
343
331
  name: 'upgrade-record',
344
332
  description: 'Upgrade the lease of a record to a permabuy',
345
- options: [...nameOptions, ...writeActionOptions],
346
- // TODO: could assert record is leased by sender, assert balance is sufficient
347
- action: async (options) => {
348
- const name = requiredStringFromOptions(options, 'name');
349
- await assertConfirmationPrompt(`Are you sure you want to upgrade the lease of ${name} to a permabuy?`, options);
350
- return writeARIOFromOptions(options).ario.upgradeRecord({
351
- name,
352
- });
353
- },
333
+ options: arnsPurchaseOptions,
334
+ action: upgradeRecordCLICommand,
354
335
  });
355
336
  makeCommand({
356
337
  name: 'extend-lease',
357
338
  description: 'Extend the lease of a record',
358
- options: [...writeActionOptions, optionMap.name, optionMap.years],
359
- action: async (options) => {
360
- const name = requiredStringFromOptions(options, 'name');
361
- const years = requiredPositiveIntegerFromOptions(options, 'years');
362
- await assertConfirmationPrompt(`Are you sure you want to extend the lease of ${name} by ${years}?`, options);
363
- return writeARIOFromOptions(options).ario.extendLease({
364
- name,
365
- years,
366
- }, writeActionTagsFromOptions(options));
367
- },
339
+ options: [...arnsPurchaseOptions, optionMap.years],
340
+ action: extendLeaseCLICommand,
368
341
  });
369
342
  makeCommand({
370
343
  name: 'increase-undername-limit',
371
344
  description: 'Increase the limit of a name',
372
- options: [...writeActionOptions, optionMap.name, optionMap.increaseCount],
373
- action: async (options) => {
374
- const name = requiredStringFromOptions(options, 'name');
375
- const increaseCount = requiredPositiveIntegerFromOptions(options, 'increaseCount');
376
- await assertConfirmationPrompt(`Are you sure you want to increase the undername limit of ${name} by ${increaseCount}?`, options);
377
- return writeARIOFromOptions(options).ario.increaseUndernameLimit({
378
- name,
379
- increaseCount,
380
- }, writeActionTagsFromOptions(options));
381
- },
345
+ options: [...arnsPurchaseOptions, optionMap.increaseCount],
346
+ action: increaseUndernameLimitCLICommand,
382
347
  });
383
348
  makeCommand({
384
349
  name: 'request-primary-name',
385
350
  description: 'Request a primary name',
386
- options: nameWriteOptions,
387
- action: async (options) => {
388
- // TODO: Assert balance is sufficient for action?
389
- // TODO: Assert name requested is not already owned
390
- // TODO: More assertions?
391
- const name = requiredStringFromOptions(options, 'name');
392
- await assertConfirmationPrompt(`Are you sure you want to request the primary name ${name}?`, options);
393
- return writeARIOFromOptions(options).ario.requestPrimaryName({
394
- name,
395
- });
396
- },
351
+ options: arnsPurchaseOptions,
352
+ action: requestPrimaryNameCLICommand,
397
353
  });
398
354
  makeCommand({
399
355
  name: 'spawn-ant',
@@ -0,0 +1,159 @@
1
+ import { assertConfirmationPrompt, assertEnoughBalanceForArNSPurchase, fundFromFromOptions, positiveIntegerFromOptions, recordTypeFromOptions, requiredPositiveIntegerFromOptions, requiredStringFromOptions, writeARIOFromOptions, writeActionTagsFromOptions, } from '../utils.js';
2
+ export async function buyRecordCLICommand(o) {
3
+ const { ario, signerAddress } = writeARIOFromOptions(o);
4
+ const name = requiredStringFromOptions(o, 'name');
5
+ const type = recordTypeFromOptions(o);
6
+ const years = positiveIntegerFromOptions(o, 'years');
7
+ const fundFrom = fundFromFromOptions(o);
8
+ const processId = o.processId;
9
+ if (processId === undefined) {
10
+ // TODO: Spawn ANT process, register it to ANT registry, get process ID
11
+ throw new Error('Process ID must be provided for buy-record');
12
+ }
13
+ if (!o.skipConfirmation) {
14
+ const existingRecord = await ario.getArNSRecord({
15
+ name,
16
+ });
17
+ if (existingRecord !== undefined) {
18
+ throw new Error(`ArNS Record ${name} is already owned`);
19
+ }
20
+ await assertEnoughBalanceForArNSPurchase({
21
+ ario,
22
+ address: signerAddress,
23
+ costDetailsParams: {
24
+ intent: 'Buy-Record',
25
+ type,
26
+ name,
27
+ years,
28
+ fundFrom,
29
+ fromAddress: signerAddress,
30
+ },
31
+ });
32
+ await assertConfirmationPrompt(`Are you sure you want to ${type} the record ${name}?`, o);
33
+ }
34
+ return ario.buyRecord({
35
+ name: requiredStringFromOptions(o, 'name'),
36
+ processId,
37
+ type,
38
+ years,
39
+ fundFrom: fundFromFromOptions(o),
40
+ }, writeActionTagsFromOptions(o));
41
+ }
42
+ export async function upgradeRecordCLICommand(o) {
43
+ const name = requiredStringFromOptions(o, 'name');
44
+ const { ario, signerAddress } = writeARIOFromOptions(o);
45
+ const fundFrom = fundFromFromOptions(o);
46
+ if (!o.skipConfirmation) {
47
+ const existingRecord = await ario.getArNSRecord({
48
+ name,
49
+ });
50
+ if (existingRecord === undefined) {
51
+ throw new Error(`ArNS Record ${name} does not exist`);
52
+ }
53
+ if (existingRecord.type === 'permabuy') {
54
+ throw new Error(`ArNS Record ${name} is already a permabuy`);
55
+ }
56
+ await assertEnoughBalanceForArNSPurchase({
57
+ ario,
58
+ address: signerAddress,
59
+ costDetailsParams: {
60
+ intent: 'Upgrade-Name',
61
+ name,
62
+ fundFrom,
63
+ fromAddress: signerAddress,
64
+ },
65
+ });
66
+ await assertConfirmationPrompt(`Are you sure you want to upgrade the lease of ${name} to a permabuy?`, o);
67
+ }
68
+ return ario.upgradeRecord({
69
+ name,
70
+ fundFrom,
71
+ });
72
+ }
73
+ export async function extendLeaseCLICommand(o) {
74
+ const name = requiredStringFromOptions(o, 'name');
75
+ const years = requiredPositiveIntegerFromOptions(o, 'years');
76
+ const fundFrom = fundFromFromOptions(o);
77
+ const { ario, signerAddress } = writeARIOFromOptions(o);
78
+ if (!o.skipConfirmation) {
79
+ const existingRecord = await ario.getArNSRecord({
80
+ name,
81
+ });
82
+ if (existingRecord === undefined) {
83
+ throw new Error(`ArNS Record ${name} does not exist`);
84
+ }
85
+ if (existingRecord.type === 'permabuy') {
86
+ throw new Error(`ArNS Record ${name} is a permabuy and cannot be extended`);
87
+ }
88
+ await assertEnoughBalanceForArNSPurchase({
89
+ ario: ario,
90
+ address: signerAddress,
91
+ costDetailsParams: {
92
+ intent: 'Extend-Lease',
93
+ name,
94
+ years,
95
+ fundFrom,
96
+ fromAddress: signerAddress,
97
+ },
98
+ });
99
+ await assertConfirmationPrompt(`Are you sure you want to extend the lease of ${name} by ${years}?`, o);
100
+ }
101
+ return ario.extendLease({
102
+ name,
103
+ years,
104
+ }, writeActionTagsFromOptions(o));
105
+ }
106
+ export async function increaseUndernameLimitCLICommand(o) {
107
+ const name = requiredStringFromOptions(o, 'name');
108
+ const increaseCount = requiredPositiveIntegerFromOptions(o, 'increaseCount');
109
+ const fundFrom = fundFromFromOptions(o);
110
+ const { ario, signerAddress } = writeARIOFromOptions(o);
111
+ if (!o.skipConfirmation) {
112
+ const existingRecord = await ario.getArNSRecord({
113
+ name,
114
+ });
115
+ if (existingRecord === undefined) {
116
+ throw new Error(`ArNS Record ${name} does not exist`);
117
+ }
118
+ await assertEnoughBalanceForArNSPurchase({
119
+ ario,
120
+ address: signerAddress,
121
+ costDetailsParams: {
122
+ intent: 'Increase-Undername-Limit',
123
+ name,
124
+ quantity: increaseCount,
125
+ fundFrom,
126
+ fromAddress: signerAddress,
127
+ },
128
+ });
129
+ await assertConfirmationPrompt(`Are you sure you want to increase the undername limit of ${name} by ${increaseCount}?`, o);
130
+ }
131
+ return ario.increaseUndernameLimit({
132
+ name,
133
+ increaseCount,
134
+ }, writeActionTagsFromOptions(o));
135
+ }
136
+ export async function requestPrimaryNameCLICommand(o) {
137
+ const { ario, signerAddress } = writeARIOFromOptions(o);
138
+ const fundFrom = fundFromFromOptions(o);
139
+ const name = requiredStringFromOptions(o, 'name');
140
+ if (!o.skipConfirmation) {
141
+ // TODO: Assert name requested is not already owned?
142
+ // TODO: More assertions?
143
+ await assertEnoughBalanceForArNSPurchase({
144
+ ario,
145
+ address: signerAddress,
146
+ costDetailsParams: {
147
+ intent: 'Primary-Name-Request',
148
+ name,
149
+ fromAddress: signerAddress,
150
+ fundFrom,
151
+ },
152
+ });
153
+ await assertConfirmationPrompt(`Are you sure you want to request the primary name ${name}?`, o);
154
+ }
155
+ return ario.requestPrimaryName({
156
+ name,
157
+ fundFrom,
158
+ }, writeActionTagsFromOptions(o));
159
+ }
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import prompts from 'prompts';
17
17
  import { mARIOToken } from '../../node/index.js';
18
- import { assertConfirmationPrompt, assertEnoughBalance, formatARIOWithCommas, gatewaySettingsFromOptions, redelegateParamsFromOptions, requiredAddressFromOptions, requiredMIOFromOptions as requiredMARIOFromOptions, requiredStringArrayFromOptions, requiredStringFromOptions, requiredTargetAndQuantityFromOptions, stringifyJsonForCLIDisplay, writeARIOFromOptions, writeActionTagsFromOptions, } from '../utils.js';
18
+ import { assertConfirmationPrompt, assertEnoughMARIOBalance, formatARIOWithCommas, gatewaySettingsFromOptions, redelegateParamsFromOptions, requiredAddressFromOptions, requiredMARIOFromOptions, requiredStringArrayFromOptions, requiredStringFromOptions, requiredTargetAndQuantityFromOptions, stringifyJsonForCLIDisplay, writeARIOFromOptions, writeActionTagsFromOptions, } from '../utils.js';
19
19
  export async function joinNetwork(options) {
20
20
  const { ario, signerAddress } = writeARIOFromOptions(options);
21
21
  const mARIOQuantity = requiredMARIOFromOptions(options, 'operatorStake');
@@ -34,7 +34,11 @@ export async function joinNetwork(options) {
34
34
  if (settings.operators.minStake > mARIOQuantity.valueOf()) {
35
35
  throw new Error(`The minimum operator stake is ${formatARIOWithCommas(new mARIOToken(settings.operators.minStake).toARIO())} ARIO. Please provide a higher stake.`);
36
36
  }
37
- await assertEnoughBalance(ario, signerAddress, mARIOQuantity.toARIO());
37
+ await assertEnoughMARIOBalance({
38
+ ario,
39
+ address: signerAddress,
40
+ mARIOQuantity,
41
+ });
38
42
  await assertConfirmationPrompt(`Gateway Settings:\n\n${JSON.stringify(settings, null, 2)}\n\nYou are about to stake ${formatARIOWithCommas(mARIOQuantity.toARIO())} ARIO to join the AR.IO network\nAre you sure?\n`, options);
39
43
  }
40
44
  const result = await ario.joinNetwork(settings, writeActionTagsFromOptions(options));
@@ -1,21 +1,5 @@
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
1
  import { mARIOToken } from '../../types/token.js';
18
- import { addressFromOptions, epochInputFromOptions, formatARIOWithCommas, paginationParamsFromOptions, readARIOFromOptions, requiredAddressFromOptions, requiredStringFromOptions, } from '../utils.js';
2
+ import { addressFromOptions, epochInputFromOptions, formatARIOWithCommas, fundFromFromOptions, getTokenCostParamsFromOptions, paginationParamsFromOptions, readARIOFromOptions, requiredAddressFromOptions, requiredStringFromOptions, } from '../utils.js';
19
3
  export async function getGateway(o) {
20
4
  const address = requiredAddressFromOptions(o);
21
5
  const gateway = await readARIOFromOptions(o).getGateway({
@@ -115,32 +99,26 @@ export async function getPrescribedNames(o) {
115
99
  : { message: `No prescribed names found for epoch ${epoch}` };
116
100
  }
117
101
  export async function getTokenCost(o) {
118
- o.intent ??= 'Buy-Record';
119
- o.type ??= 'lease';
120
- if (!isValidIntent(o.intent)) {
121
- throw new Error(`Invalid intent. Valid intents are: ${validIntents.join(', ')}`);
122
- }
123
- if (o.type !== 'lease' && o.type !== 'permabuy') {
124
- throw new Error(`Invalid type. Valid types are: lease, permabuy`);
125
- }
126
- if (o.type === 'lease' &&
127
- intentsUsingYears.includes(o.intent) &&
128
- o.years === undefined) {
129
- throw new Error('Years is required for lease type');
130
- }
131
- const tokenCost = await readARIOFromOptions(o).getTokenCost({
132
- type: o.type,
133
- quantity: o.quantity !== undefined ? +o.quantity : undefined,
134
- years: o.years !== undefined ? +o.years : undefined,
135
- intent: o.intent,
136
- name: requiredStringFromOptions(o, 'name'),
137
- });
102
+ const tokenCost = await readARIOFromOptions(o).getTokenCost(getTokenCostParamsFromOptions(o));
138
103
  const output = {
139
- mIOTokenCost: tokenCost,
104
+ mARIOTokenCost: tokenCost,
140
105
  message: `The cost of the provided action is ${formatARIOWithCommas(new mARIOToken(tokenCost).toARIO())} ARIO`,
141
106
  };
142
107
  return output;
143
108
  }
109
+ export async function getCostDetails(o) {
110
+ const costDetails = await readARIOFromOptions(o).getCostDetails({
111
+ ...getTokenCostParamsFromOptions(o),
112
+ fundFrom: fundFromFromOptions(o),
113
+ });
114
+ const output = {
115
+ ...costDetails,
116
+ message: `The cost of the provided action is ${formatARIOWithCommas(new mARIOToken(costDetails.tokenCost).toARIO())} ARIO${costDetails.fundingPlan && costDetails.fundingPlan.shortfall > 0
117
+ ? `. Insufficient funds for action. There is a shortfall of ${formatARIOWithCommas(new mARIOToken(costDetails.fundingPlan.shortfall).toARIO())} ARIO`
118
+ : ''}`,
119
+ };
120
+ return output;
121
+ }
144
122
  export async function getPrimaryName(o) {
145
123
  const address = addressFromOptions(o);
146
124
  const name = o.name;
@@ -1,9 +1,13 @@
1
- import { assertEnoughBalance, confirmationPrompt, formatARIOWithCommas, requiredTargetAndQuantityFromOptions, writeARIOFromOptions, writeActionTagsFromOptions, } from '../utils.js';
1
+ import { assertEnoughMARIOBalance, confirmationPrompt, formatARIOWithCommas, requiredTargetAndQuantityFromOptions, writeARIOFromOptions, writeActionTagsFromOptions, } from '../utils.js';
2
2
  export async function transfer(options) {
3
3
  const { target, arioQuantity } = requiredTargetAndQuantityFromOptions(options);
4
4
  const { ario, signerAddress } = writeARIOFromOptions(options);
5
5
  if (!options.skipConfirmation) {
6
- await assertEnoughBalance(ario, signerAddress, arioQuantity);
6
+ await assertEnoughMARIOBalance({
7
+ ario,
8
+ address: signerAddress,
9
+ mARIOQuantity: arioQuantity.toMARIO(),
10
+ });
7
11
  const confirm = await confirmationPrompt(`Are you sure you want to transfer ${formatARIOWithCommas(arioQuantity)} ARIO to ${target}?`);
8
12
  if (!confirm) {
9
13
  return { message: 'Transfer aborted by user' };
@@ -234,6 +234,10 @@ export const optionMap = {
234
234
  description: 'Include failed gateways in the list',
235
235
  type: 'array',
236
236
  },
237
+ fundFrom: {
238
+ alias: '--fund-from <fundFrom>',
239
+ description: 'Where to fund the action from. e.g. "balance", "stakes", or "any',
240
+ },
237
241
  };
238
242
  export const walletOptions = [
239
243
  optionMap.walletFile,
@@ -248,11 +252,13 @@ export const globalOptions = [
248
252
  optionMap.cuUrl,
249
253
  ];
250
254
  export const writeActionOptions = [optionMap.skipConfirmation, optionMap.tags];
251
- export const addressOptions = [optionMap.address];
252
- export const nameOptions = [optionMap.name];
253
- export const initiatorOptions = [optionMap.initiator];
255
+ export const arnsPurchaseOptions = [
256
+ ...writeActionOptions,
257
+ optionMap.name,
258
+ optionMap.fundFrom,
259
+ ];
254
260
  export const epochOptions = [optionMap.epochIndex, optionMap.timestamp];
255
- export const addressAndVaultIdOptions = [...addressOptions, optionMap.vaultId];
261
+ export const addressAndVaultIdOptions = [optionMap.address, optionMap.vaultId];
256
262
  export const nameWriteOptions = [...writeActionOptions, optionMap.name];
257
263
  export const paginationOptions = [
258
264
  optionMap.cursor,
@@ -271,6 +277,8 @@ export const tokenCostOptions = [
271
277
  optionMap.type,
272
278
  optionMap.years,
273
279
  optionMap.quantity,
280
+ optionMap.address,
281
+ optionMap.fundFrom,
274
282
  ];
275
283
  export const transferOptions = [
276
284
  ...writeActionOptions,
@@ -307,8 +315,7 @@ export const joinNetworkOptions = [
307
315
  optionMap.operatorStake,
308
316
  ];
309
317
  export const buyRecordOptions = [
310
- ...writeActionOptions,
311
- optionMap.name,
318
+ ...arnsPurchaseOptions,
312
319
  optionMap.quantity,
313
320
  optionMap.type,
314
321
  optionMap.years,
@@ -17,7 +17,7 @@ import { connect } from '@permaweb/aoconnect';
17
17
  import { program } from 'commander';
18
18
  import { readFileSync } from 'fs';
19
19
  import prompts from 'prompts';
20
- import { ANT, AOProcess, ARIO, ARIOToken, ARIO_DEVNET_PROCESS_ID, ARIO_TESTNET_PROCESS_ID, ArweaveSigner, Logger, createAoSigner, fromB64Url, initANTStateForAddress, mARIOToken, sha256B64Url, } from '../node/index.js';
20
+ import { ANT, AOProcess, ARIO, ARIOToken, ARIO_DEVNET_PROCESS_ID, ARIO_TESTNET_PROCESS_ID, ArweaveSigner, Logger, createAoSigner, fromB64Url, fundFromOptions, initANTStateForAddress, isValidFundFrom, isValidIntent, mARIOToken, sha256B64Url, validIntents, } from '../node/index.js';
21
21
  import { globalOptions } from './options.js';
22
22
  export function stringifyJsonForCLIDisplay(json) {
23
23
  return JSON.stringify(json, null, 2);
@@ -141,6 +141,9 @@ export function formatARIOWithCommas(value) {
141
141
  }
142
142
  return integerWithCommas + '.' + decimalPart;
143
143
  }
144
+ export function formatMARIOToARIOWithCommas(value) {
145
+ return formatARIOWithCommas(value.toARIO());
146
+ }
144
147
  /** helper to get address from --address option first, then check wallet options */
145
148
  export function addressFromOptions(options) {
146
149
  if (options.address !== undefined) {
@@ -265,16 +268,34 @@ export function recordTypeFromOptions(options) {
265
268
  }
266
269
  return options.type;
267
270
  }
268
- export function requiredMIOFromOptions(options, key) {
271
+ export function requiredMARIOFromOptions(options, key) {
269
272
  if (options[key] === undefined) {
270
273
  throw new Error(`No ${key} provided. Use --${key} denominated in ARIO`);
271
274
  }
272
275
  return new ARIOToken(+options[key]).toMARIO();
273
276
  }
274
- export async function assertEnoughBalance(ario, address, arioQuantity) {
277
+ export async function assertEnoughBalanceForArNSPurchase({ ario, address, costDetailsParams, }) {
278
+ const costDetails = await ario.getCostDetails(costDetailsParams);
279
+ if (costDetails.fundingPlan) {
280
+ if (costDetails.fundingPlan.shortfall > 0) {
281
+ throw new Error(`Insufficient balance for action. Shortfall: ${formatMARIOToARIOWithCommas(new mARIOToken(costDetails.fundingPlan.shortfall))}\n${JSON.stringify(costDetails, null, 2)}`);
282
+ }
283
+ }
284
+ else {
285
+ await assertEnoughMARIOBalance({
286
+ ario,
287
+ address,
288
+ mARIOQuantity: costDetails.tokenCost,
289
+ });
290
+ }
291
+ }
292
+ export async function assertEnoughMARIOBalance({ address, ario, mARIOQuantity, }) {
293
+ if (typeof mARIOQuantity === 'number') {
294
+ mARIOQuantity = new mARIOToken(mARIOQuantity);
295
+ }
275
296
  const balance = await ario.getBalance({ address });
276
- if (balance < arioQuantity.toMARIO().valueOf()) {
277
- throw new Error(`Insufficient ARIO balance for action. Balance available: ${new mARIOToken(balance).toARIO()} ARIO`);
297
+ if (balance < mARIOQuantity.valueOf()) {
298
+ throw new Error(`Insufficient ARIO balance for action. Balance available: ${formatMARIOToARIOWithCommas(new mARIOToken(balance))} ARIO`);
278
299
  }
279
300
  }
280
301
  export async function confirmationPrompt(message) {
@@ -364,3 +385,30 @@ export function getANTStateFromOptions(options) {
364
385
  ttlSeconds: options.ttlSeconds !== undefined ? +options.ttlSeconds : 3600,
365
386
  });
366
387
  }
388
+ export function getTokenCostParamsFromOptions(o) {
389
+ o.intent ??= 'Buy-Record';
390
+ o.type ??= 'lease';
391
+ o.years ??= '1';
392
+ if (!isValidIntent(o.intent)) {
393
+ throw new Error(`Invalid intent. Valid intents are: ${validIntents.join(', ')}`);
394
+ }
395
+ if (o.type !== 'lease' && o.type !== 'permabuy') {
396
+ throw new Error(`Invalid type. Valid types are: lease, permabuy`);
397
+ }
398
+ return {
399
+ type: o.type,
400
+ quantity: o.quantity !== undefined ? +o.quantity : undefined,
401
+ years: +o.years,
402
+ intent: o.intent,
403
+ name: requiredStringFromOptions(o, 'name'),
404
+ fromAddress: addressFromOptions(o),
405
+ };
406
+ }
407
+ export function fundFromFromOptions(o) {
408
+ if (o.fundFrom !== undefined) {
409
+ if (!isValidFundFrom(o.fundFrom)) {
410
+ throw new Error(`Invalid fund from: ${o.fundFrom}. Please use one of ${fundFromOptions.join(', ')}`);
411
+ }
412
+ }
413
+ return o.fundFrom ?? 'balance';
414
+ }