@ar.io/sdk 3.8.1 → 3.8.2-alpha.2

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.
@@ -39,46 +39,25 @@ class AOProcess {
39
39
  messageData === null);
40
40
  }
41
41
  async read({ tags, retries = 3, fromAddress, }) {
42
+ this.logger.debug(`Evaluating read interaction on process`, {
43
+ tags,
44
+ processId: this.processId,
45
+ });
46
+ // map tags to inputs
47
+ const dryRunInput = {
48
+ process: this.processId,
49
+ tags,
50
+ };
51
+ if (fromAddress !== undefined) {
52
+ dryRunInput['Owner'] = fromAddress;
53
+ }
42
54
  let attempts = 0;
43
- let lastError;
55
+ let result = undefined;
44
56
  while (attempts < retries) {
45
57
  try {
46
- this.logger.debug(`Evaluating read interaction on process`, {
47
- tags,
48
- processId: this.processId,
49
- });
50
- // map tags to inputs
51
- const dryRunInput = {
52
- process: this.processId,
53
- tags,
54
- };
55
- if (fromAddress !== undefined) {
56
- dryRunInput['Owner'] = fromAddress;
57
- }
58
- const result = await this.ao.dryrun(dryRunInput);
59
- this.logger.debug(`Read interaction result`, {
60
- result,
61
- processId: this.processId,
62
- });
63
- const error = (0, index_js_1.errorMessageFromOutput)(result);
64
- if (error !== undefined) {
65
- throw new Error(error);
66
- }
67
- if (result.Messages === undefined || result.Messages.length === 0) {
68
- this.logger.debug(`Process ${this.processId} does not support provided action.`, {
69
- result,
70
- tags,
71
- processId: this.processId,
72
- });
73
- throw new Error(`Process ${this.processId} does not support provided action.`);
74
- }
75
- const messageData = result.Messages?.[0]?.Data;
76
- // return undefined if no data is returned
77
- if (this.isMessageDataEmpty(messageData)) {
78
- return undefined;
79
- }
80
- const response = (0, json_js_1.safeDecode)(messageData);
81
- return response;
58
+ result = await this.ao.dryrun(dryRunInput);
59
+ // break on successful return of result
60
+ break;
82
61
  }
83
62
  catch (error) {
84
63
  attempts++;
@@ -88,17 +67,45 @@ class AOProcess {
88
67
  tags,
89
68
  processId: this.processId,
90
69
  });
91
- lastError = error;
70
+ if (attempts >= retries) {
71
+ throw error;
72
+ }
92
73
  // exponential backoff
93
74
  await new Promise((resolve) => setTimeout(resolve, 2 ** attempts * 1000));
94
75
  }
95
76
  }
96
- throw lastError;
77
+ if (result === undefined) {
78
+ throw new Error('Unexpected error when evaluating read interaction');
79
+ }
80
+ this.logger.debug(`Read interaction result`, {
81
+ result,
82
+ processId: this.processId,
83
+ });
84
+ const error = (0, index_js_1.errorMessageFromOutput)(result);
85
+ if (error !== undefined) {
86
+ throw new Error(error);
87
+ }
88
+ if (result.Messages === undefined || result.Messages.length === 0) {
89
+ this.logger.debug(`Process ${this.processId} does not support provided action.`, {
90
+ result,
91
+ tags,
92
+ processId: this.processId,
93
+ });
94
+ throw new Error(`Process ${this.processId} does not support provided action.`);
95
+ }
96
+ const messageData = result.Messages?.[0]?.Data;
97
+ // return undefined if no data is returned
98
+ if (this.isMessageDataEmpty(messageData)) {
99
+ return undefined;
100
+ }
101
+ const response = (0, json_js_1.safeDecode)(messageData);
102
+ return response;
97
103
  }
