@ar.io/sdk 3.22.0-alpha.1 → 3.22.0-alpha.3
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/bundles/web.bundle.min.js +69 -69
- package/lib/cjs/cli/cli.js +1 -5
- package/lib/cjs/cli/options.js +1 -0
- package/lib/cjs/cli/utils.js +4 -0
- package/lib/cjs/common/ant.js +10 -2
- package/lib/cjs/common/hyperbeam/hb.js +173 -0
- package/lib/cjs/common/io.js +35 -1
- package/lib/cjs/utils/ao.js +10 -3
- package/lib/cjs/version.js +1 -1
- package/lib/esm/cli/cli.js +1 -5
- package/lib/esm/cli/options.js +1 -0
- package/lib/esm/cli/utils.js +4 -0
- package/lib/esm/common/ant.js +10 -2
- package/lib/esm/common/hyperbeam/hb.js +169 -0
- package/lib/esm/common/io.js +35 -1
- package/lib/esm/utils/ao.js +10 -3
- package/lib/esm/version.js +1 -1
- package/lib/types/common/hyperbeam/hb.d.ts +88 -0
- package/lib/types/common/io.d.ts +2 -0
- package/lib/types/types/common.d.ts +3 -0
- package/lib/types/utils/ao.d.ts +4 -2
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -1
package/lib/cjs/cli/cli.js
CHANGED
|
@@ -448,11 +448,7 @@ const utils_js_1 = require("./utils.js");
|
|
|
448
448
|
(0, utils_js_1.makeCommand)({
|
|
449
449
|
name: 'get-ants-for-address',
|
|
450
450
|
description: 'Get the list of ANTs owned by an address according to the ANT registry',
|
|
451
|
-
options: [
|
|
452
|
-
options_js_1.optionMap.address,
|
|
453
|
-
options_js_1.optionMap.antRegistryProcessId,
|
|
454
|
-
options_js_1.optionMap.hyperbeamUrl,
|
|
455
|
-
],
|
|
451
|
+
options: [options_js_1.optionMap.address, options_js_1.optionMap.antRegistryProcessId],
|
|
456
452
|
action: readCommands_js_1.listAntsForAddress,
|
|
457
453
|
});
|
|
458
454
|
// # ANTS
|
package/lib/cjs/cli/options.js
CHANGED
|
@@ -339,6 +339,7 @@ exports.globalOptions = [
|
|
|
339
339
|
exports.optionMap.debug,
|
|
340
340
|
exports.optionMap.arioProcessId,
|
|
341
341
|
exports.optionMap.cuUrl,
|
|
342
|
+
exports.optionMap.hyperbeamUrl,
|
|
342
343
|
];
|
|
343
344
|
exports.writeActionOptions = [exports.optionMap.skipConfirmation, exports.optionMap.tags];
|
|
344
345
|
exports.arnsPurchaseOptions = [
|
package/lib/cjs/cli/utils.js
CHANGED
|
@@ -181,6 +181,7 @@ function aoProcessFromOptions(options) {
|
|
|
181
181
|
function readARIOFromOptions(options) {
|
|
182
182
|
setLoggerIfDebug(options);
|
|
183
183
|
return index_js_1.ARIO.init({
|
|
184
|
+
hyperbeamUrl: options.hyperbeamUrl,
|
|
184
185
|
process: aoProcessFromOptions({
|
|
185
186
|
cuUrl: 'https://cu.ardrive.io', // default to ardrive cu for ARIO process
|
|
186
187
|
...options,
|
|
@@ -227,6 +228,7 @@ function writeARIOFromOptions(options) {
|
|
|
227
228
|
process: aoProcessFromOptions(options),
|
|
228
229
|
signer,
|
|
229
230
|
paymentUrl: options.paymentUrl,
|
|
231
|
+
hyperbeamUrl: options.hyperbeamUrl,
|
|
230
232
|
}),
|
|
231
233
|
signerAddress,
|
|
232
234
|
};
|
|
@@ -487,6 +489,7 @@ function ANTProcessFromOptions(options) {
|
|
|
487
489
|
function readANTFromOptions(options) {
|
|
488
490
|
return index_js_1.ANT.init({
|
|
489
491
|
process: ANTProcessFromOptions(options),
|
|
492
|
+
hyperbeamUrl: options.hyperbeamUrl,
|
|
490
493
|
});
|
|
491
494
|
}
|
|
492
495
|
function writeANTFromOptions(options, signer) {
|
|
@@ -494,6 +497,7 @@ function writeANTFromOptions(options, signer) {
|
|
|
494
497
|
return index_js_1.ANT.init({
|
|
495
498
|
process: ANTProcessFromOptions(options),
|
|
496
499
|
signer,
|
|
500
|
+
hyperbeamUrl: options.hyperbeamUrl,
|
|
497
501
|
});
|
|
498
502
|
}
|
|
499
503
|
function booleanFromOptions(options, key) {
|
package/lib/cjs/common/ant.js
CHANGED
|
@@ -67,6 +67,7 @@ class ANT {
|
|
|
67
67
|
: false;
|
|
68
68
|
const ario = index_js_2.ARIO.init({
|
|
69
69
|
process: new index_js_2.AOProcess({ processId: arioProcessId, ao }),
|
|
70
|
+
hyperbeamUrl,
|
|
70
71
|
});
|
|
71
72
|
const getAllAffiliatedNames = async () => {
|
|
72
73
|
let cursor = undefined;
|
|
@@ -147,6 +148,7 @@ class ANT {
|
|
|
147
148
|
logger,
|
|
148
149
|
antRegistryId,
|
|
149
150
|
onSigningProgress,
|
|
151
|
+
hyperbeamUrl,
|
|
150
152
|
});
|
|
151
153
|
// we could parallelize this, but then signing progress would be harder to track
|
|
152
154
|
const reassignedNames = {};
|
|
@@ -471,7 +473,10 @@ class AoANTReadable {
|
|
|
471
473
|
const currentModuleId = await this.getModuleId({ graphqlUrl, retries });
|
|
472
474
|
// Get all versions from the ANT registry
|
|
473
475
|
const antVersions = ant_versions_js_1.ANTVersions.init({
|
|
474
|
-
|
|
476
|
+
process: new index_js_2.AOProcess({
|
|
477
|
+
processId: antRegistryId,
|
|
478
|
+
ao: this.process.ao,
|
|
479
|
+
}),
|
|
475
480
|
});
|
|
476
481
|
const versions = await antVersions.getANTVersions();
|
|
477
482
|
// Find the version that matches our module ID
|
|
@@ -510,7 +515,10 @@ class AoANTReadable {
|
|
|
510
515
|
});
|
|
511
516
|
// Get all versions from the ANT registry
|
|
512
517
|
const antVersions = ant_versions_js_1.ANTVersions.init({
|
|
513
|
-
|
|
518
|
+
process: new index_js_2.AOProcess({
|
|
519
|
+
processId: antRegistryId,
|
|
520
|
+
ao: this.process.ao,
|
|
521
|
+
}),
|
|
514
522
|
});
|
|
515
523
|
const latestVersion = await antVersions.getLatestANTVersion();
|
|
516
524
|
return currentVersion === latestVersion.version;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HB = void 0;
|
|
4
|
+
const logger_js_1 = require("../logger.js");
|
|
5
|
+
class HB {
|
|
6
|
+
url;
|
|
7
|
+
processId;
|
|
8
|
+
isHyperBeamCompatible;
|
|
9
|
+
checkHyperBeamPromise;
|
|
10
|
+
logger;
|
|
11
|
+
hbTimeoutMs;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.url = config.url;
|
|
14
|
+
this.processId = config.processId;
|
|
15
|
+
this.logger = config.logger ?? logger_js_1.Logger.default;
|
|
16
|
+
this.hbTimeoutMs = config.hbTimeoutMs ?? 5000;
|
|
17
|
+
this.isHyperBeamCompatible = undefined;
|
|
18
|
+
this.checkHyperBeamPromise = this.checkHyperBeamCompatibility();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* fetches the meta data for the process
|
|
22
|
+
*
|
|
23
|
+
* @returns The meta data for the process
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const hyperbeam = new Hyperbeam({ url: 'https://hyperbeam.ario.permaweb.services', processId: 'qNvAoz0TgcH7DMg8BCVn8jF32QH5L6T29VjHxhHqqGE' });
|
|
27
|
+
* const meta = await hyperbeam.meta();
|
|
28
|
+
* console.log(meta);
|
|
29
|
+
*/
|
|
30
|
+
async meta() {
|
|
31
|
+
const url = new URL(`${this.url}/${this.processId}~process@1.0/meta`);
|
|
32
|
+
return this.fetchHyperbeamPath({
|
|
33
|
+
path: url.toString(),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* calls the process device /now function, which evaluates the current process state pulling new messages
|
|
38
|
+
* to get the latest state
|
|
39
|
+
*
|
|
40
|
+
* @param path - The path to the hb state
|
|
41
|
+
* @param json - Whether to return the result as JSON, defaults to true
|
|
42
|
+
* @returns The result of the compute operation
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* const hyperbeam = new Hyperbeam({ url: 'https://hyperbeam.ario.permaweb.services', processId: 'qNvAoz0TgcH7DMg8BCVn8jF32QH5L6T29VjHxhHqqGE' });
|
|
46
|
+
* const result = await hyperbeam.now({ path: 'balances/QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ' });
|
|
47
|
+
* console.log(result);
|
|
48
|
+
*/
|
|
49
|
+
async now({ path, json = false, }) {
|
|
50
|
+
return this.fetchHyperbeamPath({
|
|
51
|
+
path: `${this.url}/${this.processId}~process@1.0/now/${path}`,
|
|
52
|
+
json,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* calls the process device /compute function, which uses the currently evaluated state in the node
|
|
57
|
+
*
|
|
58
|
+
* @param path - The path to the compute resource
|
|
59
|
+
* @param json - Whether to return the result as JSON, defaults to true
|
|
60
|
+
* @returns The result of the compute operation
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* const hyperbeam = new Hyperbeam({ url: 'https://hyperbeam.ario.permaweb.services', processId: 'qNvAoz0TgcH7DMg8BCVn8jF32QH5L6T29VjHxhHqqGE' });
|
|
64
|
+
* const result = await hyperbeam.compute({ path: 'balances/QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ' });
|
|
65
|
+
* console.log(result);
|
|
66
|
+
*/
|
|
67
|
+
async compute({ path, json = false, }) {
|
|
68
|
+
return this.fetchHyperbeamPath({
|
|
69
|
+
path: `${this.url}/${this.processId}~process@1.0/compute/${path}`,
|
|
70
|
+
json,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Checks if the process is HyperBeam compatible and caches the result.
|
|
75
|
+
*
|
|
76
|
+
* @returns {Promise<boolean>} True if the process is HyperBeam compatible, false otherwise.
|
|
77
|
+
*/
|
|
78
|
+
async checkHyperBeamCompatibility({ minSlot, } = {}) {
|
|
79
|
+
// refetch if min slot is provided
|
|
80
|
+
if (minSlot !== undefined) {
|
|
81
|
+
this.isHyperBeamCompatible = undefined;
|
|
82
|
+
this.checkHyperBeamPromise = undefined;
|
|
83
|
+
}
|
|
84
|
+
if (this.checkHyperBeamPromise !== undefined) {
|
|
85
|
+
return this.checkHyperBeamPromise;
|
|
86
|
+
}
|
|
87
|
+
if (this.isHyperBeamCompatible !== undefined) {
|
|
88
|
+
return Promise.resolve(this.isHyperBeamCompatible);
|
|
89
|
+
}
|
|
90
|
+
const result = fetch(
|
|
91
|
+
// use /now to force a refresh of the cache state, then compute when calling it for keys
|
|
92
|
+
`${this.url.toString()}/${this.processId}~process@1.0/now`, {
|
|
93
|
+
method: 'HEAD',
|
|
94
|
+
signal: AbortSignal.timeout(this.hbTimeoutMs),
|
|
95
|
+
})
|
|
96
|
+
.then(async (res) => {
|
|
97
|
+
if (res.ok) {
|
|
98
|
+
if (minSlot !== undefined) {
|
|
99
|
+
const slotRes = await this.compute({
|
|
100
|
+
path: 'at-slot',
|
|
101
|
+
json: false,
|
|
102
|
+
});
|
|
103
|
+
const slot = Number(slotRes);
|
|
104
|
+
if (slot < minSlot) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
this.isHyperBeamCompatible = true;
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
this.isHyperBeamCompatible = false;
|
|
112
|
+
return false;
|
|
113
|
+
})
|
|
114
|
+
.catch((error) => {
|
|
115
|
+
this.logger.debug('Failed to check HyperBeam compatibility', {
|
|
116
|
+
cause: error,
|
|
117
|
+
});
|
|
118
|
+
this.isHyperBeamCompatible = false;
|
|
119
|
+
return false;
|
|
120
|
+
});
|
|
121
|
+
this.checkHyperBeamPromise = result;
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
async fetchHyperbeamPath({ path, json = true, }) {
|
|
125
|
+
try {
|
|
126
|
+
const url = new URL(path);
|
|
127
|
+
if (json) {
|
|
128
|
+
this.logger.debug('Fetching path as JSON', { path });
|
|
129
|
+
/**
|
|
130
|
+
* This is the (current) way to access data as json
|
|
131
|
+
* the old way is /~json@1.0/serialize path
|
|
132
|
+
*/
|
|
133
|
+
url.searchParams.set('require-codec', 'application/json');
|
|
134
|
+
url.searchParams.set('accept-bundle', 'true');
|
|
135
|
+
const res = await fetch(url);
|
|
136
|
+
if (!res.ok) {
|
|
137
|
+
throw new Error(`Failed to fetch path as JSON: ${res.statusText}`);
|
|
138
|
+
}
|
|
139
|
+
const jsonResult = await res
|
|
140
|
+
.json()
|
|
141
|
+
.then((json) => json)
|
|
142
|
+
.catch((error) => {
|
|
143
|
+
this.logger.error('Failed to parse JSON', {
|
|
144
|
+
cause: error,
|
|
145
|
+
});
|
|
146
|
+
throw new Error(`Received response but failed to parse JSON: ${error.message}`);
|
|
147
|
+
});
|
|
148
|
+
if (typeof jsonResult !== 'object' ||
|
|
149
|
+
jsonResult === null ||
|
|
150
|
+
!('body' in jsonResult)) {
|
|
151
|
+
throw new Error('Response body missing in JSON response');
|
|
152
|
+
}
|
|
153
|
+
return jsonResult.body;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
this.logger.debug('Fetching path as text', { path });
|
|
157
|
+
const res = await fetch(url);
|
|
158
|
+
if (!res.ok) {
|
|
159
|
+
throw new Error(`Failed to fetch path: ${res.statusText}`);
|
|
160
|
+
}
|
|
161
|
+
const body = await res.text();
|
|
162
|
+
return body;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
this.logger.error('Failed to fetch path as JSON', {
|
|
167
|
+
cause: error,
|
|
168
|
+
});
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
exports.HB = HB;
|
package/lib/cjs/common/io.js
CHANGED
|
@@ -27,6 +27,7 @@ const arweave_js_2 = require("./arweave.js");
|
|
|
27
27
|
const ao_process_js_1 = require("./contracts/ao-process.js");
|
|
28
28
|
const error_js_1 = require("./error.js");
|
|
29
29
|
const faucet_js_1 = require("./faucet.js");
|
|
30
|
+
const hb_js_1 = require("./hyperbeam/hb.js");
|
|
30
31
|
const logger_js_1 = require("./logger.js");
|
|
31
32
|
const turbo_js_1 = require("./turbo.js");
|
|
32
33
|
class ARIO {
|
|
@@ -104,9 +105,9 @@ class ARIOReadable {
|
|
|
104
105
|
hyperbeamUrl;
|
|
105
106
|
paymentProvider; // TODO: this could be an array/map of payment providers
|
|
106
107
|
logger = logger_js_1.Logger.default;
|
|
108
|
+
hb;
|
|
107
109
|
constructor(config) {
|
|
108
110
|
this.arweave = config?.arweave ?? arweave_js_2.defaultArweave;
|
|
109
|
-
this.hyperbeamUrl = config?.hyperbeamUrl;
|
|
110
111
|
if (config === undefined || Object.keys(config).length === 0) {
|
|
111
112
|
this.process = new ao_process_js_1.AOProcess({
|
|
112
113
|
processId: constants_js_1.ARIO_MAINNET_PROCESS_ID,
|
|
@@ -123,6 +124,19 @@ class ARIOReadable {
|
|
|
123
124
|
else {
|
|
124
125
|
throw new error_js_1.InvalidContractConfigurationError();
|
|
125
126
|
}
|
|
127
|
+
// only use hyperbeam if the client has provided a hyperbeamUrl
|
|
128
|
+
// this will avoid overwhelming the HyperBeam node with requests
|
|
129
|
+
// as we shift using HyperBEAM for all ANT operations
|
|
130
|
+
if (config?.hyperbeamUrl !== undefined) {
|
|
131
|
+
this.hyperbeamUrl = config.hyperbeamUrl;
|
|
132
|
+
this.hb = new hb_js_1.HB({
|
|
133
|
+
url: this.hyperbeamUrl,
|
|
134
|
+
processId: this.process.processId,
|
|
135
|
+
});
|
|
136
|
+
this.logger.debug(`Using HyperBEAM node for process ${this.process.processId}`, {
|
|
137
|
+
hyperbeamUrl: this.hyperbeamUrl,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
126
140
|
this.paymentProvider = turbo_js_1.TurboArNSPaymentFactory.init({
|
|
127
141
|
paymentUrl: config?.paymentUrl,
|
|
128
142
|
});
|
|
@@ -222,6 +236,24 @@ class ARIOReadable {
|
|
|
222
236
|
});
|
|
223
237
|
}
|
|
224
238
|
async getBalance({ address }) {
|
|
239
|
+
if (this.hb && (await this.hb.checkHyperBeamCompatibility())) {
|
|
240
|
+
this.logger.debug('Getting balance from HyperBEAM', { address });
|
|
241
|
+
const res = await this.hb
|
|
242
|
+
.compute({
|
|
243
|
+
path: `balances/${address}`,
|
|
244
|
+
})
|
|
245
|
+
.then((res) => Number(res))
|
|
246
|
+
.catch((error) => {
|
|
247
|
+
this.logger.error('Failed to get balance from HyperBEAM', {
|
|
248
|
+
cause: error,
|
|
249
|
+
});
|
|
250
|
+
return null;
|
|
251
|
+
});
|
|
252
|
+
if (res !== null)
|
|
253
|
+
return res;
|
|
254
|
+
// else fall through to CU read
|
|
255
|
+
this.logger.info('Failed to get balance from HyperBEAM, failing over to to CU read', { address });
|
|
256
|
+
}
|
|
225
257
|
return this.process.read({
|
|
226
258
|
tags: [
|
|
227
259
|
{ name: 'Action', value: 'Balance' },
|
|
@@ -649,6 +681,7 @@ class ARIOReadable {
|
|
|
649
681
|
ao: this.process.ao,
|
|
650
682
|
processId: nameData.processId,
|
|
651
683
|
}),
|
|
684
|
+
hyperbeamUrl: this.hyperbeamUrl,
|
|
652
685
|
});
|
|
653
686
|
const [owner, antRecord] = await Promise.all([
|
|
654
687
|
ant.getOwner(),
|
|
@@ -1286,6 +1319,7 @@ class ARIOWriteable extends ARIOReadable {
|
|
|
1286
1319
|
ao: this.process.ao,
|
|
1287
1320
|
}),
|
|
1288
1321
|
signer: this.signer,
|
|
1322
|
+
hyperbeamUrl: this.hyperbeamUrl,
|
|
1289
1323
|
});
|
|
1290
1324
|
// approve the primary name request with the ant
|
|
1291
1325
|
const approveResult = await antClient.approvePrimaryNameRequest({
|
package/lib/cjs/utils/ao.js
CHANGED
|
@@ -39,7 +39,7 @@ async function spawnANT({ signer, module, ao = (0, aoconnect_1.connect)({
|
|
|
39
39
|
MODE: 'legacy',
|
|
40
40
|
}), scheduler = constants_js_1.DEFAULT_SCHEDULER_ID, state, tags = [], antRegistryId = constants_js_1.ANT_REGISTRY_ID, logger = index_js_1.Logger.default, authority = constants_js_1.AO_AUTHORITY, onSigningProgress = (name, payload) => {
|
|
41
41
|
logger.debug('Signing progress', { name, payload });
|
|
42
|
-
}, }) {
|
|
42
|
+
}, hyperbeamUrl, }) {
|
|
43
43
|
if (state) {
|
|
44
44
|
(0, schema_js_1.parseSchemaResult)(ant_js_1.SpawnANTStateSchema, state);
|
|
45
45
|
}
|
|
@@ -194,7 +194,12 @@ async function spawnANT({ signer, module, ao = (0, aoconnect_1.connect)({
|
|
|
194
194
|
// check the ACL for the owner
|
|
195
195
|
const antRegistry = ant_registry_js_1.ANTRegistry.init({
|
|
196
196
|
signer,
|
|
197
|
-
|
|
197
|
+
process: new index_js_1.AOProcess({
|
|
198
|
+
processId: antRegistryId,
|
|
199
|
+
ao,
|
|
200
|
+
logger,
|
|
201
|
+
}),
|
|
202
|
+
hyperbeamUrl,
|
|
198
203
|
});
|
|
199
204
|
let attempts = 0;
|
|
200
205
|
const maxAttempts = 5;
|
|
@@ -225,7 +230,7 @@ async function spawnANT({ signer, module, ao = (0, aoconnect_1.connect)({
|
|
|
225
230
|
}
|
|
226
231
|
async function forkANT({ signer, antProcessId, logger = index_js_1.Logger.default, ao, moduleId, antRegistryId = constants_js_1.ANT_REGISTRY_ID, onSigningProgress = (name, payload) => {
|
|
227
232
|
logger.debug('Forking ANT', { name, payload });
|
|
228
|
-
}, }) {
|
|
233
|
+
}, hyperbeamUrl, }) {
|
|
229
234
|
// get the state of the current ANT and use it to spawn a new ANT
|
|
230
235
|
const ant = index_js_1.ANT.init({
|
|
231
236
|
process: new index_js_1.AOProcess({
|
|
@@ -233,6 +238,7 @@ async function forkANT({ signer, antProcessId, logger = index_js_1.Logger.defaul
|
|
|
233
238
|
ao,
|
|
234
239
|
logger,
|
|
235
240
|
}),
|
|
241
|
+
hyperbeamUrl,
|
|
236
242
|
});
|
|
237
243
|
const state = await ant.getState();
|
|
238
244
|
if (state === undefined) {
|
|
@@ -256,6 +262,7 @@ async function forkANT({ signer, antProcessId, logger = index_js_1.Logger.defaul
|
|
|
256
262
|
balances: state.Balances,
|
|
257
263
|
logo: state.Logo,
|
|
258
264
|
},
|
|
265
|
+
hyperbeamUrl,
|
|
259
266
|
});
|
|
260
267
|
return forkedProcessId;
|
|
261
268
|
}
|
package/lib/cjs/version.js
CHANGED
package/lib/esm/cli/cli.js
CHANGED
|
@@ -446,11 +446,7 @@ makeCommand({
|
|
|
446
446
|
makeCommand({
|
|
447
447
|
name: 'get-ants-for-address',
|
|
448
448
|
description: 'Get the list of ANTs owned by an address according to the ANT registry',
|
|
449
|
-
options: [
|
|
450
|
-
optionMap.address,
|
|
451
|
-
optionMap.antRegistryProcessId,
|
|
452
|
-
optionMap.hyperbeamUrl,
|
|
453
|
-
],
|
|
449
|
+
options: [optionMap.address, optionMap.antRegistryProcessId],
|
|
454
450
|
action: listAntsForAddress,
|
|
455
451
|
});
|
|
456
452
|
// # ANTS
|
package/lib/esm/cli/options.js
CHANGED
|
@@ -336,6 +336,7 @@ export const globalOptions = [
|
|
|
336
336
|
optionMap.debug,
|
|
337
337
|
optionMap.arioProcessId,
|
|
338
338
|
optionMap.cuUrl,
|
|
339
|
+
optionMap.hyperbeamUrl,
|
|
339
340
|
];
|
|
340
341
|
export const writeActionOptions = [optionMap.skipConfirmation, optionMap.tags];
|
|
341
342
|
export const arnsPurchaseOptions = [
|
package/lib/esm/cli/utils.js
CHANGED
|
@@ -127,6 +127,7 @@ function aoProcessFromOptions(options) {
|
|
|
127
127
|
export function readARIOFromOptions(options) {
|
|
128
128
|
setLoggerIfDebug(options);
|
|
129
129
|
return ARIO.init({
|
|
130
|
+
hyperbeamUrl: options.hyperbeamUrl,
|
|
130
131
|
process: aoProcessFromOptions({
|
|
131
132
|
cuUrl: 'https://cu.ardrive.io', // default to ardrive cu for ARIO process
|
|
132
133
|
...options,
|
|
@@ -173,6 +174,7 @@ export function writeARIOFromOptions(options) {
|
|
|
173
174
|
process: aoProcessFromOptions(options),
|
|
174
175
|
signer,
|
|
175
176
|
paymentUrl: options.paymentUrl,
|
|
177
|
+
hyperbeamUrl: options.hyperbeamUrl,
|
|
176
178
|
}),
|
|
177
179
|
signerAddress,
|
|
178
180
|
};
|
|
@@ -433,6 +435,7 @@ function ANTProcessFromOptions(options) {
|
|
|
433
435
|
export function readANTFromOptions(options) {
|
|
434
436
|
return ANT.init({
|
|
435
437
|
process: ANTProcessFromOptions(options),
|
|
438
|
+
hyperbeamUrl: options.hyperbeamUrl,
|
|
436
439
|
});
|
|
437
440
|
}
|
|
438
441
|
export function writeANTFromOptions(options, signer) {
|
|
@@ -440,6 +443,7 @@ export function writeANTFromOptions(options, signer) {
|
|
|
440
443
|
return ANT.init({
|
|
441
444
|
process: ANTProcessFromOptions(options),
|
|
442
445
|
signer,
|
|
446
|
+
hyperbeamUrl: options.hyperbeamUrl,
|
|
443
447
|
});
|
|
444
448
|
}
|
|
445
449
|
export function booleanFromOptions(options, key) {
|
package/lib/esm/common/ant.js
CHANGED
|
@@ -64,6 +64,7 @@ export class ANT {
|
|
|
64
64
|
: false;
|
|
65
65
|
const ario = ARIO.init({
|
|
66
66
|
process: new AOProcess({ processId: arioProcessId, ao }),
|
|
67
|
+
hyperbeamUrl,
|
|
67
68
|
});
|
|
68
69
|
const getAllAffiliatedNames = async () => {
|
|
69
70
|
let cursor = undefined;
|
|
@@ -144,6 +145,7 @@ export class ANT {
|
|
|
144
145
|
logger,
|
|
145
146
|
antRegistryId,
|
|
146
147
|
onSigningProgress,
|
|
148
|
+
hyperbeamUrl,
|
|
147
149
|
});
|
|
148
150
|
// we could parallelize this, but then signing progress would be harder to track
|
|
149
151
|
const reassignedNames = {};
|
|
@@ -467,7 +469,10 @@ export class AoANTReadable {
|
|
|
467
469
|
const currentModuleId = await this.getModuleId({ graphqlUrl, retries });
|
|
468
470
|
// Get all versions from the ANT registry
|
|
469
471
|
const antVersions = ANTVersions.init({
|
|
470
|
-
|
|
472
|
+
process: new AOProcess({
|
|
473
|
+
processId: antRegistryId,
|
|
474
|
+
ao: this.process.ao,
|
|
475
|
+
}),
|
|
471
476
|
});
|
|
472
477
|
const versions = await antVersions.getANTVersions();
|
|
473
478
|
// Find the version that matches our module ID
|
|
@@ -506,7 +511,10 @@ export class AoANTReadable {
|
|
|
506
511
|
});
|
|
507
512
|
// Get all versions from the ANT registry
|
|
508
513
|
const antVersions = ANTVersions.init({
|
|
509
|
-
|
|
514
|
+
process: new AOProcess({
|
|
515
|
+
processId: antRegistryId,
|
|
516
|
+
ao: this.process.ao,
|
|
517
|
+
}),
|
|
510
518
|
});
|
|
511
519
|
const latestVersion = await antVersions.getLatestANTVersion();
|
|
512
520
|
return currentVersion === latestVersion.version;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { Logger } from '../logger.js';
|
|
2
|
+
export class HB {
|
|
3
|
+
url;
|
|
4
|
+
processId;
|
|
5
|
+
isHyperBeamCompatible;
|
|
6
|
+
checkHyperBeamPromise;
|
|
7
|
+
logger;
|
|
8
|
+
hbTimeoutMs;
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.url = config.url;
|
|
11
|
+
this.processId = config.processId;
|
|
12
|
+
this.logger = config.logger ?? Logger.default;
|
|
13
|
+
this.hbTimeoutMs = config.hbTimeoutMs ?? 5000;
|
|
14
|
+
this.isHyperBeamCompatible = undefined;
|
|
15
|
+
this.checkHyperBeamPromise = this.checkHyperBeamCompatibility();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* fetches the meta data for the process
|
|
19
|
+
*
|
|
20
|
+
* @returns The meta data for the process
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const hyperbeam = new Hyperbeam({ url: 'https://hyperbeam.ario.permaweb.services', processId: 'qNvAoz0TgcH7DMg8BCVn8jF32QH5L6T29VjHxhHqqGE' });
|
|
24
|
+
* const meta = await hyperbeam.meta();
|
|
25
|
+
* console.log(meta);
|
|
26
|
+
*/
|
|
27
|
+
async meta() {
|
|
28
|
+
const url = new URL(`${this.url}/${this.processId}~process@1.0/meta`);
|
|
29
|
+
return this.fetchHyperbeamPath({
|
|
30
|
+
path: url.toString(),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* calls the process device /now function, which evaluates the current process state pulling new messages
|
|
35
|
+
* to get the latest state
|
|
36
|
+
*
|
|
37
|
+
* @param path - The path to the hb state
|
|
38
|
+
* @param json - Whether to return the result as JSON, defaults to true
|
|
39
|
+
* @returns The result of the compute operation
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* const hyperbeam = new Hyperbeam({ url: 'https://hyperbeam.ario.permaweb.services', processId: 'qNvAoz0TgcH7DMg8BCVn8jF32QH5L6T29VjHxhHqqGE' });
|
|
43
|
+
* const result = await hyperbeam.now({ path: 'balances/QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ' });
|
|
44
|
+
* console.log(result);
|
|
45
|
+
*/
|
|
46
|
+
async now({ path, json = false, }) {
|
|
47
|
+
return this.fetchHyperbeamPath({
|
|
48
|
+
path: `${this.url}/${this.processId}~process@1.0/now/${path}`,
|
|
49
|
+
json,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* calls the process device /compute function, which uses the currently evaluated state in the node
|
|
54
|
+
*
|
|
55
|
+
* @param path - The path to the compute resource
|
|
56
|
+
* @param json - Whether to return the result as JSON, defaults to true
|
|
57
|
+
* @returns The result of the compute operation
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const hyperbeam = new Hyperbeam({ url: 'https://hyperbeam.ario.permaweb.services', processId: 'qNvAoz0TgcH7DMg8BCVn8jF32QH5L6T29VjHxhHqqGE' });
|
|
61
|
+
* const result = await hyperbeam.compute({ path: 'balances/QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ' });
|
|
62
|
+
* console.log(result);
|
|
63
|
+
*/
|
|
64
|
+
async compute({ path, json = false, }) {
|
|
65
|
+
return this.fetchHyperbeamPath({
|
|
66
|
+
path: `${this.url}/${this.processId}~process@1.0/compute/${path}`,
|
|
67
|
+
json,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Checks if the process is HyperBeam compatible and caches the result.
|
|
72
|
+
*
|
|
73
|
+
* @returns {Promise<boolean>} True if the process is HyperBeam compatible, false otherwise.
|
|
74
|
+
*/
|
|
75
|
+
async checkHyperBeamCompatibility({ minSlot, } = {}) {
|
|
76
|
+
// refetch if min slot is provided
|
|
77
|
+
if (minSlot !== undefined) {
|
|
78
|
+
this.isHyperBeamCompatible = undefined;
|
|
79
|
+
this.checkHyperBeamPromise = undefined;
|
|
80
|
+
}
|
|
81
|
+
if (this.checkHyperBeamPromise !== undefined) {
|
|
82
|
+
return this.checkHyperBeamPromise;
|
|
83
|
+
}
|
|
84
|
+
if (this.isHyperBeamCompatible !== undefined) {
|
|
85
|
+
return Promise.resolve(this.isHyperBeamCompatible);
|
|
86
|
+
}
|
|
87
|
+
const result = fetch(
|
|
88
|
+
// use /now to force a refresh of the cache state, then compute when calling it for keys
|
|
89
|
+
`${this.url.toString()}/${this.processId}~process@1.0/now`, {
|
|
90
|
+
method: 'HEAD',
|
|
91
|
+
signal: AbortSignal.timeout(this.hbTimeoutMs),
|
|
92
|
+
})
|
|
93
|
+
.then(async (res) => {
|
|
94
|
+
if (res.ok) {
|
|
95
|
+
if (minSlot !== undefined) {
|
|
96
|
+
const slotRes = await this.compute({
|
|
97
|
+
path: 'at-slot',
|
|
98
|
+
json: false,
|
|
99
|
+
});
|
|
100
|
+
const slot = Number(slotRes);
|
|
101
|
+
if (slot < minSlot) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
this.isHyperBeamCompatible = true;
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
this.isHyperBeamCompatible = false;
|
|
109
|
+
return false;
|
|
110
|
+
})
|
|
111
|
+
.catch((error) => {
|
|
112
|
+
this.logger.debug('Failed to check HyperBeam compatibility', {
|
|
113
|
+
cause: error,
|
|
114
|
+
});
|
|
115
|
+
this.isHyperBeamCompatible = false;
|
|
116
|
+
return false;
|
|
117
|
+
});
|
|
118
|
+
this.checkHyperBeamPromise = result;
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
async fetchHyperbeamPath({ path, json = true, }) {
|
|
122
|
+
try {
|
|
123
|
+
const url = new URL(path);
|
|
124
|
+
if (json) {
|
|
125
|
+
this.logger.debug('Fetching path as JSON', { path });
|
|
126
|
+
/**
|
|
127
|
+
* This is the (current) way to access data as json
|
|
128
|
+
* the old way is /~json@1.0/serialize path
|
|
129
|
+
*/
|
|
130
|
+
url.searchParams.set('require-codec', 'application/json');
|
|
131
|
+
url.searchParams.set('accept-bundle', 'true');
|
|
132
|
+
const res = await fetch(url);
|
|
133
|
+
if (!res.ok) {
|
|
134
|
+
throw new Error(`Failed to fetch path as JSON: ${res.statusText}`);
|
|
135
|
+
}
|
|
136
|
+
const jsonResult = await res
|
|
137
|
+
.json()
|
|
138
|
+
.then((json) => json)
|
|
139
|
+
.catch((error) => {
|
|
140
|
+
this.logger.error('Failed to parse JSON', {
|
|
141
|
+
cause: error,
|
|
142
|
+
});
|
|
143
|
+
throw new Error(`Received response but failed to parse JSON: ${error.message}`);
|
|
144
|
+
});
|
|
145
|
+
if (typeof jsonResult !== 'object' ||
|
|
146
|
+
jsonResult === null ||
|
|
147
|
+
!('body' in jsonResult)) {
|
|
148
|
+
throw new Error('Response body missing in JSON response');
|
|
149
|
+
}
|
|
150
|
+
return jsonResult.body;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.logger.debug('Fetching path as text', { path });
|
|
154
|
+
const res = await fetch(url);
|
|
155
|
+
if (!res.ok) {
|
|
156
|
+
throw new Error(`Failed to fetch path: ${res.statusText}`);
|
|
157
|
+
}
|
|
158
|
+
const body = await res.text();
|
|
159
|
+
return body;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
this.logger.error('Failed to fetch path as JSON', {
|
|
164
|
+
cause: error,
|
|
165
|
+
});
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|