@ar.io/sdk 3.14.0-alpha.8 → 3.14.0-alpha.9

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.
@@ -41,6 +41,7 @@ class AoANTReadable {
41
41
  strict;
42
42
  hyperbeamUrl;
43
43
  checkHyperBeamPromise;
44
+ logger = index_js_2.Logger.default;
44
45
  constructor(config) {
45
46
  this.strict = config.strict || false;
46
47
  if ((0, index_js_1.isProcessConfiguration)(config)) {
@@ -59,38 +60,57 @@ class AoANTReadable {
59
60
  this.checkHyperBeamPromise = this.checkHyperBeamCompatibility();
60
61
  }
61
62
  /**
62
- * Check if the process is hyperbeam compatible. If so, we'll use the hyperbeam node to fetch the state.
63
+ * Check if the process is HyperBeam compatible. If so, we'll use the HyperBeam node to fetch the state.
63
64
  *
64
- * @returns {Promise<boolean>} True if the process is hyperbeam compatible, false otherwise.
65
+ * @returns {Promise<boolean>} True if the process is HyperBeam compatible, false otherwise.
65
66
  */
66
67
  async checkHyperBeamCompatibility() {
67
68
  if (this.checkHyperBeamPromise !== undefined) {
68
69
  return this.checkHyperBeamPromise;
69
70
  }
70
- const res = await fetch(`${this.hyperbeamUrl.toString()}${this.processId}~process@1.0/now/cache`, {
71
- method: 'GET',
71
+ this.checkHyperBeamPromise = fetch(`${this.hyperbeamUrl.toString()}${this.processId}~process@1.0/now/cache`, {
72
+ method: 'HEAD',
73
+ }).then((res) => {
74
+ if (res.ok) {
75
+ return true;
76
+ }
77
+ return false;
72
78
  });
73
- let isHyperBeamCompatible = false;
74
- if (res.ok) {
75
- isHyperBeamCompatible = true;
76
- }
77
- this.checkHyperBeamPromise = Promise.resolve(isHyperBeamCompatible);
78
- return isHyperBeamCompatible;
79
+ return this.checkHyperBeamPromise;
79
80
  }
80
81
  async getState({ strict } = { strict: this.strict }) {
81
82
  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');
83
+ let retries = 0;
84
+ while (retries < 3) {
85
+ try {
86
+ const res = await fetch(`${this.hyperbeamUrl}${this.processId}~process@1.0/compute/cache/serialize~json@1.0`, {
87
+ method: 'GET',
88
+ redirect: 'follow',
89
+ mode: 'cors',
90
+ headers: {
91
+ 'Content-Type': 'application/json',
92
+ },
93
+ });
94
+ if (res.status !== 200) {
95
+ throw new Error(`Failed to fetch ant state: ${res?.statusText ?? 'Unknown error'}`);
96
+ }
97
+ const unnormalizedState = (await res.json());
98
+ if (!(0, ant_js_2.isHyperBeamANTState)(unnormalizedState)) {
99
+ throw new Error('Invalid HyperBeam ANT state', {
100
+ cause: { state: unnormalizedState },
101
+ });
102
+ }
103
+ // normalize and return the state
104
+ return (0, ant_js_2.convertHyperBeamStateToAoANTState)(unnormalizedState);
105
+ }
106
+ catch (error) {
107
+ this.logger.error(`Failed to fetch process state from HyperBEAM (attempt ${retries + 1} / 3)`, {
108
+ cause: error,
109
+ });
110
+ retries++;
111
+ await new Promise((resolve) => setTimeout(resolve, 1000 * retries ** 2));
112
+ }
92
113
  }
93
- return (0, ant_js_2.convertHyperBeamStateToAoANTState)((await res.json()));
94
114
  }
95
115
  const tags = [{ name: 'Action', value: 'State' }];
96
116
  const res = await this.process.read({
@@ -264,25 +284,8 @@ class AoANTReadable {
264
284
  * ```
265
285
  */
266
286
  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
- }
282
- const tags = [{ name: 'Action', value: 'Balances' }];
283
- const balances = await this.process.read({
284
- tags,
285
- });
287
+ const state = await this.getState();
288
+ const balances = state.Balances;
286
289
  if (strict)
287
290
  (0, schema_js_1.parseSchemaResult)(ant_js_1.AntBalancesSchema, balances);
288
291
  return balances;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertHyperBeamStateToAoANTState = exports.sortANTRecords = void 0;
3
+ exports.convertHyperBeamStateToAoANTState = exports.isHyperBeamANTState = exports.sortANTRecords = void 0;
4
4
  /**
5
5
  * Sorts ANT records by priority and then lexicographically.
6
6
  *
@@ -41,6 +41,21 @@ const sortANTRecords = (antRecords) => {
41
41
  return Object.fromEntries(sortedEntries.map(([a, aRecord], index) => [a, { ...aRecord, index }]));
42
42
  };
43
43
  exports.sortANTRecords = sortANTRecords;
44
+ const isHyperBeamANTState = (state) => {
45
+ return ('name' in state &&
46
+ 'ticker' in state &&
47
+ 'description' in state &&
48
+ 'keywords' in state &&
49
+ 'denomination' in state &&
50
+ 'owner' in state &&
51
+ 'controllers' in state &&
52
+ 'records' in state &&
53
+ 'balances' in state &&
54
+ 'logo' in state &&
55
+ 'totalsupply' in state &&
56
+ 'initialized' in state);
57
+ };
58
+ exports.isHyperBeamANTState = isHyperBeamANTState;
44
59
  /**
45
60
  * Convert HyperBeam serialized ANT state to backwards compatible format.
46
61
  *
@@ -16,11 +16,11 @@
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 { convertHyperBeamStateToAoANTState, sortANTRecords, } from '../utils/ant.js';
19
+ import { convertHyperBeamStateToAoANTState, isHyperBeamANTState, 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';
23
- import { AOProcess, InvalidContractConfigurationError } from './index.js';
23
+ import { AOProcess, InvalidContractConfigurationError, Logger, } from './index.js';
24
24
  export class ANT {
25
25
  static versions = ANTVersions.init();
26
26
  // implementation
@@ -37,6 +37,7 @@ export class AoANTReadable {
37
37
  strict;
38
38
  hyperbeamUrl;
39
39
  checkHyperBeamPromise;
40
+ logger = Logger.default;
40
41
  constructor(config) {
41
42
  this.strict = config.strict || false;
42
43
  if (isProcessConfiguration(config)) {
@@ -55,38 +56,57 @@ export class AoANTReadable {
55
56
  this.checkHyperBeamPromise = this.checkHyperBeamCompatibility();
56
57
  }
57
58
  /**
58
- * Check if the process is hyperbeam compatible. If so, we'll use the hyperbeam node to fetch the state.
59
+ * Check if the process is HyperBeam compatible. If so, we'll use the HyperBeam node to fetch the state.
59
60
  *
60
- * @returns {Promise<boolean>} True if the process is hyperbeam compatible, false otherwise.
61
+ * @returns {Promise<boolean>} True if the process is HyperBeam compatible, false otherwise.
61
62
  */
62
63
  async checkHyperBeamCompatibility() {
63
64
  if (this.checkHyperBeamPromise !== undefined) {
64
65
  return this.checkHyperBeamPromise;
65
66
  }
66
- const res = await fetch(`${this.hyperbeamUrl.toString()}${this.processId}~process@1.0/now/cache`, {
67
- method: 'GET',
67
+ this.checkHyperBeamPromise = fetch(`${this.hyperbeamUrl.toString()}${this.processId}~process@1.0/now/cache`, {
68
+ method: 'HEAD',
69
+ }).then((res) => {
70
+ if (res.ok) {
71
+ return true;
72
+ }
73
+ return false;
68
74
  });
69
- let isHyperBeamCompatible = false;
70
- if (res.ok) {
71
- isHyperBeamCompatible = true;
72
- }
73
- this.checkHyperBeamPromise = Promise.resolve(isHyperBeamCompatible);
74
- return isHyperBeamCompatible;
75
+ return this.checkHyperBeamPromise;
75
76
  }
76
77
  async getState({ strict } = { strict: this.strict }) {
77
78
  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');
79
+ let retries = 0;
80
+ while (retries < 3) {
81
+ try {
82
+ const res = await fetch(`${this.hyperbeamUrl}${this.processId}~process@1.0/compute/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.status !== 200) {
91
+ throw new Error(`Failed to fetch ant state: ${res?.statusText ?? 'Unknown error'}`);
92
+ }
93
+ const unnormalizedState = (await res.json());
94
+ if (!isHyperBeamANTState(unnormalizedState)) {
95
+ throw new Error('Invalid HyperBeam ANT state', {
96
+ cause: { state: unnormalizedState },
97
+ });
98
+ }
99
+ // normalize and return the state
100
+ return convertHyperBeamStateToAoANTState(unnormalizedState);
101
+ }
102
+ catch (error) {
103
+ this.logger.error(`Failed to fetch process state from HyperBEAM (attempt ${retries + 1} / 3)`, {
104
+ cause: error,
105
+ });
106
+ retries++;
107
+ await new Promise((resolve) => setTimeout(resolve, 1000 * retries ** 2));
108
+ }
88
109
  }
89
- return convertHyperBeamStateToAoANTState((await res.json()));
90
110
  }
91
111
  const tags = [{ name: 'Action', value: 'State' }];
92
112
  const res = await this.process.read({
@@ -260,25 +280,8 @@ export class AoANTReadable {
260
280
  * ```
261
281
  */
262
282
  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
- }
278
- const tags = [{ name: 'Action', value: 'Balances' }];
279
- const balances = await this.process.read({
280
- tags,
281
- });
283
+ const state = await this.getState();
284
+ const balances = state.Balances;
282
285
  if (strict)
283
286
  parseSchemaResult(AntBalancesSchema, balances);
284
287
  return balances;
@@ -37,6 +37,20 @@ 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
+ export const isHyperBeamANTState = (state) => {
41
+ return ('name' in state &&
42
+ 'ticker' in state &&
43
+ 'description' in state &&
44
+ 'keywords' in state &&
45
+ 'denomination' in state &&
46
+ 'owner' in state &&
47
+ 'controllers' in state &&
48
+ 'records' in state &&
49
+ 'balances' in state &&
50
+ 'logo' in state &&
51
+ 'totalsupply' in state &&
52
+ 'initialized' in state);
53
+ };
40
54
  /**
41
55
  * Convert HyperBeam serialized ANT state to backwards compatible format.
42
56
  *
@@ -18,11 +18,12 @@ export declare class AoANTReadable implements AoANTRead {
18
18
  private strict;
19
19
  private hyperbeamUrl;
20
20
  private checkHyperBeamPromise;
21
+ private logger;
21
22
  constructor(config: ANTConfigOptionalStrict);
22
23
  /**
23
- * Check if the process is hyperbeam compatible. If so, we'll use the hyperbeam node to fetch the state.
24
+ * Check if the process is HyperBeam compatible. If so, we'll use the HyperBeam node to fetch the state.
24
25
  *
25
- * @returns {Promise<boolean>} True if the process is hyperbeam compatible, false otherwise.
26
+ * @returns {Promise<boolean>} True if the process is HyperBeam compatible, false otherwise.
26
27
  */
27
28
  private checkHyperBeamCompatibility;
28
29
  getState({ strict }?: AntReadOptions): Promise<AoANTState>;
@@ -24,6 +24,7 @@ import { ANTRecords, AoANTState, HyperBeamANTState, SortedANTRecords } from '../
24
24
  * @param antRecords - The ANT records to sort.
25
25
  */
26
26
  export declare const sortANTRecords: (antRecords: ANTRecords) => SortedANTRecords;
27
+ export declare const isHyperBeamANTState: (state: any) => state is HyperBeamANTState;
27
28
  /**
28
29
  * Convert HyperBeam serialized ANT state to backwards compatible format.
29
30
  *
@@ -13,4 +13,4 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- export declare const version = "3.14.0-alpha.7";
16
+ export declare const version = "3.14.0-alpha.8";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ar.io/sdk",
3
- "version": "3.14.0-alpha.8",
3
+ "version": "3.14.0-alpha.9",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/ar-io/ar-io-sdk.git"