98
104
  async send({ tags, data, signer, retries = 3, }) {
99
105
  // main purpose of retries is to handle network errors/new process delays
100
106
  let attempts = 0;
101
- let lastError;
107
+ let messageId;
108
+ let result = undefined;
102
109
  while (attempts < retries) {
103
110
  try {
104
111
  this.logger.debug(`Evaluating send interaction on contract`, {
@@ -109,7 +116,7 @@ class AOProcess {
109
116
  // TODO: do a read as a dry run to check if the process supports the action
110
117
  // anchor is a random text produce non-deterministic messages IDs when deterministic signers are provided (ETH)
111
118
  const anchor = (0, base64_js_1.getRandomText)(32);
112
- const messageId = await this.ao.message({
119
+ messageId = await this.ao.message({
113
120
  process: this.processId,
114
121
  // TODO: any other default tags we want to add?
115
122
  tags: [...tags, { name: 'AR-IO-SDK', value: version_js_1.version }],
@@ -123,36 +130,16 @@ class AOProcess {
123
130
  anchor,
124
131
  });
125
132
  // check the result of the send interaction
126
- const output = await this.ao.result({
133
+ result = await this.ao.result({
127
134
  message: messageId,
128
135
  process: this.processId,
129
136
  });
130
137
  this.logger.debug('Message result', {
131
- output,
132
- messageId,
133
- processId: this.processId,
134
- });
135
- const error = (0, index_js_1.errorMessageFromOutput)(output);
136
- if (error !== undefined) {
137
- throw new error_js_1.WriteInteractionError(error);
138
- }
139
- // check if there are any Messages in the output
140
- if (output.Messages?.length === 0 || output.Messages === undefined) {
141
- return { id: messageId };
142
- }
143
- if (output.Messages.length === 0) {
144
- throw new Error(`Process ${this.processId} does not support provided action.`);
145
- }
146
- if (this.isMessageDataEmpty(output.Messages[0].Data)) {
147
- return { id: messageId };
148
- }
149
- const resultData = (0, json_js_1.safeDecode)(output.Messages[0].Data);
150
- this.logger.debug('Message result data', {
151
- resultData,
138
+ result,
152
139
  messageId,
153
140
  processId: this.processId,
154
141
  });
155
- return { id: messageId, result: resultData };
142
+ break;
156
143
  }
157
144
  catch (error) {
158
145
  this.logger.error('Error sending message to process', {
@@ -161,24 +148,44 @@ class AOProcess {
161
148
  processId: this.processId,
162
149
  tags,
163
150
  });
164
- // throw on write interaction errors. No point retrying write interactions, waste of gas.
165
- if (error.message.includes('500')) {
166
- this.logger.debug('Retrying send interaction', {
167
- attempts,
168
- retries,
169
- error: error?.message,
170
- processId: this.processId,
171
- });
172
- // exponential backoff
173
- await new Promise((resolve) => setTimeout(resolve, 2 ** attempts * 2000));
174
- attempts++;
175
- lastError = error;
176
- }
177
- else
151
+ attempts++;
152
+ this.logger.debug('Retrying send interaction', {
153
+ attempts,
154
+ retries,
155
+ error: error?.message,
156
+ processId: this.processId,
157
+ });
158
+ if (attempts >= retries) {
178
159
  throw error;
160
+ }
161
+ // exponential backoff
162
+ await new Promise((resolve) => setTimeout(resolve, 2 ** attempts * 2000));
179
163
  }
180
164
  }
181
- throw lastError;
165
+ if (result === undefined || messageId === undefined) {
166
+ throw new Error('Unexpected error when evaluating write interaction');
167
+ }
168
+ const error = (0, index_js_1.errorMessageFromOutput)(result);
169
+ if (error !== undefined) {
170
+ throw new error_js_1.WriteInteractionError(error);
171
+ }
172
+ // check if there are any Messages in the output
173
+ if (result.Messages?.length === 0 || result.Messages === undefined) {
174
+ return { id: messageId };
175
+ }
176
+ if (result.Messages.length === 0) {
177
+ throw new Error(`Process ${this.processId} does not support provided action.`);
178
+ }
179
+ if (this.isMessageDataEmpty(result.Messages[0].Data)) {
180
+ return { id: messageId };
181
+ }
182
+ const resultData = (0, json_js_1.safeDecode)(result.Messages[0].Data);
183
+ this.logger.debug('Message result data', {
184
+ resultData,
185
+ messageId,
186
+ processId: this.processId,
187
+ });
188
+ return { id: messageId, result: resultData };
182
189
  }
183
190
  }
184
191
  exports.AOProcess = AOProcess;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isAoANTState = exports.AntInfoSchema = exports.AntHandlersSchema = exports.AntHandlerNames = exports.AntWriteHandlers = exports.AntReadHandlers = exports.AntStateSchema = exports.AntBalancesSchema = exports.AntControllersSchema = exports.AntRecordsSchema = exports.AntRecordSchema = exports.AntKeywordsSchema = exports.AntDescriptionSchema = exports.IntegerStringSchema = exports.ArweaveTxIdSchema = void 0;
3
+ exports.isAoANTState = exports.AntInfoSchema = exports.AntHandlersSchema = exports.AntHandlerNames = exports.AntWriteHandlers = exports.AntReadHandlers = exports.AntStateSchema = exports.AntBalancesSchema = exports.AntControllersSchema = exports.AntRecordsSchema = exports.AntRecordSchema = exports.AntKeywordsSchema = exports.AntDescriptionSchema = exports.IntegerStringSchema = exports.AOAddressSchema = exports.ArweaveTxIdSchema = void 0;
4
4
  /**
5
5
  * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
6
6
  *
@@ -37,6 +37,9 @@ exports.ArweaveTxIdSchema = zod_1.z
37
37
  .refine((val) => constants_js_1.ARWEAVE_TX_REGEX.test(val), {
38
38
  message: 'Must be an Arweave Transaction ID',
39
39
  });
40
+ exports.AOAddressSchema = zod_1.z.string({
41
+ description: 'AO Address',
42
+ });
40
43
  exports.IntegerStringSchema = zod_1.z
41
44
  .string({
42
45
  description: 'Integer String',
@@ -53,8 +56,8 @@ exports.AntRecordSchema = zod_1.z.object({
53
56
  priority: zod_1.z.number().optional(),
54
57
  });
55
58
  exports.AntRecordsSchema = zod_1.z.record(zod_1.z.string(), exports.AntRecordSchema);
56
- exports.AntControllersSchema = zod_1.z.array(exports.ArweaveTxIdSchema.describe('Controller address'));
57
- exports.AntBalancesSchema = zod_1.z.record(exports.ArweaveTxIdSchema.describe('Holder address'), zod_1.z.number());
59
+ exports.AntControllersSchema = zod_1.z.array(exports.AOAddressSchema.describe('Controller address'));
60
+ exports.AntBalancesSchema = zod_1.z.record(exports.AOAddressSchema.describe('Holder address'), zod_1.z.number());
58
61
  exports.AntStateSchema = zod_1.z.object({
59
62
  Name: zod_1.z.string().describe('The name of the ANT.'),
60
63
  Ticker: zod_1.z.string().describe('The ticker symbol for the ANT.'),
@@ -64,7 +67,7 @@ exports.AntStateSchema = zod_1.z.object({
64
67
  .number()
65
68
  .describe('The number of decimal places to use for the ANT. Defaults to 0 if not set representing whole numbers.')
66
69
  .min(0, { message: 'Denomination must be a non-negative number' }),
67
- Owner: exports.ArweaveTxIdSchema.describe('The Owners address.'),
70
+ Owner: exports.AOAddressSchema.describe('The Owners address.'),
68
71
  Controllers: exports.AntControllersSchema.describe('Controllers of the ANT who have administrative privileges.'),
69
72
  Records: exports.AntRecordsSchema.describe('Records associated with the ANT.'),
70
73
  Balances: exports.AntBalancesSchema.describe('Balance details for each address holding the ANT.'),
@@ -4,7 +4,8 @@ const node_assert_1 = require("node:assert");
4
4
  const node_test_1 = require("node:test");
5
5
  const zod_1 = require("zod");
6
6
  const ant_js_1 = require("./ant.js");
7
- const stub_address = 'valid-address'.padEnd(43, '1');
7
+ const stub_arweave_address = 'valid-address'.padEnd(43, '1');
8
+ const stub_eth_address = '0x8B5f221c8837d862b818799e6b19cc23CE23B0E5';
8
9
  (0, node_test_1.describe)('ANT Schemas', () => {
9
10
  (0, node_test_1.it)('should validate AntStateSchema', () => {
10
11
  const validState = {
@@ -13,18 +14,18 @@ const stub_address = 'valid-address'.padEnd(43, '1');
13
14
  Description: 'Test description',
14
15
  Keywords: ['keyword1', 'keyword2', 'keyword3'],
15
16
  Denomination: 0,
16
- Owner: stub_address,
17
- Controllers: [stub_address],
17
+ Owner: stub_arweave_address,
18
+ Controllers: [stub_arweave_address],
18
19
  Records: {
19
20
  record1: {
20
- transactionId: stub_address,
21
+ transactionId: stub_arweave_address,
21
22
  ttlSeconds: 3600,
22
23
  },
23
24
  },
24
25
  Balances: {
25
- [stub_address]: 1,
26
+ [stub_arweave_address]: 1,
26
27
  },
27
- Logo: stub_address,
28
+ Logo: stub_arweave_address,
28
29
  TotalSupply: 1,
29
30
  Initialized: true,
30
31
  };
@@ -34,8 +35,8 @@ const stub_address = 'valid-address'.padEnd(43, '1');
34
35
  Description: 'Test description',
35
36
  Keywords: ['keyword1', 'keyword2', 'keyword3'],
36
37
  Denomination: 0,
37
- Owner: stub_address,
38
- Controllers: [stub_address],
38
+ Owner: stub_arweave_address,
39
+ Controllers: [stub_arweave_address],
39
40
  Records: {
40
41
  record1: {
41
42
  transactionId: 'invalid-id',
@@ -43,33 +44,57 @@ const stub_address = 'valid-address'.padEnd(43, '1');
43
44
  },
44
45
  },
45
46
  Balances: {
46
- [stub_address]: 1,
47
+ [stub_arweave_address]: 1,
47
48
  },
48
- Logo: stub_address,
49
+ Logo: stub_arweave_address,
49
50
  TotalSupply: -1,
50
51
  Initialized: true,
51
52
  };
52
53
  node_assert_1.strict.doesNotThrow(() => ant_js_1.AntStateSchema.parse(validState));
53
54
  node_assert_1.strict.throws(() => ant_js_1.AntStateSchema.parse(invalidState), zod_1.z.ZodError);
54
55
  });
56
+ (0, node_test_1.it)('should validate AntStateSchema with ETH address', () => {
57
+ const validState = {
58
+ Name: 'TestToken',
59
+ Ticker: 'TST',
60
+ Description: 'Test description',
61
+ Keywords: ['keyword1', 'keyword2', 'keyword3'],
62
+ Denomination: 0,
63
+ Owner: stub_eth_address,
64
+ Controllers: [stub_eth_address],
65
+ Records: {
66
+ record1: {
67
+ transactionId: stub_arweave_address,
68
+ ttlSeconds: 3600,
69
+ },
70
+ },
71
+ Balances: {
72
+ [stub_eth_address]: 1,
73
+ },
74
+ Logo: stub_arweave_address,
75
+ TotalSupply: 1,
76
+ Initialized: true,
77
+ };
78
+ node_assert_1.strict.doesNotThrow(() => ant_js_1.AntStateSchema.parse(validState));
79
+ });
55
80
  (0, node_test_1.it)('should validate AntInfoSchema', () => {
56
81
  const validInfo = {
57
82
  Name: 'TestToken',
58
- Owner: stub_address,
83
+ Owner: stub_arweave_address,
59
84
  Ticker: 'TST',
60
85
  Description: 'Test description',
61
86
  Keywords: ['keyword1', 'keyword2', 'keyword3'],
62
87
  ['Total-Supply']: '1',
63
- Logo: stub_address,
88
+ Logo: stub_arweave_address,
64
89
  Denomination: '0',
65
90
  Handlers: ant_js_1.AntHandlerNames,
66
91
  };
67
92
  const invalidInfo = {
68
93
  Name: 'TestToken',
69
- Owner: stub_address,
94
+ Owner: stub_arweave_address,
70
95
  Ticker: 'TST',
71
96
  ['Total-Supply']: 1000,
72
- Logo: stub_address,
97
+ Logo: stub_arweave_address,
73
98
  Denomination: '1',
74
99
  Handlers: ant_js_1.AntHandlerNames,
75
100
  };
@@ -83,18 +108,18 @@ const stub_address = 'valid-address'.padEnd(43, '1');
83
108
  Description: 'Test description',
84
109
  Keywords: ['keyword1', 'keyword2', 'keyword3'],
85
110
  Denomination: 0,
86
- Owner: stub_address,
87
- Controllers: [stub_address],
111
+ Owner: stub_arweave_address,
112
+ Controllers: [stub_arweave_address],
88
113
  Records: {
89
114
  record1: {
90
- transactionId: stub_address,
115
+ transactionId: stub_arweave_address,
91
116
  ttlSeconds: 3600,
92
117
  },
93
118
  },
94
119
  Balances: {
95
- [stub_address]: 1,
120
+ [stub_arweave_address]: 1,
96
121
  },
97
- Logo: stub_address,
122
+ Logo: stub_arweave_address,
98
123
  TotalSupply: 0,
99
124
  Initialized: true,
100
125
  };
@@ -104,8 +129,8 @@ const stub_address = 'valid-address'.padEnd(43, '1');
104
129
  Description: 'Test description',
105
130
  Keywords: ['keyword1', 'keyword2', 'keyword3'],
106
131
  Denomination: 0,
107
- Owner: stub_address,
108
- Controllers: [stub_address],
132
+ Owner: stub_arweave_address,
133
+ Controllers: [stub_arweave_address],
109
134
  Records: {
110
135
  record1: {
111
136
  transactionId: 'invalid-id',
@@ -113,9 +138,9 @@ const stub_address = 'valid-address'.padEnd(43, '1');
113
138
  },
114
139
  },
115
140
  Balances: {
116
- [stub_address]: 1,
141
+ [stub_arweave_address]: 1,
117
142
  },
118
- Logo: stub_address,
143
+ Logo: stub_arweave_address,
119
144
  TotalSupply: -1,
120
145
  Initialized: true,
121
146
  };
@@ -17,4 +17,4 @@
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.version = void 0;
19
19
  // AUTOMATICALLY GENERATED FILE - DO NOT TOUCH
20
- exports.version = '3.8.1';
20
+ exports.version = '3.8.2-alpha.2';
@@ -36,46 +36,25 @@ export class AOProcess {
36
36
  messageData === null);
37
37
  }
38
38
  async read({ tags, retries = 3, fromAddress, }) {
39
+ this.logger.debug(`Evaluating read interaction on process`, {
40
+ tags,
41
+ processId: this.processId,
42
+ });
43
+ // map tags to inputs
44
+ const dryRunInput = {
45
+ process: this.processId,
46
+ tags,
47
+ };
48
+ if (fromAddress !== undefined) {
49
+ dryRunInput['Owner'] = fromAddress;
50
+ }
39
51
  let attempts = 0;
40
- let lastError;
52
+ let result = undefined;
41
53
  while (attempts < retries) {
42
54
  try {
43
- this.logger.debug(`Evaluating read interaction on process`, {
44
- tags,
45
- processId: this.processId,
46
- });
47
- // map tags to inputs
48
- const dryRunInput = {
49
- process: this.processId,
50
- tags,
51
- };
52
- if (fromAddress !== undefined) {
53
- dryRunInput['Owner'] = fromAddress;
54
- }
55
- const result = await this.ao.dryrun(dryRunInput);
56
- this.logger.debug(`Read interaction result`, {
57
- result,
58
- processId: this.processId,
59
- });
60
- const error = errorMessageFromOutput(result);
61
- if (error !== undefined) {
62
- throw new Error(error);
63
- }
64
- if (result.Messages === undefined || result.Messages.length === 0) {
65
- this.logger.debug(`Process ${this.processId} does not support provided action.`, {
66
- result,
67
- tags,
68
- processId: this.processId,
69
- });
70
- throw new Error(`Process ${this.processId} does not support provided action.`);
71
- }
72
- const messageData = result.Messages?.[0]?.Data;
73
- // return undefined if no data is returned
74
- if (this.isMessageDataEmpty(messageData)) {
75
- return undefined;
76
- }
77
- const response = safeDecode(messageData);
78
- return response;
55
+ result = await this.ao.dryrun(dryRunInput);
56
+ // break on successful return of result
57
+ break;
79
58
  }
80
59
  catch (error) {
81
60
  attempts++;
@@ -85,17 +64,45 @@ export class AOProcess {
85
64
  tags,
86
65
  processId: this.processId,
87
66
  });
88
- lastError = error;
67
+ if (attempts >= retries) {
68
+ throw error;
69
+ }
89
70
  // exponential backoff
90
71
  await new Promise((resolve) => setTimeout(resolve, 2 ** attempts * 1000));
91
72
  }
92
73
  }
93
- throw lastError;
74
+ if (result === undefined) {
75
+ throw new Error('Unexpected error when evaluating read interaction');
76
+ }
77
+ this.logger.debug(`Read interaction result`, {
78
+ result,
79
+ processId: this.processId,
80
+ });
81
+ const error = errorMessageFromOutput(result);
82
+ if (error !== undefined) {
83
+ throw new Error(error);
84
+ }
85
+ if (result.Messages === undefined || result.Messages.length === 0) {
86
+ this.logger.debug(`Process ${this.processId} does not support provided action.`, {
87
+ result,
88
+ tags,
89
+ processId: this.processId,
90
+ });
91
+ throw new Error(`Process ${this.processId} does not support provided action.`);
92
+ }
93
+ const messageData = result.Messages?.[0]?.Data;
94
+ // return undefined if no data is returned
95
+ if (this.isMessageDataEmpty(messageData)) {
96
+ return undefined;
97
+ }
98
+ const response = safeDecode(messageData);
99
+ return response;
94
100
  }
95
101
  async send({ tags, data, signer, retries = 3, }) {
96
102
  // main purpose of retries is to handle network errors/new process delays
97
103
  let attempts = 0;
98
- let lastError;
104
+ let messageId;
105
+ let result = undefined;
99
106
  while (attempts < retries) {
100
107
  try {
101
108
  this.logger.debug(`Evaluating send interaction on contract`, {
@@ -106,7 +113,7 @@ export class AOProcess {
106
113
  // TODO: do a read as a dry run to check if the process supports the action
107
114
  // anchor is a random text produce non-deterministic messages IDs when deterministic signers are provided (ETH)
108
115
  const anchor = getRandomText(32);
109
- const messageId = await this.ao.message({
116
+ messageId = await this.ao.message({
110
117
  process: this.processId,
111
118
  // TODO: any other default tags we want to add?
112
119
  tags: [...tags, { name: 'AR-IO-SDK', value: version }],
@@ -120,36 +127,16 @@ export class AOProcess {
120
127
  anchor,
121
128
  });
122
129
  // check the result of the send interaction
123
- const output = await this.ao.result({
130
+ result = await this.ao.result({
124
131
  message: messageId,
125
132
  process: this.processId,
126
133
  });
127
134
  this.logger.debug('Message result', {
128
- output,
129
- messageId,
130
- processId: this.processId,
131
- });
132
- const error = errorMessageFromOutput(output);
133
- if (error !== undefined) {
134
- throw new WriteInteractionError(error);
135
- }
136
- // check if there are any Messages in the output
137
- if (output.Messages?.length === 0 || output.Messages === undefined) {
138
- return { id: messageId };
139
- }
140
- if (output.Messages.length === 0) {
141
- throw new Error(`Process ${this.processId} does not support provided action.`);
142
- }
143
- if (this.isMessageDataEmpty(output.Messages[0].Data)) {
144
- return { id: messageId };
145
- }
146
- const resultData = safeDecode(output.Messages[0].Data);
147
- this.logger.debug('Message result data', {
148
- resultData,
135
+ result,
149
136
  messageId,
150
137
  processId: this.processId,
151
138
  });
152
- return { id: messageId, result: resultData };
139
+ break;
153
140
  }
154
141
  catch (error) {
155
142
  this.logger.error('Error sending message to process', {
@@ -158,23 +145,43 @@ export class AOProcess {
158
145
  processId: this.processId,
159
146
  tags,
160
147
  });
161
- // throw on write interaction errors. No point retrying write interactions, waste of gas.
162
- if (error.message.includes('500')) {
163
- this.logger.debug('Retrying send interaction', {
164
- attempts,
165
- retries,
166
- error: error?.message,
167
- processId: this.processId,
168
- });
169
- // exponential backoff
170
- await new Promise((resolve) => setTimeout(resolve, 2 ** attempts * 2000));
171
- attempts++;
172
- lastError = error;
173
- }
174
- else
148
+ attempts++;
149
+ this.logger.debug('Retrying send interaction', {
150
+ attempts,
151
+ retries,
152
+ error: error?.message,
153
+ processId: this.processId,
154
+ });
155
+ if (attempts >= retries) {
175
156
  throw error;
157
+ }
158
+ // exponential backoff
159
+ await new Promise((resolve) => setTimeout(resolve, 2 ** attempts * 2000));
176
160
  }
177
161
  }
178
- throw lastError;
162
+ if (result === undefined || messageId === undefined) {
163
+ throw new Error('Unexpected error when evaluating write interaction');
164
+ }
165
+ const error = errorMessageFromOutput(result);
166
+ if (error !== undefined) {
167
+ throw new WriteInteractionError(error);
168
+ }
169
+ // check if there are any Messages in the output
170
+ if (result.Messages?.length === 0 || result.Messages === undefined) {
171
+ return { id: messageId };
172
+ }
173
+ if (result.Messages.length === 0) {
174
+ throw new Error(`Process ${this.processId} does not support provided action.`);
175
+ }
176
+ if (this.isMessageDataEmpty(result.Messages[0].Data)) {
177
+ return { id: messageId };
178
+ }
179
+ const resultData = safeDecode(result.Messages[0].Data);
180
+ this.logger.debug('Message result data', {
181
+ resultData,
182
+ messageId,
183
+ processId: this.processId,
184
+ });
185
+ return { id: messageId, result: resultData };
179
186
  }
180
187
  }
@@ -34,6 +34,9 @@ export const ArweaveTxIdSchema = z
34
34
  .refine((val) => ARWEAVE_TX_REGEX.test(val), {
35
35
  message: 'Must be an Arweave Transaction ID',
36
36
  });
37
+ export const AOAddressSchema = z.string({
38
+ description: 'AO Address',
39
+ });
37
40
  export const IntegerStringSchema = z
38
41
  .string({
39
42
  description: 'Integer String',
@@ -50,8 +53,8 @@ export const AntRecordSchema = z.object({
50
53
  priority: z.number().optional(),
51
54
  });
52
55
  export const AntRecordsSchema = z.record(z.string(), AntRecordSchema);
53
- export const AntControllersSchema = z.array(ArweaveTxIdSchema.describe('Controller address'));
54
- export const AntBalancesSchema = z.record(ArweaveTxIdSchema.describe('Holder address'), z.number());
56
+ export const AntControllersSchema = z.array(AOAddressSchema.describe('Controller address'));
57
+ export const AntBalancesSchema = z.record(AOAddressSchema.describe('Holder address'), z.number());
55
58
  export const AntStateSchema = z.object({
56
59
  Name: z.string().describe('The name of the ANT.'),
57
60
  Ticker: z.string().describe('The ticker symbol for the ANT.'),
@@ -61,7 +64,7 @@ export const AntStateSchema = z.object({
61
64
  .number()
62
65
  .describe('The number of decimal places to use for the ANT. Defaults to 0 if not set representing whole numbers.')
63
66
  .min(0, { message: 'Denomination must be a non-negative number' }),
64
- Owner: ArweaveTxIdSchema.describe('The Owners address.'),
67
+ Owner: AOAddressSchema.describe('The Owners address.'),
65
68
  Controllers: AntControllersSchema.describe('Controllers of the ANT who have administrative privileges.'),
66
69
  Records: AntRecordsSchema.describe('Records associated with the ANT.'),
67
70
  Balances: AntBalancesSchema.describe('Balance details for each address holding the ANT.'),