@ar.io/sdk 3.0.0 → 3.1.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 +38 -0
- package/bundles/web.bundle.min.js +69 -69
- package/lib/cjs/cli/cli.js +8 -2
- package/lib/cjs/cli/commands/readCommands.js +22 -22
- package/lib/cjs/cli/options.js +6 -0
- package/lib/cjs/cli/utils.js +21 -1
- package/lib/cjs/common/contracts/ao-process.js +12 -3
- package/lib/cjs/common/io.js +47 -1
- package/lib/cjs/types/io.js +6 -1
- package/lib/cjs/utils/base64.js +10 -1
- package/lib/cjs/version.js +1 -1
- package/lib/esm/cli/cli.js +9 -3
- package/lib/esm/cli/commands/readCommands.js +21 -22
- package/lib/esm/cli/options.js +6 -0
- package/lib/esm/cli/utils.js +20 -1
- package/lib/esm/common/contracts/ao-process.js +12 -3
- package/lib/esm/common/io.js +47 -1
- package/lib/esm/types/io.js +4 -0
- package/lib/esm/utils/base64.js +9 -1
- package/lib/esm/version.js +1 -1
- package/lib/types/cli/commands/readCommands.d.ts +24 -2
- package/lib/types/cli/options.d.ts +4 -0
- package/lib/types/cli/utils.d.ts +9 -1
- package/lib/types/common/contracts/ao-process.d.ts +2 -1
- package/lib/types/common/io.d.ts +2 -1
- package/lib/types/types/io.d.ts +31 -3
- package/lib/types/utils/base64.d.ts +1 -0
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -1
package/lib/cjs/cli/cli.js
CHANGED
|
@@ -154,10 +154,16 @@ const utils_js_1 = require("./utils.js");
|
|
|
154
154
|
});
|
|
155
155
|
(0, utils_js_1.makeCommand)({
|
|
156
156
|
name: 'get-token-cost',
|
|
157
|
-
description: 'Get token cost',
|
|
157
|
+
description: 'Get token cost for an intended action',
|
|
158
158
|
options: options_js_1.tokenCostOptions,
|
|
159
159
|
action: readCommands_js_1.getTokenCost,
|
|
160
160
|
});
|
|
161
|
+
(0, utils_js_1.makeCommand)({
|
|
162
|
+
name: 'get-cost-details',
|
|
163
|
+
description: 'Get expanded cost details for an intended action',
|
|
164
|
+
options: options_js_1.tokenCostOptions,
|
|
165
|
+
action: readCommands_js_1.getCostDetails,
|
|
166
|
+
});
|
|
161
167
|
(0, utils_js_1.makeCommand)({
|
|
162
168
|
name: 'list-vaults',
|
|
163
169
|
description: 'Get all wallet vaults',
|
|
@@ -209,7 +215,7 @@ const utils_js_1 = require("./utils.js");
|
|
|
209
215
|
.getBalance({ address: (0, utils_js_1.requiredAddressFromOptions)(options) })
|
|
210
216
|
.then((result) => ({
|
|
211
217
|
address: (0, utils_js_1.requiredAddressFromOptions)(options),
|
|
212
|
-
|
|
218
|
+
mARIOBalance: result,
|
|
213
219
|
message: `Provided address current has a balance of ${(0, utils_js_1.formatARIOWithCommas)(new token_js_1.mARIOToken(result).toARIO())} ARIO`,
|
|
214
220
|
})),
|
|
215
221
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getVault = exports.getGatewayVaults = exports.getPrimaryName = exports.getTokenCost = exports.getPrescribedNames = exports.getPrescribedObservers = exports.getEpoch = exports.listArNSReturnedNames = exports.getArNSReturnedName = exports.listArNSReservedNames = exports.getArNSReservedName = exports.listArNSRecords = exports.getArNSRecord = exports.getAllowedDelegates = exports.getDelegations = exports.getGatewayDelegates = exports.listGateways = exports.getGateway = void 0;
|
|
3
|
+
exports.getVault = exports.getGatewayVaults = exports.getPrimaryName = exports.getCostDetails = exports.getTokenCost = exports.getPrescribedNames = exports.getPrescribedObservers = exports.getEpoch = exports.listArNSReturnedNames = exports.getArNSReturnedName = exports.listArNSReservedNames = exports.getArNSReservedName = exports.listArNSRecords = exports.getArNSRecord = exports.getAllowedDelegates = exports.getDelegations = exports.getGatewayDelegates = exports.listGateways = exports.getGateway = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
6
6
|
*
|
|
@@ -132,33 +132,33 @@ async function getPrescribedNames(o) {
|
|
|
132
132
|
}
|
|
133
133
|
exports.getPrescribedNames = getPrescribedNames;
|
|
134
134
|
async function getTokenCost(o) {
|
|
135
|
-
o.
|
|
136
|
-
o.type ??= 'lease';
|
|
137
|
-
if (!(0, io_js_1.isValidIntent)(o.intent)) {
|
|
138
|
-
throw new Error(`Invalid intent. Valid intents are: ${io_js_1.validIntents.join(', ')}`);
|
|
139
|
-
}
|
|
140
|
-
if (o.type !== 'lease' && o.type !== 'permabuy') {
|
|
141
|
-
throw new Error(`Invalid type. Valid types are: lease, permabuy`);
|
|
142
|
-
}
|
|
143
|
-
if (o.type === 'lease' &&
|
|
144
|
-
io_js_1.intentsUsingYears.includes(o.intent) &&
|
|
145
|
-
o.years === undefined) {
|
|
146
|
-
throw new Error('Years is required for lease type');
|
|
147
|
-
}
|
|
148
|
-
const tokenCost = await (0, utils_js_1.readARIOFromOptions)(o).getTokenCost({
|
|
149
|
-
type: o.type,
|
|
150
|
-
quantity: o.quantity !== undefined ? +o.quantity : undefined,
|
|
151
|
-
years: o.years !== undefined ? +o.years : undefined,
|
|
152
|
-
intent: o.intent,
|
|
153
|
-
name: (0, utils_js_1.requiredStringFromOptions)(o, 'name'),
|
|
154
|
-
});
|
|
135
|
+
const tokenCost = await (0, utils_js_1.readARIOFromOptions)(o).getTokenCost((0, utils_js_1.getTokenCostParamsFromOptions)(o));
|
|
155
136
|
const output = {
|
|
156
|
-
|
|
137
|
+
mARIOTokenCost: tokenCost,
|
|
157
138
|
message: `The cost of the provided action is ${(0, utils_js_1.formatARIOWithCommas)(new token_js_1.mARIOToken(tokenCost).toARIO())} ARIO`,
|
|
158
139
|
};
|
|
159
140
|
return output;
|
|
160
141
|
}
|
|
161
142
|
exports.getTokenCost = getTokenCost;
|
|
143
|
+
async function getCostDetails(o) {
|
|
144
|
+
if (o.fundFrom !== undefined) {
|
|
145
|
+
if (!(0, io_js_1.isValidFundFrom)(o.fundFrom)) {
|
|
146
|
+
throw new Error(`Invalid fund from: ${o.fundFrom}. Please use one of ${io_js_1.fundFromOptions.join(', ')}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const costDetails = await (0, utils_js_1.readARIOFromOptions)(o).getCostDetails({
|
|
150
|
+
...(0, utils_js_1.getTokenCostParamsFromOptions)(o),
|
|
151
|
+
fundFrom: o.fundFrom,
|
|
152
|
+
});
|
|
153
|
+
const output = {
|
|
154
|
+
...costDetails,
|
|
155
|
+
message: `The cost of the provided action is ${(0, utils_js_1.formatARIOWithCommas)(new token_js_1.mARIOToken(costDetails.tokenCost).toARIO())} ARIO${costDetails.fundingPlan && costDetails.fundingPlan.shortfall > 0
|
|
156
|
+
? `. Insufficient funds for action. There is a shortfall of ${(0, utils_js_1.formatARIOWithCommas)(new token_js_1.mARIOToken(costDetails.fundingPlan.shortfall).toARIO())} ARIO`
|
|
157
|
+
: ''}`,
|
|
158
|
+
};
|
|
159
|
+
return output;
|
|
160
|
+
}
|
|
161
|
+
exports.getCostDetails = getCostDetails;
|
|
162
162
|
async function getPrimaryName(o) {
|
|
163
163
|
const address = (0, utils_js_1.addressFromOptions)(o);
|
|
164
164
|
const name = o.name;
|
package/lib/cjs/cli/options.js
CHANGED
|
@@ -237,6 +237,10 @@ exports.optionMap = {
|
|
|
237
237
|
description: 'Include failed gateways in the list',
|
|
238
238
|
type: 'array',
|
|
239
239
|
},
|
|
240
|
+
fundFrom: {
|
|
241
|
+
alias: '--fund-from <fundFrom>',
|
|
242
|
+
description: 'Where to fund the action from. e.g. "balance", "stakes", or "any',
|
|
243
|
+
},
|
|
240
244
|
};
|
|
241
245
|
exports.walletOptions = [
|
|
242
246
|
exports.optionMap.walletFile,
|
|
@@ -274,6 +278,8 @@ exports.tokenCostOptions = [
|
|
|
274
278
|
exports.optionMap.type,
|
|
275
279
|
exports.optionMap.years,
|
|
276
280
|
exports.optionMap.quantity,
|
|
281
|
+
exports.optionMap.address,
|
|
282
|
+
exports.optionMap.fundFrom,
|
|
277
283
|
];
|
|
278
284
|
exports.transferOptions = [
|
|
279
285
|
...exports.writeActionOptions,
|
package/lib/cjs/cli/utils.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getANTStateFromOptions = exports.requiredPositiveIntegerFromOptions = exports.positiveIntegerFromOptions = exports.requiredStringArrayFromOptions = exports.requiredStringFromOptions = exports.writeANTFromOptions = exports.readANTFromOptions = exports.requiredProcessIdFromOptions = exports.assertConfirmationPrompt = exports.confirmationPrompt = exports.assertEnoughBalance = exports.requiredMIOFromOptions = exports.recordTypeFromOptions = exports.redelegateParamsFromOptions = exports.requiredTargetAndQuantityFromOptions = exports.gatewaySettingsFromOptions = exports.writeActionTagsFromOptions = exports.requiredInitiatorFromOptions = exports.epochInputFromOptions = exports.paginationParamsFromOptions = exports.requiredAddressFromOptions = exports.addressFromOptions = exports.formatARIOWithCommas = exports.writeARIOFromOptions = exports.requiredAoSignerFromOptions = exports.requiredContractSignerFromOptions = exports.readARIOFromOptions = exports.getLoggerFromOptions = exports.jwkToAddress = exports.requiredJwkFromOptions = exports.arioProcessIdFromOptions = exports.makeCommand = exports.applyOptions = exports.runCommand = exports.stringifyJsonForCLIDisplay = void 0;
|
|
6
|
+
exports.getTokenCostParamsFromOptions = exports.getANTStateFromOptions = exports.requiredPositiveIntegerFromOptions = exports.positiveIntegerFromOptions = exports.requiredStringArrayFromOptions = exports.requiredStringFromOptions = exports.writeANTFromOptions = exports.readANTFromOptions = exports.requiredProcessIdFromOptions = exports.assertConfirmationPrompt = exports.confirmationPrompt = exports.assertEnoughBalance = exports.requiredMIOFromOptions = exports.recordTypeFromOptions = exports.redelegateParamsFromOptions = exports.requiredTargetAndQuantityFromOptions = exports.gatewaySettingsFromOptions = exports.writeActionTagsFromOptions = exports.requiredInitiatorFromOptions = exports.epochInputFromOptions = exports.paginationParamsFromOptions = exports.requiredAddressFromOptions = exports.addressFromOptions = exports.formatARIOWithCommas = exports.writeARIOFromOptions = exports.requiredAoSignerFromOptions = exports.requiredContractSignerFromOptions = exports.readARIOFromOptions = exports.getLoggerFromOptions = exports.jwkToAddress = exports.requiredJwkFromOptions = exports.arioProcessIdFromOptions = exports.makeCommand = exports.applyOptions = exports.runCommand = exports.stringifyJsonForCLIDisplay = void 0;
|
|
7
7
|
/**
|
|
8
8
|
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
9
9
|
*
|
|
@@ -405,3 +405,23 @@ function getANTStateFromOptions(options) {
|
|
|
405
405
|
});
|
|
406
406
|
}
|
|
407
407
|
exports.getANTStateFromOptions = getANTStateFromOptions;
|
|
408
|
+
function getTokenCostParamsFromOptions(o) {
|
|
409
|
+
o.intent ??= 'Buy-Record';
|
|
410
|
+
o.type ??= 'lease';
|
|
411
|
+
o.years ??= '1';
|
|
412
|
+
if (!(0, index_js_1.isValidIntent)(o.intent)) {
|
|
413
|
+
throw new Error(`Invalid intent. Valid intents are: ${index_js_1.validIntents.join(', ')}`);
|
|
414
|
+
}
|
|
415
|
+
if (o.type !== 'lease' && o.type !== 'permabuy') {
|
|
416
|
+
throw new Error(`Invalid type. Valid types are: lease, permabuy`);
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
type: o.type,
|
|
420
|
+
quantity: o.quantity !== undefined ? +o.quantity : undefined,
|
|
421
|
+
years: +o.years,
|
|
422
|
+
intent: o.intent,
|
|
423
|
+
name: requiredStringFromOptions(o, 'name'),
|
|
424
|
+
fromAddress: addressFromOptions(o),
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
exports.getTokenCostParamsFromOptions = getTokenCostParamsFromOptions;
|
|
@@ -17,6 +17,7 @@ exports.AOProcess = void 0;
|
|
|
17
17
|
* limitations under the License.
|
|
18
18
|
*/
|
|
19
19
|
const aoconnect_1 = require("@permaweb/aoconnect");
|
|
20
|
+
const base64_js_1 = require("../../utils/base64.js");
|
|
20
21
|
const json_js_1 = require("../../utils/json.js");
|
|
21
22
|
const version_js_1 = require("../../version.js");
|
|
22
23
|
const error_js_1 = require("../error.js");
|
|
@@ -30,7 +31,7 @@ class AOProcess {
|
|
|
30
31
|
this.logger = logger;
|
|
31
32
|
this.ao = ao;
|
|
32
33
|
}
|
|
33
|
-
async read({ tags, retries = 3, }) {
|
|
34
|
+
async read({ tags, retries = 3, fromAddress, }) {
|
|
34
35
|
let attempts = 0;
|
|
35
36
|
let lastError;
|
|
36
37
|
while (attempts < retries) {
|
|
@@ -39,10 +40,14 @@ class AOProcess {
|
|
|
39
40
|
tags,
|
|
40
41
|
});
|
|
41
42
|
// map tags to inputs
|
|
42
|
-
const
|
|
43
|
+
const dryRunInput = {
|
|
43
44
|
process: this.processId,
|
|
44
45
|
tags,
|
|
45
|
-
}
|
|
46
|
+
};
|
|
47
|
+
if (fromAddress !== undefined) {
|
|
48
|
+
dryRunInput['Owner'] = fromAddress;
|
|
49
|
+
}
|
|
50
|
+
const result = await this.ao.dryrun(dryRunInput);
|
|
46
51
|
this.logger.debug(`Read interaction result`, {
|
|
47
52
|
result,
|
|
48
53
|
});
|
|
@@ -89,16 +94,20 @@ class AOProcess {
|
|
|
89
94
|
processId: this.processId,
|
|
90
95
|
});
|
|
91
96
|
// TODO: do a read as a dry run to check if the process supports the action
|
|
97
|
+
// anchor is a random text produce non-deterministic messages IDs when deterministic signers are provided (ETH)
|
|
98
|
+
const anchor = (0, base64_js_1.getRandomText)(32);
|
|
92
99
|
const messageId = await this.ao.message({
|
|
93
100
|
process: this.processId,
|
|
94
101
|
// TODO: any other default tags we want to add?
|
|
95
102
|
tags: [...tags, { name: 'AR-IO-SDK', value: version_js_1.version }],
|
|
96
103
|
data,
|
|
97
104
|
signer,
|
|
105
|
+
anchor,
|
|
98
106
|
});
|
|
99
107
|
this.logger.debug(`Sent message to process`, {
|
|
100
108
|
messageId,
|
|
101
109
|
processId: this.processId,
|
|
110
|
+
anchor,
|
|
102
111
|
});
|
|
103
112
|
// check the result of the send interaction
|
|
104
113
|
const output = await this.ao.result({
|
package/lib/cjs/common/io.js
CHANGED
|
@@ -265,7 +265,7 @@ class ARIOReadable {
|
|
|
265
265
|
tags: (0, arweave_js_1.pruneTags)(allTags),
|
|
266
266
|
});
|
|
267
267
|
}
|
|
268
|
-
async getTokenCost({ intent, type, years, name, quantity, }) {
|
|
268
|
+
async getTokenCost({ intent, type, years, name, quantity, fromAddress, }) {
|
|
269
269
|
const allTags = [
|
|
270
270
|
{ name: 'Action', value: 'Token-Cost' },
|
|
271
271
|
{
|
|
@@ -302,6 +302,52 @@ class ARIOReadable {
|
|
|
302
302
|
];
|
|
303
303
|
return this.process.read({
|
|
304
304
|
tags: (0, arweave_js_1.pruneTags)(allTags),
|
|
305
|
+
fromAddress,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
// TODO: Can overload this function to refine different types of cost details params
|
|
309
|
+
async getCostDetails({ intent, type, years, name, quantity, fromAddress, fundFrom, }) {
|
|
310
|
+
const allTags = [
|
|
311
|
+
{ name: 'Action', value: 'Get-Cost-Details-For-Action' },
|
|
312
|
+
{
|
|
313
|
+
name: 'Intent',
|
|
314
|
+
value: intent,
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
name: 'Name',
|
|
318
|
+
value: name,
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
name: 'Years',
|
|
322
|
+
value: years?.toString(),
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
name: 'Quantity',
|
|
326
|
+
value: quantity?.toString(),
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
name: 'Purchase-Type',
|
|
330
|
+
value: type,
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
name: 'Fund-From',
|
|
334
|
+
value: fundFrom,
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
name: 'Timestamp',
|
|
338
|
+
value: (await this.arweave.blocks
|
|
339
|
+
.getCurrent()
|
|
340
|
+
.then((block) => {
|
|
341
|
+
return { timestamp: block.timestamp * 1000 };
|
|
342
|
+
})
|
|
343
|
+
.catch(() => {
|
|
344
|
+
return { timestamp: Date.now() }; // fallback to current time
|
|
345
|
+
})).timestamp.toString(),
|
|
346
|
+
},
|
|
347
|
+
];
|
|
348
|
+
return this.process.read({
|
|
349
|
+
tags: (0, arweave_js_1.pruneTags)(allTags),
|
|
350
|
+
fromAddress,
|
|
305
351
|
});
|
|
306
352
|
}
|
|
307
353
|
async getRegistrationFees() {
|
package/lib/cjs/types/io.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isLeasedArNSRecord = exports.isProcessIdConfiguration = exports.isProcessConfiguration = exports.isValidIntent = exports.intentsUsingYears = exports.validIntents = void 0;
|
|
3
|
+
exports.isLeasedArNSRecord = exports.isProcessIdConfiguration = exports.isProcessConfiguration = exports.isValidFundFrom = exports.fundFromOptions = exports.isValidIntent = exports.intentsUsingYears = exports.validIntents = void 0;
|
|
4
4
|
const arweave_js_1 = require("../utils/arweave.js");
|
|
5
5
|
exports.validIntents = [
|
|
6
6
|
'Buy-Record',
|
|
@@ -14,6 +14,11 @@ const isValidIntent = (intent) => {
|
|
|
14
14
|
return exports.validIntents.indexOf(intent) !== -1;
|
|
15
15
|
};
|
|
16
16
|
exports.isValidIntent = isValidIntent;
|
|
17
|
+
exports.fundFromOptions = ['balance', 'stakes', 'any'];
|
|
18
|
+
const isValidFundFrom = (fundFrom) => {
|
|
19
|
+
return exports.fundFromOptions.indexOf(fundFrom) !== -1;
|
|
20
|
+
};
|
|
21
|
+
exports.isValidFundFrom = isValidFundFrom;
|
|
17
22
|
// Typeguard functions
|
|
18
23
|
function isProcessConfiguration(config) {
|
|
19
24
|
return 'process' in config;
|
package/lib/cjs/utils/base64.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.sha256B64Url = exports.toB64Url = exports.fromB64Url = void 0;
|
|
3
|
+
exports.getRandomText = exports.sha256B64Url = exports.toB64Url = exports.fromB64Url = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
6
6
|
*
|
|
@@ -52,3 +52,12 @@ function sha256B64Url(input) {
|
|
|
52
52
|
return toB64Url((0, crypto_1.createHash)('sha256').update(Uint8Array.from(input)).digest());
|
|
53
53
|
}
|
|
54
54
|
exports.sha256B64Url = sha256B64Url;
|
|
55
|
+
function getRandomText(length = 32) {
|
|
56
|
+
// Generate a buffer of random bytes
|
|
57
|
+
const buffer = (0, crypto_1.randomBytes)(length);
|
|
58
|
+
// Convert bytes to hexadecimal string
|
|
59
|
+
return Array.from(buffer, (byte) => byte.toString(16).padStart(2, '0'))
|
|
60
|
+
.join('')
|
|
61
|
+
.slice(0, length);
|
|
62
|
+
}
|
|
63
|
+
exports.getRandomText = getRandomText;
|
package/lib/cjs/version.js
CHANGED
package/lib/esm/cli/cli.js
CHANGED
|
@@ -20,7 +20,7 @@ import { spawnANT } from '../node/index.js';
|
|
|
20
20
|
import { mARIOToken } from '../types/token.js';
|
|
21
21
|
import { version } from '../version.js';
|
|
22
22
|
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';
|
|
23
|
+
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
24
|
import { transfer } from './commands/transfer.js';
|
|
25
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
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';
|
|
@@ -152,10 +152,16 @@ makeCommand({
|
|
|
152
152
|
});
|
|
153
153
|
makeCommand({
|
|
154
154
|
name: 'get-token-cost',
|
|
155
|
-
description: 'Get token cost',
|
|
155
|
+
description: 'Get token cost for an intended action',
|
|
156
156
|
options: tokenCostOptions,
|
|
157
157
|
action: getTokenCost,
|
|
158
158
|
});
|
|
159
|
+
makeCommand({
|
|
160
|
+
name: 'get-cost-details',
|
|
161
|
+
description: 'Get expanded cost details for an intended action',
|
|
162
|
+
options: tokenCostOptions,
|
|
163
|
+
action: getCostDetails,
|
|
164
|
+
});
|
|
159
165
|
makeCommand({
|
|
160
166
|
name: 'list-vaults',
|
|
161
167
|
description: 'Get all wallet vaults',
|
|
@@ -207,7 +213,7 @@ makeCommand({
|
|
|
207
213
|
.getBalance({ address: requiredAddressFromOptions(options) })
|
|
208
214
|
.then((result) => ({
|
|
209
215
|
address: requiredAddressFromOptions(options),
|
|
210
|
-
|
|
216
|
+
mARIOBalance: result,
|
|
211
217
|
message: `Provided address current has a balance of ${formatARIOWithCommas(new mARIOToken(result).toARIO())} ARIO`,
|
|
212
218
|
})),
|
|
213
219
|
});
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import {
|
|
16
|
+
import { fundFromOptions, isValidFundFrom, } from '../../types/io.js';
|
|
17
17
|
import { mARIOToken } from '../../types/token.js';
|
|
18
|
-
import { addressFromOptions, epochInputFromOptions, formatARIOWithCommas, paginationParamsFromOptions, readARIOFromOptions, requiredAddressFromOptions, requiredStringFromOptions, } from '../utils.js';
|
|
18
|
+
import { addressFromOptions, epochInputFromOptions, formatARIOWithCommas, getTokenCostParamsFromOptions, paginationParamsFromOptions, readARIOFromOptions, requiredAddressFromOptions, requiredStringFromOptions, } from '../utils.js';
|
|
19
19
|
export async function getGateway(o) {
|
|
20
20
|
const address = requiredAddressFromOptions(o);
|
|
21
21
|
const gateway = await readARIOFromOptions(o).getGateway({
|
|
@@ -115,29 +115,28 @@ export async function getPrescribedNames(o) {
|
|
|
115
115
|
: { message: `No prescribed names found for epoch ${epoch}` };
|
|
116
116
|
}
|
|
117
117
|
export async function getTokenCost(o) {
|
|
118
|
-
o.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (o.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
118
|
+
const tokenCost = await readARIOFromOptions(o).getTokenCost(getTokenCostParamsFromOptions(o));
|
|
119
|
+
const output = {
|
|
120
|
+
mARIOTokenCost: tokenCost,
|
|
121
|
+
message: `The cost of the provided action is ${formatARIOWithCommas(new mARIOToken(tokenCost).toARIO())} ARIO`,
|
|
122
|
+
};
|
|
123
|
+
return output;
|
|
124
|
+
}
|
|
125
|
+
export async function getCostDetails(o) {
|
|
126
|
+
if (o.fundFrom !== undefined) {
|
|
127
|
+
if (!isValidFundFrom(o.fundFrom)) {
|
|
128
|
+
throw new Error(`Invalid fund from: ${o.fundFrom}. Please use one of ${fundFromOptions.join(', ')}`);
|
|
129
|
+
}
|
|
130
130
|
}
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
years: o.years !== undefined ? +o.years : undefined,
|
|
135
|
-
intent: o.intent,
|
|
136
|
-
name: requiredStringFromOptions(o, 'name'),
|
|
131
|
+
const costDetails = await readARIOFromOptions(o).getCostDetails({
|
|
132
|
+
...getTokenCostParamsFromOptions(o),
|
|
133
|
+
fundFrom: o.fundFrom,
|
|
137
134
|
});
|
|
138
135
|
const output = {
|
|
139
|
-
|
|
140
|
-
message: `The cost of the provided action is ${formatARIOWithCommas(new mARIOToken(tokenCost).toARIO())} ARIO
|
|
136
|
+
...costDetails,
|
|
137
|
+
message: `The cost of the provided action is ${formatARIOWithCommas(new mARIOToken(costDetails.tokenCost).toARIO())} ARIO${costDetails.fundingPlan && costDetails.fundingPlan.shortfall > 0
|
|
138
|
+
? `. Insufficient funds for action. There is a shortfall of ${formatARIOWithCommas(new mARIOToken(costDetails.fundingPlan.shortfall).toARIO())} ARIO`
|
|
139
|
+
: ''}`,
|
|
141
140
|
};
|
|
142
141
|
return output;
|
|
143
142
|
}
|
package/lib/esm/cli/options.js
CHANGED
|
@@ -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,
|
|
@@ -271,6 +275,8 @@ export const tokenCostOptions = [
|
|
|
271
275
|
optionMap.type,
|
|
272
276
|
optionMap.years,
|
|
273
277
|
optionMap.quantity,
|
|
278
|
+
optionMap.address,
|
|
279
|
+
optionMap.fundFrom,
|
|
274
280
|
];
|
|
275
281
|
export const transferOptions = [
|
|
276
282
|
...writeActionOptions,
|
package/lib/esm/cli/utils.js
CHANGED
|
@@ -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, initANTStateForAddress, 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);
|
|
@@ -364,3 +364,22 @@ export function getANTStateFromOptions(options) {
|
|
|
364
364
|
ttlSeconds: options.ttlSeconds !== undefined ? +options.ttlSeconds : 3600,
|
|
365
365
|
});
|
|
366
366
|
}
|
|
367
|
+
export function getTokenCostParamsFromOptions(o) {
|
|
368
|
+
o.intent ??= 'Buy-Record';
|
|
369
|
+
o.type ??= 'lease';
|
|
370
|
+
o.years ??= '1';
|
|
371
|
+
if (!isValidIntent(o.intent)) {
|
|
372
|
+
throw new Error(`Invalid intent. Valid intents are: ${validIntents.join(', ')}`);
|
|
373
|
+
}
|
|
374
|
+
if (o.type !== 'lease' && o.type !== 'permabuy') {
|
|
375
|
+
throw new Error(`Invalid type. Valid types are: lease, permabuy`);
|
|
376
|
+
}
|
|
377
|
+
return {
|
|
378
|
+
type: o.type,
|
|
379
|
+
quantity: o.quantity !== undefined ? +o.quantity : undefined,
|
|
380
|
+
years: +o.years,
|
|
381
|
+
intent: o.intent,
|
|
382
|
+
name: requiredStringFromOptions(o, 'name'),
|
|
383
|
+
fromAddress: addressFromOptions(o),
|
|
384
|
+
};
|
|
385
|
+
}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { connect } from '@permaweb/aoconnect';
|
|
17
|
+
import { getRandomText } from '../../utils/base64.js';
|
|
17
18
|
import { safeDecode } from '../../utils/json.js';
|
|
18
19
|
import { version } from '../../version.js';
|
|
19
20
|
import { WriteInteractionError } from '../error.js';
|
|
@@ -27,7 +28,7 @@ export class AOProcess {
|
|
|
27
28
|
this.logger = logger;
|
|
28
29
|
this.ao = ao;
|
|
29
30
|
}
|
|
30
|
-
async read({ tags, retries = 3, }) {
|
|
31
|
+
async read({ tags, retries = 3, fromAddress, }) {
|
|
31
32
|
let attempts = 0;
|
|
32
33
|
let lastError;
|
|
33
34
|
while (attempts < retries) {
|
|
@@ -36,10 +37,14 @@ export class AOProcess {
|
|
|
36
37
|
tags,
|
|
37
38
|
});
|
|
38
39
|
// map tags to inputs
|
|
39
|
-
const
|
|
40
|
+
const dryRunInput = {
|
|
40
41
|
process: this.processId,
|
|
41
42
|
tags,
|
|
42
|
-
}
|
|
43
|
+
};
|
|
44
|
+
if (fromAddress !== undefined) {
|
|
45
|
+
dryRunInput['Owner'] = fromAddress;
|
|
46
|
+
}
|
|
47
|
+
const result = await this.ao.dryrun(dryRunInput);
|
|
43
48
|
this.logger.debug(`Read interaction result`, {
|
|
44
49
|
result,
|
|
45
50
|
});
|
|
@@ -86,16 +91,20 @@ export class AOProcess {
|
|
|
86
91
|
processId: this.processId,
|
|
87
92
|
});
|
|
88
93
|
// TODO: do a read as a dry run to check if the process supports the action
|
|
94
|
+
// anchor is a random text produce non-deterministic messages IDs when deterministic signers are provided (ETH)
|
|
95
|
+
const anchor = getRandomText(32);
|
|
89
96
|
const messageId = await this.ao.message({
|
|
90
97
|
process: this.processId,
|
|
91
98
|
// TODO: any other default tags we want to add?
|
|
92
99
|
tags: [...tags, { name: 'AR-IO-SDK', value: version }],
|
|
93
100
|
data,
|
|
94
101
|
signer,
|
|
102
|
+
anchor,
|
|
95
103
|
});
|
|
96
104
|
this.logger.debug(`Sent message to process`, {
|
|
97
105
|
messageId,
|
|
98
106
|
processId: this.processId,
|
|
107
|
+
anchor,
|
|
99
108
|
});
|
|
100
109
|
// check the result of the send interaction
|
|
101
110
|
const output = await this.ao.result({
|
package/lib/esm/common/io.js
CHANGED
|
@@ -261,7 +261,7 @@ export class ARIOReadable {
|
|
|
261
261
|
tags: pruneTags(allTags),
|
|
262
262
|
});
|
|
263
263
|
}
|
|
264
|
-
async getTokenCost({ intent, type, years, name, quantity, }) {
|
|
264
|
+
async getTokenCost({ intent, type, years, name, quantity, fromAddress, }) {
|
|
265
265
|
const allTags = [
|
|
266
266
|
{ name: 'Action', value: 'Token-Cost' },
|
|
267
267
|
{
|
|
@@ -298,6 +298,52 @@ export class ARIOReadable {
|
|
|
298
298
|
];
|
|
299
299
|
return this.process.read({
|
|
300
300
|
tags: pruneTags(allTags),
|
|
301
|
+
fromAddress,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
// TODO: Can overload this function to refine different types of cost details params
|
|
305
|
+
async getCostDetails({ intent, type, years, name, quantity, fromAddress, fundFrom, }) {
|
|
306
|
+
const allTags = [
|
|
307
|
+
{ name: 'Action', value: 'Get-Cost-Details-For-Action' },
|
|
308
|
+
{
|
|
309
|
+
name: 'Intent',
|
|
310
|
+
value: intent,
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
name: 'Name',
|
|
314
|
+
value: name,
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
name: 'Years',
|
|
318
|
+
value: years?.toString(),
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
name: 'Quantity',
|
|
322
|
+
value: quantity?.toString(),
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
name: 'Purchase-Type',
|
|
326
|
+
value: type,
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
name: 'Fund-From',
|
|
330
|
+
value: fundFrom,
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
name: 'Timestamp',
|
|
334
|
+
value: (await this.arweave.blocks
|
|
335
|
+
.getCurrent()
|
|
336
|
+
.then((block) => {
|
|
337
|
+
return { timestamp: block.timestamp * 1000 };
|
|
338
|
+
})
|
|
339
|
+
.catch(() => {
|
|
340
|
+
return { timestamp: Date.now() }; // fallback to current time
|
|
341
|
+
})).timestamp.toString(),
|
|
342
|
+
},
|
|
343
|
+
];
|
|
344
|
+
return this.process.read({
|
|
345
|
+
tags: pruneTags(allTags),
|
|
346
|
+
fromAddress,
|
|
301
347
|
});
|
|
302
348
|
}
|
|
303
349
|
async getRegistrationFees() {
|
package/lib/esm/types/io.js
CHANGED
|
@@ -10,6 +10,10 @@ export const intentsUsingYears = ['Buy-Record', 'Extend-Lease'];
|
|
|
10
10
|
export const isValidIntent = (intent) => {
|
|
11
11
|
return validIntents.indexOf(intent) !== -1;
|
|
12
12
|
};
|
|
13
|
+
export const fundFromOptions = ['balance', 'stakes', 'any'];
|
|
14
|
+
export const isValidFundFrom = (fundFrom) => {
|
|
15
|
+
return fundFromOptions.indexOf(fundFrom) !== -1;
|
|
16
|
+
};
|
|
13
17
|
// Typeguard functions
|
|
14
18
|
export function isProcessConfiguration(config) {
|
|
15
19
|
return 'process' in config;
|
package/lib/esm/utils/base64.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import { createHash } from 'crypto';
|
|
16
|
+
import { createHash, randomBytes } from 'crypto';
|
|
17
17
|
// safely encodes and decodes base64url strings to and from buffers
|
|
18
18
|
const BASE64_CHAR_62 = '+';
|
|
19
19
|
const BASE64_CHAR_63 = '/';
|
|
@@ -46,3 +46,11 @@ export function toB64Url(buffer) {
|
|
|
46
46
|
export function sha256B64Url(input) {
|
|
47
47
|
return toB64Url(createHash('sha256').update(Uint8Array.from(input)).digest());
|
|
48
48
|
}
|
|
49
|
+
export function getRandomText(length = 32) {
|
|
50
|
+
// Generate a buffer of random bytes
|
|
51
|
+
const buffer = randomBytes(length);
|
|
52
|
+
// Convert bytes to hexadecimal string
|
|
53
|
+
return Array.from(buffer, (byte) => byte.toString(16).padStart(2, '0'))
|
|
54
|
+
.join('')
|
|
55
|
+
.slice(0, length);
|
|
56
|
+
}
|
package/lib/esm/version.js
CHANGED