@ar.io/sdk 1.2.0-alpha.9 → 1.2.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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getANTProcessesOwnedByWallet = void 0;
3
+ exports.ArNSEventEmitter = exports.getANTProcessesOwnedByWallet = void 0;
4
4
  /**
5
5
  * Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved.
6
6
  *
@@ -17,15 +17,15 @@ exports.getANTProcessesOwnedByWallet = void 0;
17
17
  * You should have received a copy of the GNU Affero General Public License
18
18
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
  */
20
+ const eventemitter3_1 = require("eventemitter3");
20
21
  const plimit_lit_1 = require("plimit-lit");
21
22
  const ant_js_1 = require("../../common/ant.js");
22
23
  const io_js_1 = require("../../common/io.js");
23
24
  const constants_js_1 = require("../../constants.js");
24
- // throttle the requests to avoid rate limiting
25
- const throttle = (0, plimit_lit_1.pLimit)(50);
26
25
  const getANTProcessesOwnedByWallet = async ({ address, contract = io_js_1.IO.init({
27
- processId: constants_js_1.ioDevnetProcessId,
26
+ processId: constants_js_1.IO_TESTNET_PROCESS_ID,
28
27
  }), }) => {
28
+ const throttle = (0, plimit_lit_1.pLimit)(50);
29
29
  // get the record names of the registry - TODO: this may need to be paginated
30
30
  const uniqueContractProcessIds = await contract
31
31
  .getArNSRecords()
@@ -33,15 +33,95 @@ const getANTProcessesOwnedByWallet = async ({ address, contract = io_js_1.IO.ini
33
33
  .filter((record) => record.processId !== undefined)
34
34
  .map((record) => record.processId));
35
35
  // check the contract owner and controllers
36
- const ownedOrControlledByWallet = await Promise.all(uniqueContractProcessIds.filter(async (processId) => throttle(async () => {
36
+ const ownedOrControlledByWallet = await Promise.all(uniqueContractProcessIds.map(async (processId) => throttle(async () => {
37
37
  const ant = ant_js_1.ANT.init({
38
38
  processId,
39
39
  });
40
- const owner = await ant.getOwner();
41
- const controllers = await ant.getControllers();
42
- return owner === address || controllers.includes(address);
40
+ const { Owner, Controllers } = await ant.getState();
41
+ if (Owner === address || Controllers.includes(address)) {
42
+ return processId;
43
+ }
44
+ return;
43
45
  })));
46
+ if (ownedOrControlledByWallet.length === 0) {
47
+ return [];
48
+ }
44
49
  // TODO: insert gql query to find ANT processes owned by wallet given wallet not currently in the registry
45
50
  return [...new Set(ownedOrControlledByWallet)];
46
51
  };
47
52
  exports.getANTProcessesOwnedByWallet = getANTProcessesOwnedByWallet;
53
+ function timeout(ms, promise) {
54
+ return new Promise((resolve, reject) => {
55
+ const timer = setTimeout(() => {
56
+ reject(new Error('Timeout'));
57
+ }, ms);
58
+ promise
59
+ .then((value) => {
60
+ clearTimeout(timer);
61
+ resolve(value);
62
+ })
63
+ .catch((err) => {
64
+ clearTimeout(timer);
65
+ reject(err);
66
+ });
67
+ });
68
+ }
69
+ class ArNSEventEmitter extends eventemitter3_1.EventEmitter {
70
+ contract;
71
+ timeoutMs; // timeout for each request to 3 seconds
72
+ throttle;
73
+ constructor({ contract = io_js_1.IO.init({
74
+ processId: constants_js_1.IO_TESTNET_PROCESS_ID,
75
+ }), timeoutMs = 60_000, concurrency = 30, }) {
76
+ super();
77
+ this.contract = contract;
78
+ this.timeoutMs = timeoutMs;
79
+ this.throttle = (0, plimit_lit_1.pLimit)(concurrency);
80
+ }
81
+ async fetchProcessesOwnedByWallet({ address }) {
82
+ const uniqueContractProcessIds = {};
83
+ await timeout(this.timeoutMs, this.contract.getArNSRecords().catch((e) => {
84
+ this.emit('error', `Error getting ArNS records: ${e}`);
85
+ return {};
86
+ })).then((records) => {
87
+ if (!records)
88
+ return;
89
+ Object.entries(records).forEach(([name, record]) => {
90
+ if (record.processId === undefined) {
91
+ return;
92
+ }
93
+ if (uniqueContractProcessIds[record.processId] === undefined) {
94
+ uniqueContractProcessIds[record.processId] = {
95
+ state: undefined,
96
+ names: {},
97
+ };
98
+ }
99
+ uniqueContractProcessIds[record.processId].names[name] = record;
100
+ });
101
+ });
102
+ const idCount = Object.keys(uniqueContractProcessIds).length;
103
+ // check the contract owner and controllers
104
+ this.emit('progress', 0, idCount);
105
+ await Promise.all(Object.keys(uniqueContractProcessIds).map(async (processId, i) => this.throttle(async () => {
106
+ if (uniqueContractProcessIds[processId].state !== undefined) {
107
+ this.emit('progress', i + 1, idCount);
108
+ return;
109
+ }
110
+ const ant = ant_js_1.ANT.init({
111
+ processId,
112
+ });
113
+ const state = (await timeout(this.timeoutMs, ant.getState()).catch((e) => {
114
+ this.emit('error', `Error getting state for process ${processId}: ${e}`);
115
+ return undefined;
116
+ }));
117
+ if (state?.Owner === address ||
118
+ state?.Controllers.includes(address)) {
119
+ uniqueContractProcessIds[processId].state = state;
120
+ this.emit('process', processId, uniqueContractProcessIds[processId]);
121
+ }
122
+ this.emit('progress', i + 1, idCount);
123
+ })));
124
+ this.emit('end', uniqueContractProcessIds);
125
+ }
126
+ }
127
+ exports.ArNSEventEmitter = ArNSEventEmitter;
@@ -35,3 +35,4 @@ __exportStar(require("./http-client.js"), exports);
35
35
  __exportStar(require("./smartweave.js"), exports);
36
36
  __exportStar(require("./graphql/index.js"), exports);
37
37
  __exportStar(require("./ao.js"), exports);
38
+ __exportStar(require("./json.js"), exports);
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.safeDecode = void 0;
4
+ /**
5
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved.
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU Affero General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU Affero General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Affero General Public License
18
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+ function safeDecode(data) {
21
+ try {
22
+ return JSON.parse(data);
23
+ }
24
+ catch (e) {
25
+ return data;
26
+ }
27
+ }
28
+ exports.safeDecode = safeDecode;
@@ -18,4 +18,4 @@
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.version = void 0;
20
20
  // AUTOMATICALLY GENERATED FILE - DO NOT TOUCH
21
- exports.version = '1.2.0-alpha.9';
21
+ exports.version = '1.2.1';
@@ -16,6 +16,13 @@ export class AoANTReadable {
16
16
  throw new InvalidContractConfigurationError();
17
17
  }
18
18
  }
19
+ async getState() {
20
+ const tags = [{ name: 'Action', value: 'State' }];
21
+ const res = await this.process.read({
22
+ tags,
23
+ });
24
+ return res;
25
+ }
19
26
  async getInfo() {
20
27
  const tags = [{ name: 'Action', value: 'Info' }];
21
28
  const info = await this.process.read({
@@ -35,7 +42,7 @@ export class AoANTReadable {
35
42
  async getRecord({ undername }) {
36
43
  const tags = [
37
44
  { name: 'Sub-Domain', value: undername },
38
- { name: 'Action', value: 'Get-Record' },
45
+ { name: 'Action', value: 'Record' },
39
46
  ];
40
47
  const record = await this.process.read({
41
48
  tags,
@@ -51,7 +58,7 @@ export class AoANTReadable {
51
58
  * ````
52
59
  */
53
60
  async getRecords() {
54
- const tags = [{ name: 'Action', value: 'Get-Records' }];
61
+ const tags = [{ name: 'Action', value: 'Records' }];
55
62
  const records = await this.process.read({
56
63
  tags,
57
64
  });
@@ -78,7 +85,7 @@ export class AoANTReadable {
78
85
  * ```
79
86
  */
80
87
  async getControllers() {
81
- const tags = [{ name: 'Action', value: 'Get-Controllers' }];
88
+ const tags = [{ name: 'Action', value: 'Controllers' }];
82
89
  const controllers = await this.process.read({
83
90
  tags,
84
91
  });
@@ -178,7 +185,7 @@ export class AoANTWriteable extends AoANTReadable {
178
185
  */
179
186
  async addController({ controller, }) {
180
187
  const tags = [
181
- { name: 'Action', value: 'Set-Controller' },
188
+ { name: 'Action', value: 'Add-Controller' },
182
189
  { name: 'Controller', value: controller },
183
190
  ];
184
191
  return this.process.send({
@@ -16,6 +16,7 @@
16
16
  */
17
17
  import { connect } from '@permaweb/aoconnect';
18
18
  import { createData } from 'arbundles';
19
+ import { safeDecode } from '../../utils/json.js';
19
20
  import { version } from '../../version.js';
20
21
  import { WriteInteractionError } from '../error.js';
21
22
  import { DefaultLogger } from '../logger.js';
@@ -57,18 +58,22 @@ export class AOProcess {
57
58
  process: this.processId,
58
59
  tags,
59
60
  });
61
+ if (result.Messages.length === 0) {
62
+ throw new Error(`Process ${this.processId} does not support provided action.`);
63
+ }
60
64
  const tagsOutput = result.Messages[0].Tags;
61
65
  const error = tagsOutput.find((tag) => tag.name === 'Error');
62
66
  if (error) {
63
67
  throw new Error(`${error.Value}: ${result.Messages[0].Data}`);
64
68
  }
65
- if (result.Messages.length === 0) {
66
- throw new Error('Process does not support provided action.');
67
- }
68
69
  this.logger.debug(`Read interaction result`, {
69
70
  result: result.Messages[0].Data,
70
71
  });
71
- const response = JSON.parse(result.Messages[0].Data);
72
+ // return empty object if no data is returned
73
+ if (result.Messages[0].Data === undefined) {
74
+ return {};
75
+ }
76
+ const response = safeDecode(result.Messages[0].Data);
72
77
  return response;
73
78
  }
74
79
  catch (e) {
@@ -128,7 +133,13 @@ export class AOProcess {
128
133
  const result = output.Messages[0].Data;
129
134
  throw new WriteInteractionError(`${error.Value}: ${result}`);
130
135
  }
131
- const resultData = JSON.parse(output.Messages[0].Data);
136
+ if (output.Messages.length === 0) {
137
+ throw new Error(`Process ${this.processId} does not support provided action.`);
138
+ }
139
+ if (output.Messages[0].Data === undefined) {
140
+ return { id: messageId };
141
+ }
142
+ const resultData = safeDecode(output.Messages[0].Data);
132
143
  this.logger.debug('Message result data', {
133
144
  resultData,
134
145
  messageId,