@ar.io/sdk 3.13.0-beta.1 → 3.14.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 +1 -1
- package/bundles/web.bundle.min.js +133 -136
- package/lib/cjs/cli/cli.js +8 -0
- package/lib/cjs/common/ant.js +102 -1
- package/lib/cjs/common/index.js +0 -2
- package/lib/cjs/utils/ant.js +32 -1
- package/lib/cjs/utils/hash.js +31 -83
- package/lib/cjs/version.js +1 -1
- package/lib/esm/cli/cli.js +8 -0
- package/lib/esm/common/ant.js +103 -2
- package/lib/esm/common/index.js +0 -2
- package/lib/esm/utils/ant.js +30 -0
- package/lib/esm/utils/hash.js +27 -74
- package/lib/esm/version.js +1 -1
- package/lib/types/common/ant.d.ts +9 -1
- package/lib/types/common/index.d.ts +0 -1
- package/lib/types/types/ant.d.ts +17 -0
- package/lib/types/types/io.d.ts +0 -3
- package/lib/types/utils/ant.d.ts +7 -1
- package/lib/types/utils/hash.d.ts +4 -8
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -2
- package/lib/cjs/common/wayfinder/gateways/network.js +0 -48
- package/lib/cjs/common/wayfinder/gateways/simple-cache.js +0 -35
- package/lib/cjs/common/wayfinder/gateways/static.js +0 -13
- package/lib/cjs/common/wayfinder/index.js +0 -48
- package/lib/cjs/common/wayfinder/routing/strategies/ping.js +0 -72
- package/lib/cjs/common/wayfinder/routing/strategies/preferred-with-fallback.js +0 -50
- package/lib/cjs/common/wayfinder/routing/strategies/random.js +0 -13
- package/lib/cjs/common/wayfinder/routing/strategies/round-robin.js +0 -42
- package/lib/cjs/common/wayfinder/routing/strategies/static.js +0 -29
- package/lib/cjs/common/wayfinder/verification/strategies/data-root-verifier.js +0 -110
- package/lib/cjs/common/wayfinder/verification/strategies/hash-verifier.js +0 -27
- package/lib/cjs/common/wayfinder/verification/trusted.js +0 -125
- package/lib/cjs/common/wayfinder/wayfinder.js +0 -508
- package/lib/cjs/types/wayfinder.js +0 -3
- package/lib/esm/common/wayfinder/gateways/network.js +0 -44
- package/lib/esm/common/wayfinder/gateways/simple-cache.js +0 -31
- package/lib/esm/common/wayfinder/gateways/static.js +0 -9
- package/lib/esm/common/wayfinder/index.js +0 -32
- package/lib/esm/common/wayfinder/routing/strategies/ping.js +0 -68
- package/lib/esm/common/wayfinder/routing/strategies/preferred-with-fallback.js +0 -46
- package/lib/esm/common/wayfinder/routing/strategies/random.js +0 -9
- package/lib/esm/common/wayfinder/routing/strategies/round-robin.js +0 -38
- package/lib/esm/common/wayfinder/routing/strategies/static.js +0 -25
- package/lib/esm/common/wayfinder/verification/strategies/data-root-verifier.js +0 -102
- package/lib/esm/common/wayfinder/verification/strategies/hash-verifier.js +0 -23
- package/lib/esm/common/wayfinder/verification/trusted.js +0 -121
- package/lib/esm/common/wayfinder/wayfinder.js +0 -499
- package/lib/esm/types/wayfinder.js +0 -2
- package/lib/types/common/wayfinder/gateways/network.d.ts +0 -33
- package/lib/types/common/wayfinder/gateways/simple-cache.d.ts +0 -31
- package/lib/types/common/wayfinder/gateways/static.d.ts +0 -23
- package/lib/types/common/wayfinder/index.d.ts +0 -27
- package/lib/types/common/wayfinder/routing/strategies/ping.d.ts +0 -27
- package/lib/types/common/wayfinder/routing/strategies/preferred-with-fallback.d.ts +0 -31
- package/lib/types/common/wayfinder/routing/strategies/random.d.ts +0 -21
- package/lib/types/common/wayfinder/routing/strategies/round-robin.d.ts +0 -29
- package/lib/types/common/wayfinder/routing/strategies/static.d.ts +0 -29
- package/lib/types/common/wayfinder/verification/strategies/data-root-verifier.d.ts +0 -27
- package/lib/types/common/wayfinder/verification/strategies/hash-verifier.d.ts +0 -26
- package/lib/types/common/wayfinder/verification/trusted.d.ts +0 -51
- package/lib/types/common/wayfinder/wayfinder.d.ts +0 -257
- package/lib/types/types/wayfinder.d.ts +0 -66
package/lib/cjs/cli/cli.js
CHANGED
|
@@ -479,6 +479,14 @@ const utils_js_1 = require("./utils.js");
|
|
|
479
479
|
return (0, utils_js_1.readANTFromOptions)(options).getTicker();
|
|
480
480
|
},
|
|
481
481
|
});
|
|
482
|
+
(0, utils_js_1.makeCommand)({
|
|
483
|
+
name: 'get-ant-logo',
|
|
484
|
+
description: 'Get the logo of an ANT process',
|
|
485
|
+
options: [options_js_1.optionMap.processId],
|
|
486
|
+
action: async (options) => {
|
|
487
|
+
return (0, utils_js_1.readANTFromOptions)(options).getLogo();
|
|
488
|
+
},
|
|
489
|
+
});
|
|
482
490
|
(0, utils_js_1.makeCommand)({
|
|
483
491
|
name: 'get-ant-balance',
|
|
484
492
|
description: 'Get the balance of an ANT process',
|
package/lib/cjs/common/ant.js
CHANGED
|
@@ -39,6 +39,8 @@ class AoANTReadable {
|
|
|
39
39
|
process;
|
|
40
40
|
processId;
|
|
41
41
|
strict;
|
|
42
|
+
hyperbeamUrl;
|
|
43
|
+
checkHyperBeamPromise;
|
|
42
44
|
constructor(config) {
|
|
43
45
|
this.strict = config.strict || false;
|
|
44
46
|
if ((0, index_js_1.isProcessConfiguration)(config)) {
|
|
@@ -53,8 +55,43 @@ class AoANTReadable {
|
|
|
53
55
|
throw new index_js_2.InvalidContractConfigurationError();
|
|
54
56
|
}
|
|
55
57
|
this.processId = this.process.processId;
|
|
58
|
+
this.hyperbeamUrl = config.hyperbeamUrl || 'https://permanode.xyz'; // TODO: replace this with hyperbeam.ario.permaweb.services once deployed
|
|
59
|
+
this.checkHyperBeamPromise = this.checkHyperBeamCompatibility();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if the process is hyperbeam compatible. If so, we'll use the hyperbeam node to fetch the state.
|
|
63
|
+
*
|
|
64
|
+
* @returns {Promise<boolean>} True if the process is hyperbeam compatible, false otherwise.
|
|
65
|
+
*/
|
|
66
|
+
async checkHyperBeamCompatibility() {
|
|
67
|
+
if (this.checkHyperBeamPromise !== undefined) {
|
|
68
|
+
return this.checkHyperBeamPromise;
|
|
69
|
+
}
|
|
70
|
+
const res = await fetch(`https://permanode.xyz/${this.processId}~process@1.0/now/cache`, {
|
|
71
|
+
method: 'HEAD',
|
|
72
|
+
});
|
|
73
|
+
let isHyperBeamCompatible = false;
|
|
74
|
+
if (res.ok) {
|
|
75
|
+
isHyperBeamCompatible = true;
|
|
76
|
+
}
|
|
77
|
+
this.checkHyperBeamPromise = Promise.resolve(isHyperBeamCompatible);
|
|
78
|
+
return isHyperBeamCompatible;
|
|
56
79
|
}
|
|
57
80
|
async getState({ strict } = { strict: this.strict }) {
|
|
81
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
82
|
+
const res = await fetch(`${this.hyperbeamUrl}/${this.processId}~process@1.0/now/cache/serialize~json@1.0`, {
|
|
83
|
+
method: 'GET',
|
|
84
|
+
redirect: 'follow',
|
|
85
|
+
mode: 'cors',
|
|
86
|
+
headers: {
|
|
87
|
+
'Content-Type': 'application/json',
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
if (!res.ok) {
|
|
91
|
+
throw new Error('Failed to fetch ant state');
|
|
92
|
+
}
|
|
93
|
+
return (0, ant_js_2.convertHyperBeamStateToAoANTState)((await res.json()));
|
|
94
|
+
}
|
|
58
95
|
const tags = [{ name: 'Action', value: 'State' }];
|
|
59
96
|
const res = await this.process.read({
|
|
60
97
|
tags,
|
|
@@ -67,6 +104,20 @@ class AoANTReadable {
|
|
|
67
104
|
return res;
|
|
68
105
|
}
|
|
69
106
|
async getInfo({ strict } = { strict: this.strict }) {
|
|
107
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
108
|
+
const state = await this.getState();
|
|
109
|
+
return {
|
|
110
|
+
Name: state.Name,
|
|
111
|
+
Ticker: state.Ticker,
|
|
112
|
+
Description: state.Description,
|
|
113
|
+
Keywords: state.Keywords,
|
|
114
|
+
Denomination: state.Denomination.toString(),
|
|
115
|
+
Owner: state.Owner,
|
|
116
|
+
Logo: state.Logo,
|
|
117
|
+
'Total-Supply': state.TotalSupply.toString(),
|
|
118
|
+
Handlers: [], // TODO: support for handler in patched state
|
|
119
|
+
};
|
|
120
|
+
}
|
|
70
121
|
const tags = [{ name: 'Action', value: 'Info' }];
|
|
71
122
|
const info = await this.process.read({
|
|
72
123
|
tags,
|
|
@@ -93,6 +144,15 @@ class AoANTReadable {
|
|
|
93
144
|
* ```
|
|
94
145
|
*/
|
|
95
146
|
async getRecord({ undername }, { strict } = { strict: this.strict }) {
|
|
147
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
148
|
+
const records = await this.getRecords();
|
|
149
|
+
const cachedRecord = records[undername];
|
|
150
|
+
// if the record is not found, throw an error
|
|
151
|
+
if (cachedRecord === undefined) {
|
|
152
|
+
throw new Error('Record not found');
|
|
153
|
+
}
|
|
154
|
+
return cachedRecord;
|
|
155
|
+
}
|
|
96
156
|
// TODO: use sortedANTRecords to get priority on all records, even if ANT does not have a priority set
|
|
97
157
|
const record = await this.process.read({
|
|
98
158
|
tags: [
|
|
@@ -113,6 +173,10 @@ class AoANTReadable {
|
|
|
113
173
|
* ````
|
|
114
174
|
*/
|
|
115
175
|
async getRecords({ strict } = { strict: this.strict }) {
|
|
176
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
177
|
+
const state = await this.getState();
|
|
178
|
+
return (0, ant_js_2.sortANTRecords)(state.Records);
|
|
179
|
+
}
|
|
116
180
|
const tags = [{ name: 'Action', value: 'Records' }];
|
|
117
181
|
const records = await this.process.read({
|
|
118
182
|
tags,
|
|
@@ -131,6 +195,10 @@ class AoANTReadable {
|
|
|
131
195
|
* ```
|
|
132
196
|
*/
|
|
133
197
|
async getOwner({ strict } = { strict: this.strict }) {
|
|
198
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
199
|
+
const state = await this.getState();
|
|
200
|
+
return state.Owner;
|
|
201
|
+
}
|
|
134
202
|
const info = await this.getInfo({ strict });
|
|
135
203
|
return info.Owner;
|
|
136
204
|
}
|
|
@@ -143,6 +211,10 @@ class AoANTReadable {
|
|
|
143
211
|
* ```
|
|
144
212
|
*/
|
|
145
213
|
async getControllers({ strict } = { strict: this.strict }) {
|
|
214
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
215
|
+
const state = await this.getState();
|
|
216
|
+
return state.Controllers;
|
|
217
|
+
}
|
|
146
218
|
const tags = [{ name: 'Action', value: 'Controllers' }];
|
|
147
219
|
const controllers = await this.process.read({
|
|
148
220
|
tags,
|
|
@@ -160,6 +232,10 @@ class AoANTReadable {
|
|
|
160
232
|
* ```
|
|
161
233
|
*/
|
|
162
234
|
async getName({ strict } = { strict: this.strict }) {
|
|
235
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
236
|
+
const state = await this.getState();
|
|
237
|
+
return state.Name;
|
|
238
|
+
}
|
|
163
239
|
const info = await this.getInfo({ strict });
|
|
164
240
|
return info.Name;
|
|
165
241
|
}
|
|
@@ -172,6 +248,10 @@ class AoANTReadable {
|
|
|
172
248
|
* ```
|
|
173
249
|
*/
|
|
174
250
|
async getTicker({ strict } = { strict: this.strict }) {
|
|
251
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
252
|
+
const state = await this.getState();
|
|
253
|
+
return state.Ticker;
|
|
254
|
+
}
|
|
175
255
|
const info = await this.getInfo({ strict });
|
|
176
256
|
return info.Ticker;
|
|
177
257
|
}
|
|
@@ -184,6 +264,21 @@ class AoANTReadable {
|
|
|
184
264
|
* ```
|
|
185
265
|
*/
|
|
186
266
|
async getBalances({ strict } = { strict: this.strict }) {
|
|
267
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
268
|
+
const res = await fetch(`${this.hyperbeamUrl}/${this.processId}~process@1.0/now/cache/balances/serialize~json@1.0`, {
|
|
269
|
+
method: 'GET',
|
|
270
|
+
redirect: 'follow',
|
|
271
|
+
mode: 'cors',
|
|
272
|
+
headers: {
|
|
273
|
+
'Content-Type': 'application/json',
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
if (!res.ok) {
|
|
277
|
+
throw new Error('Failed to fetch ant balances');
|
|
278
|
+
}
|
|
279
|
+
const result = (await res.json());
|
|
280
|
+
return result.balances;
|
|
281
|
+
}
|
|
187
282
|
const tags = [{ name: 'Action', value: 'Balances' }];
|
|
188
283
|
const balances = await this.process.read({
|
|
189
284
|
tags,
|
|
@@ -202,6 +297,10 @@ class AoANTReadable {
|
|
|
202
297
|
* ```
|
|
203
298
|
*/
|
|
204
299
|
async getBalance({ address }, { strict } = { strict: this.strict }) {
|
|
300
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
301
|
+
const balances = await this.getBalances();
|
|
302
|
+
return balances[address] ?? 0;
|
|
303
|
+
}
|
|
205
304
|
const tags = [
|
|
206
305
|
{ name: 'Action', value: 'Balance' },
|
|
207
306
|
{ name: 'Recipient', value: address },
|
|
@@ -222,6 +321,9 @@ class AoANTReadable {
|
|
|
222
321
|
* ```
|
|
223
322
|
*/
|
|
224
323
|
async getHandlers() {
|
|
324
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
325
|
+
throw new Error('Handlers are not supported on HyperBeam');
|
|
326
|
+
}
|
|
225
327
|
const info = await this.getInfo();
|
|
226
328
|
return (info.Handlers ?? info.HandlerNames);
|
|
227
329
|
}
|
|
@@ -486,7 +588,6 @@ class AoANTWriteable extends AoANTReadable {
|
|
|
486
588
|
/**
|
|
487
589
|
* Releases an ArNS name associated with the ANT. This will release the name to the public and allow anyone to register it. All primary names must be removed before the name can be released.
|
|
488
590
|
*
|
|
489
|
-
*
|
|
490
591
|
* @param name @type {string} The name you want to release. The name will be put up for as a recently returned name on the ARIO contract. 50% of the winning bid will be distributed to the ANT owner at the time of purchase. If no purchase in the recently returned name period (14 epochs), the name will be released and can be reregistered by anyone.
|
|
491
592
|
* @param arioProcessId @type {string} The processId of the ARIO contract. This is where the ANT will send the message to release the name.
|
|
492
593
|
* @returns {Promise<AoMessageResult>} The result of the interaction.
|
package/lib/cjs/common/index.js
CHANGED
package/lib/cjs/utils/ant.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.sortANTRecords = void 0;
|
|
3
|
+
exports.convertHyperBeamStateToAoANTState = exports.sortANTRecords = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Sorts ANT records by priority and then lexicographically.
|
|
6
6
|
*
|
|
@@ -41,3 +41,34 @@ const sortANTRecords = (antRecords) => {
|
|
|
41
41
|
return Object.fromEntries(sortedEntries.map(([a, aRecord], index) => [a, { ...aRecord, index }]));
|
|
42
42
|
};
|
|
43
43
|
exports.sortANTRecords = sortANTRecords;
|
|
44
|
+
/**
|
|
45
|
+
* Convert HyperBeam serialized ANT state to backwards compatible format.
|
|
46
|
+
*
|
|
47
|
+
* @param state - The HyperBeam serialized ANT state.
|
|
48
|
+
*/
|
|
49
|
+
const convertHyperBeamStateToAoANTState = (state) => {
|
|
50
|
+
return {
|
|
51
|
+
Name: state.name,
|
|
52
|
+
Ticker: state.ticker,
|
|
53
|
+
Description: state.description,
|
|
54
|
+
Keywords: state.keywords,
|
|
55
|
+
Denomination: parseInt(state.denomination),
|
|
56
|
+
Owner: state.owner,
|
|
57
|
+
Controllers: state.controllers,
|
|
58
|
+
Records: Object.entries(state.records).reduce((acc, [key, record]) => {
|
|
59
|
+
acc[key] = {
|
|
60
|
+
transactionId: record.transactionid,
|
|
61
|
+
ttlSeconds: record.ttlseconds,
|
|
62
|
+
...(record.priority !== undefined
|
|
63
|
+
? { priority: record.priority }
|
|
64
|
+
: {}),
|
|
65
|
+
};
|
|
66
|
+
return acc;
|
|
67
|
+
}, {}),
|
|
68
|
+
Balances: state.balances,
|
|
69
|
+
Logo: state.logo,
|
|
70
|
+
TotalSupply: state.totalsupply || 1,
|
|
71
|
+
Initialized: state.initialized,
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
exports.convertHyperBeamStateToAoANTState = convertHyperBeamStateToAoANTState;
|
package/lib/cjs/utils/hash.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
3
|
+
exports.hashBufferToB64Url = exports.hashReadableStreamToB64Url = exports.hashReadableToB64Url = void 0;
|
|
7
4
|
/**
|
|
8
5
|
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
9
6
|
*
|
|
@@ -19,90 +16,41 @@ exports.convertDataStreamToDataRoot = exports.hashDataStreamToB64Url = exports.r
|
|
|
19
16
|
* See the License for the specific language governing permissions and
|
|
20
17
|
* limitations under the License.
|
|
21
18
|
*/
|
|
22
|
-
const arweave_1 = __importDefault(require("arweave"));
|
|
23
|
-
const merkle_js_1 = require("arweave/node/lib/merkle.js");
|
|
24
19
|
const crypto_1 = require("crypto");
|
|
25
20
|
const base64_js_1 = require("./base64.js");
|
|
26
|
-
const
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
const hashReadableToB64Url = (stream, algorithm = 'sha256') => {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
const hash = (0, crypto_1.createHash)(algorithm);
|
|
24
|
+
stream.on('data', (chunk) => hash.update(chunk));
|
|
25
|
+
stream.on('end', () => resolve((0, base64_js_1.toB64Url)(hash.digest())));
|
|
26
|
+
stream.on('error', (err) => reject(err));
|
|
27
|
+
});
|
|
32
28
|
};
|
|
33
|
-
exports.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
exports.hashReadableToB64Url = hashReadableToB64Url;
|
|
30
|
+
const hashReadableStreamToB64Url = (stream, algorithm = 'sha256') => {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const hash = (0, crypto_1.createHash)(algorithm);
|
|
37
33
|
const reader = stream.getReader();
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
const read = async () => {
|
|
35
|
+
try {
|
|
40
36
|
const { done, value } = await reader.read();
|
|
41
|
-
if (done)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
if (done) {
|
|
38
|
+
resolve((0, base64_js_1.toB64Url)(hash.digest()));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
hash.update(value);
|
|
42
|
+
read();
|
|
43
|
+
}
|
|
45
44
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
reader.releaseLock();
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
exports.readableStreamToAsyncIterable = readableStreamToAsyncIterable;
|
|
53
|
-
const hashDataStreamToB64Url = async (stream, algorithm = 'sha256') => {
|
|
54
|
-
const asyncIterable = (0, exports.isAsyncIterable)(stream)
|
|
55
|
-
? stream
|
|
56
|
-
: (0, exports.readableStreamToAsyncIterable)(stream);
|
|
57
|
-
const hash = (0, crypto_1.createHash)(algorithm);
|
|
58
|
-
for await (const chunk of asyncIterable) {
|
|
59
|
-
hash.update(chunk);
|
|
60
|
-
}
|
|
61
|
-
return (0, base64_js_1.toB64Url)(hash.digest());
|
|
62
|
-
};
|
|
63
|
-
exports.hashDataStreamToB64Url = hashDataStreamToB64Url;
|
|
64
|
-
const convertDataStreamToDataRoot = async ({ dataStream, }) => {
|
|
65
|
-
const chunks = [];
|
|
66
|
-
let leftover = new Uint8Array(0);
|
|
67
|
-
let cursor = 0;
|
|
68
|
-
const asyncIterable = (0, exports.isAsyncIterable)(dataStream)
|
|
69
|
-
? dataStream
|
|
70
|
-
: (0, exports.readableStreamToAsyncIterable)(dataStream);
|
|
71
|
-
for await (const data of asyncIterable) {
|
|
72
|
-
const inputChunk = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
73
|
-
const combined = new Uint8Array(leftover.length + inputChunk.length);
|
|
74
|
-
combined.set(leftover, 0);
|
|
75
|
-
combined.set(inputChunk, leftover.length);
|
|
76
|
-
let startIndex = 0;
|
|
77
|
-
while (combined.length - startIndex >= merkle_js_1.MAX_CHUNK_SIZE) {
|
|
78
|
-
let chunkSize = merkle_js_1.MAX_CHUNK_SIZE;
|
|
79
|
-
const remainderAfterThis = combined.length - startIndex - merkle_js_1.MAX_CHUNK_SIZE;
|
|
80
|
-
if (remainderAfterThis > 0 && remainderAfterThis < merkle_js_1.MIN_CHUNK_SIZE) {
|
|
81
|
-
chunkSize = Math.ceil((combined.length - startIndex) / 2);
|
|
45
|
+
catch (err) {
|
|
46
|
+
reject(err);
|
|
82
47
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
cursor += chunkSize;
|
|
91
|
-
startIndex += chunkSize;
|
|
92
|
-
}
|
|
93
|
-
leftover = combined.slice(startIndex);
|
|
94
|
-
}
|
|
95
|
-
if (leftover.length > 0) {
|
|
96
|
-
// TODO: ensure a web friendly crypto hash function is used in web
|
|
97
|
-
const dataHash = await arweave_1.default.crypto.hash(leftover);
|
|
98
|
-
chunks.push({
|
|
99
|
-
dataHash,
|
|
100
|
-
minByteRange: cursor,
|
|
101
|
-
maxByteRange: cursor + leftover.length,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
const leaves = await (0, merkle_js_1.generateLeaves)(chunks);
|
|
105
|
-
const root = await (0, merkle_js_1.buildLayers)(leaves);
|
|
106
|
-
return (0, base64_js_1.toB64Url)(Buffer.from(root.id));
|
|
48
|
+
};
|
|
49
|
+
read().catch(reject);
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
exports.hashReadableStreamToB64Url = hashReadableStreamToB64Url;
|
|
53
|
+
const hashBufferToB64Url = (buffer, algorithm = 'sha256') => {
|
|
54
|
+
return (0, base64_js_1.toB64Url)((0, crypto_1.createHash)(algorithm).update(buffer).digest());
|
|
107
55
|
};
|
|
108
|
-
exports.
|
|
56
|
+
exports.hashBufferToB64Url = hashBufferToB64Url;
|
package/lib/cjs/version.js
CHANGED
package/lib/esm/cli/cli.js
CHANGED
|
@@ -477,6 +477,14 @@ makeCommand({
|
|
|
477
477
|
return readANTFromOptions(options).getTicker();
|
|
478
478
|
},
|
|
479
479
|
});
|
|
480
|
+
makeCommand({
|
|
481
|
+
name: 'get-ant-logo',
|
|
482
|
+
description: 'Get the logo of an ANT process',
|
|
483
|
+
options: [optionMap.processId],
|
|
484
|
+
action: async (options) => {
|
|
485
|
+
return readANTFromOptions(options).getLogo();
|
|
486
|
+
},
|
|
487
|
+
});
|
|
480
488
|
makeCommand({
|
|
481
489
|
name: 'get-ant-balance',
|
|
482
490
|
description: 'Get the balance of an ANT process',
|
package/lib/esm/common/ant.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { AntBalancesSchema, AntControllersSchema, AntInfoSchema, AntRecordSchema, AntRecordsSchema, AntStateSchema, } from '../types/ant.js';
|
|
18
18
|
import { isProcessConfiguration, isProcessIdConfiguration, } from '../types/index.js';
|
|
19
|
-
import { sortANTRecords } from '../utils/ant.js';
|
|
19
|
+
import { convertHyperBeamStateToAoANTState, sortANTRecords, } from '../utils/ant.js';
|
|
20
20
|
import { createAoSigner } from '../utils/ao.js';
|
|
21
21
|
import { parseSchemaResult } from '../utils/schema.js';
|
|
22
22
|
import { ANTVersions } from './ant-versions.js';
|
|
@@ -35,6 +35,8 @@ export class AoANTReadable {
|
|
|
35
35
|
process;
|
|
36
36
|
processId;
|
|
37
37
|
strict;
|
|
38
|
+
hyperbeamUrl;
|
|
39
|
+
checkHyperBeamPromise;
|
|
38
40
|
constructor(config) {
|
|
39
41
|
this.strict = config.strict || false;
|
|
40
42
|
if (isProcessConfiguration(config)) {
|
|
@@ -49,8 +51,43 @@ export class AoANTReadable {
|
|
|
49
51
|
throw new InvalidContractConfigurationError();
|
|
50
52
|
}
|
|
51
53
|
this.processId = this.process.processId;
|
|
54
|
+
this.hyperbeamUrl = config.hyperbeamUrl || 'https://permanode.xyz'; // TODO: replace this with hyperbeam.ario.permaweb.services once deployed
|
|
55
|
+
this.checkHyperBeamPromise = this.checkHyperBeamCompatibility();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Check if the process is hyperbeam compatible. If so, we'll use the hyperbeam node to fetch the state.
|
|
59
|
+
*
|
|
60
|
+
* @returns {Promise<boolean>} True if the process is hyperbeam compatible, false otherwise.
|
|
61
|
+
*/
|
|
62
|
+
async checkHyperBeamCompatibility() {
|
|
63
|
+
if (this.checkHyperBeamPromise !== undefined) {
|
|
64
|
+
return this.checkHyperBeamPromise;
|
|
65
|
+
}
|
|
66
|
+
const res = await fetch(`https://permanode.xyz/${this.processId}~process@1.0/now/cache`, {
|
|
67
|
+
method: 'HEAD',
|
|
68
|
+
});
|
|
69
|
+
let isHyperBeamCompatible = false;
|
|
70
|
+
if (res.ok) {
|
|
71
|
+
isHyperBeamCompatible = true;
|
|
72
|
+
}
|
|
73
|
+
this.checkHyperBeamPromise = Promise.resolve(isHyperBeamCompatible);
|
|
74
|
+
return isHyperBeamCompatible;
|
|
52
75
|
}
|
|
53
76
|
async getState({ strict } = { strict: this.strict }) {
|
|
77
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
78
|
+
const res = await fetch(`${this.hyperbeamUrl}/${this.processId}~process@1.0/now/cache/serialize~json@1.0`, {
|
|
79
|
+
method: 'GET',
|
|
80
|
+
redirect: 'follow',
|
|
81
|
+
mode: 'cors',
|
|
82
|
+
headers: {
|
|
83
|
+
'Content-Type': 'application/json',
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
if (!res.ok) {
|
|
87
|
+
throw new Error('Failed to fetch ant state');
|
|
88
|
+
}
|
|
89
|
+
return convertHyperBeamStateToAoANTState((await res.json()));
|
|
90
|
+
}
|
|
54
91
|
const tags = [{ name: 'Action', value: 'State' }];
|
|
55
92
|
const res = await this.process.read({
|
|
56
93
|
tags,
|
|
@@ -63,6 +100,20 @@ export class AoANTReadable {
|
|
|
63
100
|
return res;
|
|
64
101
|
}
|
|
65
102
|
async getInfo({ strict } = { strict: this.strict }) {
|
|
103
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
104
|
+
const state = await this.getState();
|
|
105
|
+
return {
|
|
106
|
+
Name: state.Name,
|
|
107
|
+
Ticker: state.Ticker,
|
|
108
|
+
Description: state.Description,
|
|
109
|
+
Keywords: state.Keywords,
|
|
110
|
+
Denomination: state.Denomination.toString(),
|
|
111
|
+
Owner: state.Owner,
|
|
112
|
+
Logo: state.Logo,
|
|
113
|
+
'Total-Supply': state.TotalSupply.toString(),
|
|
114
|
+
Handlers: [], // TODO: support for handler in patched state
|
|
115
|
+
};
|
|
116
|
+
}
|
|
66
117
|
const tags = [{ name: 'Action', value: 'Info' }];
|
|
67
118
|
const info = await this.process.read({
|
|
68
119
|
tags,
|
|
@@ -89,6 +140,15 @@ export class AoANTReadable {
|
|
|
89
140
|
* ```
|
|
90
141
|
*/
|
|
91
142
|
async getRecord({ undername }, { strict } = { strict: this.strict }) {
|
|
143
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
144
|
+
const records = await this.getRecords();
|
|
145
|
+
const cachedRecord = records[undername];
|
|
146
|
+
// if the record is not found, throw an error
|
|
147
|
+
if (cachedRecord === undefined) {
|
|
148
|
+
throw new Error('Record not found');
|
|
149
|
+
}
|
|
150
|
+
return cachedRecord;
|
|
151
|
+
}
|
|
92
152
|
// TODO: use sortedANTRecords to get priority on all records, even if ANT does not have a priority set
|
|
93
153
|
const record = await this.process.read({
|
|
94
154
|
tags: [
|
|
@@ -109,6 +169,10 @@ export class AoANTReadable {
|
|
|
109
169
|
* ````
|
|
110
170
|
*/
|
|
111
171
|
async getRecords({ strict } = { strict: this.strict }) {
|
|
172
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
173
|
+
const state = await this.getState();
|
|
174
|
+
return sortANTRecords(state.Records);
|
|
175
|
+
}
|
|
112
176
|
const tags = [{ name: 'Action', value: 'Records' }];
|
|
113
177
|
const records = await this.process.read({
|
|
114
178
|
tags,
|
|
@@ -127,6 +191,10 @@ export class AoANTReadable {
|
|
|
127
191
|
* ```
|
|
128
192
|
*/
|
|
129
193
|
async getOwner({ strict } = { strict: this.strict }) {
|
|
194
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
195
|
+
const state = await this.getState();
|
|
196
|
+
return state.Owner;
|
|
197
|
+
}
|
|
130
198
|
const info = await this.getInfo({ strict });
|
|
131
199
|
return info.Owner;
|
|
132
200
|
}
|
|
@@ -139,6 +207,10 @@ export class AoANTReadable {
|
|
|
139
207
|
* ```
|
|
140
208
|
*/
|
|
141
209
|
async getControllers({ strict } = { strict: this.strict }) {
|
|
210
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
211
|
+
const state = await this.getState();
|
|
212
|
+
return state.Controllers;
|
|
213
|
+
}
|
|
142
214
|
const tags = [{ name: 'Action', value: 'Controllers' }];
|
|
143
215
|
const controllers = await this.process.read({
|
|
144
216
|
tags,
|
|
@@ -156,6 +228,10 @@ export class AoANTReadable {
|
|
|
156
228
|
* ```
|
|
157
229
|
*/
|
|
158
230
|
async getName({ strict } = { strict: this.strict }) {
|
|
231
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
232
|
+
const state = await this.getState();
|
|
233
|
+
return state.Name;
|
|
234
|
+
}
|
|
159
235
|
const info = await this.getInfo({ strict });
|
|
160
236
|
return info.Name;
|
|
161
237
|
}
|
|
@@ -168,6 +244,10 @@ export class AoANTReadable {
|
|
|
168
244
|
* ```
|
|
169
245
|
*/
|
|
170
246
|
async getTicker({ strict } = { strict: this.strict }) {
|
|
247
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
248
|
+
const state = await this.getState();
|
|
249
|
+
return state.Ticker;
|
|
250
|
+
}
|
|
171
251
|
const info = await this.getInfo({ strict });
|
|
172
252
|
return info.Ticker;
|
|
173
253
|
}
|
|
@@ -180,6 +260,21 @@ export class AoANTReadable {
|
|
|
180
260
|
* ```
|
|
181
261
|
*/
|
|
182
262
|
async getBalances({ strict } = { strict: this.strict }) {
|
|
263
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
264
|
+
const res = await fetch(`${this.hyperbeamUrl}/${this.processId}~process@1.0/now/cache/balances/serialize~json@1.0`, {
|
|
265
|
+
method: 'GET',
|
|
266
|
+
redirect: 'follow',
|
|
267
|
+
mode: 'cors',
|
|
268
|
+
headers: {
|
|
269
|
+
'Content-Type': 'application/json',
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
if (!res.ok) {
|
|
273
|
+
throw new Error('Failed to fetch ant balances');
|
|
274
|
+
}
|
|
275
|
+
const result = (await res.json());
|
|
276
|
+
return result.balances;
|
|
277
|
+
}
|
|
183
278
|
const tags = [{ name: 'Action', value: 'Balances' }];
|
|
184
279
|
const balances = await this.process.read({
|
|
185
280
|
tags,
|
|
@@ -198,6 +293,10 @@ export class AoANTReadable {
|
|
|
198
293
|
* ```
|
|
199
294
|
*/
|
|
200
295
|
async getBalance({ address }, { strict } = { strict: this.strict }) {
|
|
296
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
297
|
+
const balances = await this.getBalances();
|
|
298
|
+
return balances[address] ?? 0;
|
|
299
|
+
}
|
|
201
300
|
const tags = [
|
|
202
301
|
{ name: 'Action', value: 'Balance' },
|
|
203
302
|
{ name: 'Recipient', value: address },
|
|
@@ -218,6 +317,9 @@ export class AoANTReadable {
|
|
|
218
317
|
* ```
|
|
219
318
|
*/
|
|
220
319
|
async getHandlers() {
|
|
320
|
+
if (await this.checkHyperBeamCompatibility()) {
|
|
321
|
+
throw new Error('Handlers are not supported on HyperBeam');
|
|
322
|
+
}
|
|
221
323
|
const info = await this.getInfo();
|
|
222
324
|
return (info.Handlers ?? info.HandlerNames);
|
|
223
325
|
}
|
|
@@ -481,7 +583,6 @@ export class AoANTWriteable extends AoANTReadable {
|
|
|
481
583
|
/**
|
|
482
584
|
* Releases an ArNS name associated with the ANT. This will release the name to the public and allow anyone to register it. All primary names must be removed before the name can be released.
|
|
483
585
|
*
|
|
484
|
-
*
|
|
485
586
|
* @param name @type {string} The name you want to release. The name will be put up for as a recently returned name on the ARIO contract. 50% of the winning bid will be distributed to the ANT owner at the time of purchase. If no purchase in the recently returned name period (14 epochs), the name will be released and can be reregistered by anyone.
|
|
486
587
|
* @param arioProcessId @type {string} The processId of the ARIO contract. This is where the ANT will send the message to release the name.
|
|
487
588
|
* @returns {Promise<AoMessageResult>} The result of the interaction.
|
package/lib/esm/common/index.js
CHANGED
package/lib/esm/utils/ant.js
CHANGED
|
@@ -37,3 +37,33 @@ export const sortANTRecords = (antRecords) => {
|
|
|
37
37
|
// now that they are sorted, add the index to each record - this is their position in the sorted list and is used to enforce undername limits
|
|
38
38
|
return Object.fromEntries(sortedEntries.map(([a, aRecord], index) => [a, { ...aRecord, index }]));
|
|
39
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Convert HyperBeam serialized ANT state to backwards compatible format.
|
|
42
|
+
*
|
|
43
|
+
* @param state - The HyperBeam serialized ANT state.
|
|
44
|
+
*/
|
|
45
|
+
export const convertHyperBeamStateToAoANTState = (state) => {
|
|
46
|
+
return {
|
|
47
|
+
Name: state.name,
|
|
48
|
+
Ticker: state.ticker,
|
|
49
|
+
Description: state.description,
|
|
50
|
+
Keywords: state.keywords,
|
|
51
|
+
Denomination: parseInt(state.denomination),
|
|
52
|
+
Owner: state.owner,
|
|
53
|
+
Controllers: state.controllers,
|
|
54
|
+
Records: Object.entries(state.records).reduce((acc, [key, record]) => {
|
|
55
|
+
acc[key] = {
|
|
56
|
+
transactionId: record.transactionid,
|
|
57
|
+
ttlSeconds: record.ttlseconds,
|
|
58
|
+
...(record.priority !== undefined
|
|
59
|
+
? { priority: record.priority }
|
|
60
|
+
: {}),
|
|
61
|
+
};
|
|
62
|
+
return acc;
|
|
63
|
+
}, {}),
|
|
64
|
+
Balances: state.balances,
|
|
65
|
+
Logo: state.logo,
|
|
66
|
+
TotalSupply: state.totalsupply || 1,
|
|
67
|
+
Initialized: state.initialized,
|
|
68
|
+
};
|
|
69
|
+
};
|