@ar.io/sdk 3.24.0 → 4.0.0-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.
Files changed (169) hide show
  1. package/README.md +757 -589
  2. package/lib/esm/cli/cli.js +188 -152
  3. package/lib/esm/cli/commands/antCommands.js +23 -58
  4. package/lib/esm/cli/commands/arnsPurchaseCommands.js +48 -30
  5. package/lib/esm/cli/commands/escrowCommands.js +227 -0
  6. package/lib/esm/cli/commands/gatewayWriteCommands.js +140 -23
  7. package/lib/esm/cli/commands/pruneCommands.js +154 -0
  8. package/lib/esm/cli/commands/readCommands.js +22 -3
  9. package/lib/esm/cli/commands/transfer.js +6 -6
  10. package/lib/esm/cli/options.js +124 -58
  11. package/lib/esm/cli/utils.js +303 -175
  12. package/lib/esm/common/ant-registry.js +17 -143
  13. package/lib/esm/common/ant.js +44 -1167
  14. package/lib/esm/common/faucet.js +17 -6
  15. package/lib/esm/common/index.js +0 -4
  16. package/lib/esm/common/io.js +25 -1412
  17. package/lib/esm/constants.js +13 -19
  18. package/lib/esm/solana/ant-readable.js +724 -0
  19. package/lib/esm/solana/ant-registry-readable.js +133 -0
  20. package/lib/esm/solana/ant-registry-writeable.js +472 -0
  21. package/lib/esm/solana/ant-writeable.js +384 -0
  22. package/lib/esm/solana/ata.js +70 -0
  23. package/lib/esm/solana/canonical-message.js +128 -0
  24. package/lib/esm/solana/clusters.js +111 -0
  25. package/lib/esm/solana/constants.js +146 -0
  26. package/lib/esm/solana/delegation-math.js +112 -0
  27. package/lib/esm/solana/deserialize.js +711 -0
  28. package/lib/esm/solana/escrow.js +839 -0
  29. package/lib/{cjs/utils/json.js → esm/solana/events.js} +15 -10
  30. package/lib/esm/solana/funding-plan.js +699 -0
  31. package/lib/esm/solana/index.js +126 -0
  32. package/lib/esm/solana/instruction.js +39 -0
  33. package/lib/esm/solana/io-readable.js +2182 -0
  34. package/lib/esm/solana/io-writeable.js +3196 -0
  35. package/lib/esm/solana/json-rpc.js +90 -0
  36. package/lib/esm/solana/metadata.js +81 -0
  37. package/lib/esm/solana/mpl-core.js +192 -0
  38. package/lib/esm/solana/pda.js +332 -0
  39. package/lib/esm/solana/predict-prescribed-observers.js +110 -0
  40. package/lib/esm/solana/retry.js +117 -0
  41. package/lib/esm/solana/rpc-circuit-breaker.js +258 -0
  42. package/lib/esm/solana/send.js +372 -0
  43. package/lib/esm/solana/spawn-ant.js +224 -0
  44. package/lib/esm/solana/types.js +1 -0
  45. package/lib/esm/types/ant.js +27 -15
  46. package/lib/esm/types/io.js +8 -11
  47. package/lib/esm/utils/ant.js +0 -63
  48. package/lib/esm/utils/index.js +0 -3
  49. package/lib/esm/version.js +1 -1
  50. package/lib/types/cli/commands/antCommands.d.ts +5 -13
  51. package/lib/types/cli/commands/arnsPurchaseCommands.d.ts +33 -7
  52. package/lib/types/cli/commands/escrowCommands.d.ts +68 -0
  53. package/lib/types/cli/commands/gatewayWriteCommands.d.ts +12 -11
  54. package/lib/types/cli/commands/pruneCommands.d.ts +31 -0
  55. package/lib/types/cli/commands/readCommands.d.ts +27 -22
  56. package/lib/types/cli/commands/transfer.d.ts +9 -9
  57. package/lib/types/cli/options.d.ts +76 -21
  58. package/lib/types/cli/types.d.ts +11 -13
  59. package/lib/types/cli/utils.d.ts +71 -31
  60. package/lib/types/common/ant-registry.d.ts +49 -47
  61. package/lib/types/common/ant.d.ts +54 -539
  62. package/lib/types/common/faucet.d.ts +20 -8
  63. package/lib/types/common/index.d.ts +0 -3
  64. package/lib/types/common/io.d.ts +66 -258
  65. package/lib/types/constants.d.ts +11 -18
  66. package/lib/types/solana/ant-readable.d.ts +180 -0
  67. package/lib/types/solana/ant-registry-readable.d.ts +105 -0
  68. package/lib/types/solana/ant-registry-writeable.d.ts +249 -0
  69. package/lib/types/solana/ant-writeable.d.ts +177 -0
  70. package/lib/types/solana/ata.d.ts +44 -0
  71. package/lib/types/solana/canonical-message.d.ts +121 -0
  72. package/lib/types/solana/clusters.d.ts +109 -0
  73. package/lib/types/solana/constants.d.ts +119 -0
  74. package/lib/types/solana/delegation-math.d.ts +45 -0
  75. package/lib/types/solana/deserialize.d.ts +262 -0
  76. package/lib/types/solana/escrow.d.ts +480 -0
  77. package/lib/types/solana/events.d.ts +38 -0
  78. package/lib/types/solana/funding-plan.d.ts +225 -0
  79. package/lib/types/solana/index.d.ts +87 -0
  80. package/lib/types/solana/instruction.d.ts +39 -0
  81. package/lib/types/solana/io-readable.d.ts +499 -0
  82. package/lib/types/solana/io-writeable.d.ts +893 -0
  83. package/lib/types/solana/json-rpc.d.ts +47 -0
  84. package/lib/types/solana/metadata.d.ts +84 -0
  85. package/lib/types/solana/mpl-core.d.ts +120 -0
  86. package/lib/types/solana/pda.d.ts +95 -0
  87. package/lib/types/solana/predict-prescribed-observers.d.ts +28 -0
  88. package/lib/types/solana/retry.d.ts +62 -0
  89. package/lib/types/solana/rpc-circuit-breaker.d.ts +78 -0
  90. package/lib/types/solana/send.d.ts +94 -0
  91. package/lib/types/solana/spawn-ant.d.ts +145 -0
  92. package/lib/types/solana/types.d.ts +82 -0
  93. package/lib/types/types/ant-registry.d.ts +43 -4
  94. package/lib/types/types/ant.d.ts +114 -96
  95. package/lib/types/types/common.d.ts +18 -74
  96. package/lib/types/types/faucet.d.ts +2 -2
  97. package/lib/types/types/io.d.ts +244 -158
  98. package/lib/types/types/token.d.ts +0 -12
  99. package/lib/types/utils/ant.d.ts +1 -12
  100. package/lib/types/utils/index.d.ts +0 -3
  101. package/lib/types/version.d.ts +1 -1
  102. package/package.json +36 -33
  103. package/lib/cjs/cli/cli.js +0 -822
  104. package/lib/cjs/cli/commands/antCommands.js +0 -113
  105. package/lib/cjs/cli/commands/arnsPurchaseCommands.js +0 -212
  106. package/lib/cjs/cli/commands/gatewayWriteCommands.js +0 -210
  107. package/lib/cjs/cli/commands/readCommands.js +0 -215
  108. package/lib/cjs/cli/commands/transfer.js +0 -159
  109. package/lib/cjs/cli/options.js +0 -470
  110. package/lib/cjs/cli/types.js +0 -2
  111. package/lib/cjs/cli/utils.js +0 -639
  112. package/lib/cjs/common/ant-registry.js +0 -155
  113. package/lib/cjs/common/ant-versions.js +0 -93
  114. package/lib/cjs/common/ant.js +0 -1182
  115. package/lib/cjs/common/arweave.js +0 -27
  116. package/lib/cjs/common/contracts/ao-process.js +0 -224
  117. package/lib/cjs/common/error.js +0 -64
  118. package/lib/cjs/common/faucet.js +0 -150
  119. package/lib/cjs/common/hyperbeam/hb.js +0 -173
  120. package/lib/cjs/common/index.js +0 -42
  121. package/lib/cjs/common/io.js +0 -1423
  122. package/lib/cjs/common/logger.js +0 -83
  123. package/lib/cjs/common/loggers/winston.js +0 -68
  124. package/lib/cjs/common/marketplace.js +0 -731
  125. package/lib/cjs/common/turbo.js +0 -223
  126. package/lib/cjs/constants.js +0 -41
  127. package/lib/cjs/node/index.js +0 -39
  128. package/lib/cjs/package.json +0 -1
  129. package/lib/cjs/types/ant-registry.js +0 -2
  130. package/lib/cjs/types/ant.js +0 -168
  131. package/lib/cjs/types/common.js +0 -2
  132. package/lib/cjs/types/faucet.js +0 -2
  133. package/lib/cjs/types/index.js +0 -37
  134. package/lib/cjs/types/io.js +0 -51
  135. package/lib/cjs/types/token.js +0 -116
  136. package/lib/cjs/utils/ant.js +0 -108
  137. package/lib/cjs/utils/ao.js +0 -432
  138. package/lib/cjs/utils/arweave.js +0 -285
  139. package/lib/cjs/utils/base64.js +0 -62
  140. package/lib/cjs/utils/hash.js +0 -56
  141. package/lib/cjs/utils/index.js +0 -38
  142. package/lib/cjs/utils/processes.js +0 -173
  143. package/lib/cjs/utils/random.js +0 -30
  144. package/lib/cjs/utils/schema.js +0 -15
  145. package/lib/cjs/utils/url.js +0 -37
  146. package/lib/cjs/version.js +0 -20
  147. package/lib/cjs/web/index.js +0 -41
  148. package/lib/esm/common/ant-versions.js +0 -87
  149. package/lib/esm/common/arweave.js +0 -21
  150. package/lib/esm/common/contracts/ao-process.js +0 -220
  151. package/lib/esm/common/hyperbeam/hb.js +0 -169
  152. package/lib/esm/common/marketplace.js +0 -724
  153. package/lib/esm/common/turbo.js +0 -215
  154. package/lib/esm/node/index.js +0 -20
  155. package/lib/esm/utils/ao.js +0 -420
  156. package/lib/esm/utils/arweave.js +0 -271
  157. package/lib/esm/utils/processes.js +0 -167
  158. package/lib/esm/web/index.js +0 -20
  159. package/lib/types/common/ant-versions.d.ts +0 -39
  160. package/lib/types/common/arweave.d.ts +0 -17
  161. package/lib/types/common/contracts/ao-process.d.ts +0 -47
  162. package/lib/types/common/hyperbeam/hb.d.ts +0 -88
  163. package/lib/types/common/marketplace.d.ts +0 -568
  164. package/lib/types/common/turbo.d.ts +0 -61
  165. package/lib/types/node/index.d.ts +0 -20
  166. package/lib/types/utils/ao.d.ts +0 -80
  167. package/lib/types/utils/arweave.d.ts +0 -79
  168. package/lib/types/utils/processes.d.ts +0 -39
  169. package/lib/types/web/index.d.ts +0 -20
@@ -1,215 +0,0 @@
1
- /**
2
- * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
- import { ArconnectSigner, ArweaveSigner, EthereumSigner, InjectedEthereumSigner, SignatureConfig, } from '@dha-team/arbundles';
17
- import { mARIOToken } from '../types/token.js';
18
- import { toB64Url } from '../utils/base64.js';
19
- import { urlWithSearchParams } from '../utils/url.js';
20
- import { version } from '../version.js';
21
- import { Logger } from './logger.js';
22
- export const defaultHeaders = {
23
- 'x-source-version': `${version}`,
24
- 'x-source-identifier': 'ar-io-sdk',
25
- };
26
- export async function signedRequestHeadersFromSigner({ signer, nonce = crypto.randomUUID(), }) {
27
- let signature = undefined;
28
- let publicKey = undefined;
29
- const signatureType = isWanderArweaveBrowserSigner(signer)
30
- ? SignatureConfig.ARWEAVE
31
- : signer.signatureType;
32
- // equivalent to window.arweaveWallet
33
- if (isWanderArweaveBrowserSigner(signer)) {
34
- signature = toB64Url(Buffer.from(await signer.signMessage(Uint8Array.from(Buffer.from(nonce)))));
35
- }
36
- else if (signer instanceof ArconnectSigner) {
37
- signature = toB64Url(Buffer.from(await signer['signer'].signMessage(Uint8Array.from(Buffer.from(nonce)))));
38
- }
39
- else if (signer instanceof ArweaveSigner ||
40
- signer instanceof EthereumSigner ||
41
- signer instanceof InjectedEthereumSigner) {
42
- if ('setPublicKey' in signer && signer['publicKey'] === undefined) {
43
- await signer.setPublicKey();
44
- }
45
- signature = toB64Url(Buffer.from(await signer.sign(Uint8Array.from(Buffer.from(nonce)))));
46
- }
47
- switch (signatureType) {
48
- case SignatureConfig.ARWEAVE:
49
- if (isWanderArweaveBrowserSigner(signer)) {
50
- publicKey = await signer.getActivePublicKey();
51
- }
52
- else if ('setPublicKey' in signer) {
53
- await signer.setPublicKey();
54
- publicKey = toB64Url(signer.publicKey);
55
- }
56
- else if ('publicKey' in signer) {
57
- publicKey = toB64Url(signer.publicKey);
58
- }
59
- break;
60
- case SignatureConfig.ETHEREUM:
61
- if ('publicKey' in signer) {
62
- publicKey = '0x' + signer.publicKey.toString('hex');
63
- }
64
- else {
65
- throw new Error('Public key not found');
66
- }
67
- break;
68
- // TODO: solana sig support
69
- // case SignatureConfig.SOLANA:
70
- // case SignatureConfig.ED25519:
71
- default:
72
- throw new Error(`Unsupported signer type for signing requests: ${signatureType}`);
73
- }
74
- if (publicKey === undefined || signature === undefined) {
75
- throw new Error('Public key or signature not found');
76
- }
77
- return {
78
- 'x-public-key': publicKey,
79
- 'x-nonce': nonce,
80
- 'x-signature': signature,
81
- 'x-signature-type': signatureType.toString(),
82
- };
83
- }
84
- export class TurboArNSPaymentFactory {
85
- static init(config) {
86
- const { signer, paymentUrl, logger } = config ?? {};
87
- if (signer !== undefined) {
88
- return new TurboArNSPaymentProviderAuthenticated({
89
- signer,
90
- paymentUrl,
91
- logger,
92
- });
93
- }
94
- return new TurboArNSPaymentProviderUnauthenticated({
95
- paymentUrl,
96
- logger,
97
- });
98
- }
99
- }
100
- // Base class for unauthenticated operations
101
- export class TurboArNSPaymentProviderUnauthenticated {
102
- paymentUrl;
103
- logger;
104
- constructor({ paymentUrl = 'https://payment.ardrive.io', logger = Logger.default, }) {
105
- this.paymentUrl = paymentUrl;
106
- this.logger = logger;
107
- }
108
- async getArNSPriceDetails({ intent, name, quantity, type, years, }) {
109
- const url = urlWithSearchParams({
110
- baseUrl: `${this.paymentUrl}/v1/arns/price/${intent}/${name}`,
111
- params: {
112
- increaseQty: quantity,
113
- type,
114
- years,
115
- },
116
- });
117
- const response = await fetch(url, {
118
- method: 'GET',
119
- headers: defaultHeaders,
120
- });
121
- const status = response.status;
122
- const data = (await response.json());
123
- this.logger.debug('getArNSPriceDetails', {
124
- intent,
125
- name,
126
- quantity,
127
- type,
128
- years,
129
- data,
130
- status,
131
- });
132
- if (status !== 200) {
133
- throw new Error('Failed to get ArNS purchase price ' + JSON.stringify(data));
134
- }
135
- if (!data.winc || !data.mARIO) {
136
- throw new Error('Invalid response from Turbo ' + JSON.stringify(data));
137
- }
138
- return {
139
- winc: data.winc,
140
- mARIO: new mARIOToken(+data.mARIO),
141
- };
142
- }
143
- async getPrice(params) {
144
- const { winc } = await this.getArNSPriceDetails(params);
145
- return +winc;
146
- }
147
- }
148
- // Class for authenticated operations, extending the base class
149
- export class TurboArNSPaymentProviderAuthenticated extends TurboArNSPaymentProviderUnauthenticated {
150
- signer;
151
- constructor({ signer, ...restConfig }) {
152
- super(restConfig); // Pass unauthenticated config to base class+
153
- if (!isTurboArNSSigner(signer)) {
154
- throw new Error('Signer must be a TurboArNSSigner');
155
- }
156
- this.signer = signer;
157
- }
158
- async initiateArNSPurchase({ intent, name, quantity, type, processId, years, paidBy = [], referrer, }) {
159
- // Signer check is implicitly handled by requiring it in the constructor
160
- const url = urlWithSearchParams({
161
- baseUrl: `${this.paymentUrl}/v1/arns/purchase/${intent}/${name}`,
162
- params: {
163
- increaseQty: quantity,
164
- processId,
165
- type,
166
- years,
167
- paidBy,
168
- referrer,
169
- },
170
- });
171
- const signedHeaders = await signedRequestHeadersFromSigner({
172
- signer: this.signer,
173
- });
174
- const response = await fetch(url, {
175
- method: 'POST',
176
- headers: {
177
- ...defaultHeaders,
178
- ...signedHeaders,
179
- },
180
- });
181
- const status = response.status;
182
- const data = (await response.json());
183
- this.logger.debug('Initiated ArNS purchase', {
184
- intent,
185
- name,
186
- quantity,
187
- processId,
188
- type,
189
- years,
190
- data,
191
- status,
192
- });
193
- if (status !== 200) {
194
- throw new Error('Failed to initiate ArNS purchase ' + JSON.stringify(data));
195
- }
196
- return {
197
- id: data.arioWriteResult.id,
198
- result: data.purchaseReceipt,
199
- };
200
- }
201
- }
202
- function isWanderArweaveBrowserSigner(signer) {
203
- return (typeof signer === 'object' &&
204
- signer !== null &&
205
- 'signMessage' in signer &&
206
- 'getActivePublicKey' in signer);
207
- }
208
- export function isTurboArNSSigner(signer) {
209
- const isWanderWallet = isWanderArweaveBrowserSigner(signer);
210
- const isSigner = signer instanceof EthereumSigner ||
211
- signer instanceof InjectedEthereumSigner ||
212
- signer instanceof ArweaveSigner ||
213
- signer instanceof ArconnectSigner;
214
- return isWanderWallet || isSigner;
215
- }
@@ -1,20 +0,0 @@
1
- /**
2
- * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
- export { ArweaveSigner, ArconnectSigner } from '@dha-team/arbundles';
17
- export * from '../types/index.js';
18
- export * from '../common/index.js';
19
- export * from '../constants.js';
20
- export * from '../utils/index.js';
@@ -1,420 +0,0 @@
1
- /**
2
- * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
- import { ArconnectSigner, DataItem, createData } from '@dha-team/arbundles';
17
- import { connect, createDataItemSigner } from '@permaweb/aoconnect';
18
- import { z } from 'zod';
19
- import { ANTRegistry } from '../common/ant-registry.js';
20
- import { ANTVersions } from '../common/ant-versions.js';
21
- import { defaultArweave } from '../common/arweave.js';
22
- import { ANT, AOProcess, Logger } from '../common/index.js';
23
- import { ANT_LUA_ID, ANT_REGISTRY_ID, AO_AUTHORITY, DEFAULT_SCHEDULER_ID, } from '../constants.js';
24
- import { SpawnANTStateSchema } from '../types/ant.js';
25
- import { parseSchemaResult } from './schema.js';
26
- export async function spawnANT({ signer, module, ao = connect({
27
- MODE: 'legacy',
28
- }), scheduler = DEFAULT_SCHEDULER_ID, state, tags = [], antRegistryId = ANT_REGISTRY_ID, logger = Logger.default, authority = AO_AUTHORITY, onSigningProgress = (name, payload) => {
29
- logger.debug('Signing progress', { name, payload });
30
- }, hyperbeamUrl, }) {
31
- if (state) {
32
- parseSchemaResult(SpawnANTStateSchema, state);
33
- }
34
- let version;
35
- if (module === undefined) {
36
- const antRegistry = ANTVersions.init({
37
- process: new AOProcess({
38
- processId: antRegistryId,
39
- ao,
40
- logger,
41
- }),
42
- });
43
- const { moduleId: latestAntModule, version: latestVersion } = await antRegistry.getLatestANTVersion();
44
- logger.debug('Spawning new ANT with latest module from ANT registry', {
45
- moduleId: latestAntModule,
46
- version: latestVersion,
47
- antRegistryId,
48
- });
49
- module = latestAntModule;
50
- version = latestVersion;
51
- }
52
- onSigningProgress?.('spawning-ant', {
53
- moduleId: module,
54
- antRegistryId,
55
- version,
56
- state,
57
- });
58
- const processId = await ao.spawn({
59
- module,
60
- scheduler,
61
- signer,
62
- data: state ? JSON.stringify(state) : undefined,
63
- tags: [
64
- // Required for AOS to initialize the authorities table
65
- {
66
- name: 'Authority',
67
- value: authority,
68
- },
69
- {
70
- name: 'ANT-Registry-Id',
71
- value: antRegistryId,
72
- },
73
- ...tags,
74
- ],
75
- });
76
- /**
77
- * Note: if we are given a state, ensure the ANT was initialized with it
78
- * there is a bug in the ANT source where we try to parse the empty default
79
- * 'Data' string as JSON that causes the Invalid-Boot-Notice error, even though
80
- * the ANT was initialized with the default state set by the ANT source code.
81
- *
82
- * Reference: https://github.com/ar-io/ar-io-ant-process/blob/b89018ffcce079add2e90e7ab82d0bbc9b671346/src/common/main.lua#L355-L358
83
- */
84
- if (state !== undefined) {
85
- let bootRes;
86
- let attempts = 0;
87
- while (attempts < 5 && bootRes === undefined) {
88
- try {
89
- // TODO: could add a progress event here to show the boot progress and number of attempts
90
- if (bootRes === undefined) {
91
- bootRes = await ao.result({
92
- process: processId,
93
- message: processId,
94
- });
95
- }
96
- break;
97
- }
98
- catch (error) {
99
- logger.debug('Retrying ANT boot result fetch', {
100
- processId,
101
- module,
102
- scheduler,
103
- attempts,
104
- error,
105
- });
106
- attempts++;
107
- await new Promise((resolve) => setTimeout(resolve, 1000 * attempts ** 2));
108
- }
109
- }
110
- if (bootRes === undefined ||
111
- bootRes.Messages?.some((m) => m?.Tags?.some((t) => t.value === 'Invalid-Boot-Notice'))) {
112
- if (bootRes === undefined) {
113
- throw new Error('Failed to get boot result');
114
- }
115
- const bootError = errorMessageFromOutput(bootRes);
116
- logger.error('ANT failed to boot correctly', {
117
- processId,
118
- module,
119
- scheduler,
120
- bootRes,
121
- bootError,
122
- });
123
- throw new Error(`ANT failed to boot correctly: ${bootError}`);
124
- }
125
- }
126
- onSigningProgress?.('verifying-state', {
127
- processId,
128
- moduleId: module,
129
- antRegistryId,
130
- });
131
- // Note: for hyperbeam caching, due to a SU issue, we need to send a second message to the ANT to cache the state
132
- // We wait for the first message to be processed before sending the second one to ensure this is the second message
133
- // We use the resulting state to check the owner of the ANT is set in the registry. Should this be patched on MUs,
134
- // we can convert to just a simple dry-run to avoid sending/signing another message.
135
- let owner;
136
- try {
137
- const processApi = new AOProcess({
138
- processId,
139
- ao,
140
- logger,
141
- });
142
- const { id } = await processApi.send({
143
- tags: [{ name: 'Action', value: 'State' }],
144
- signer,
145
- });
146
- const stateResult = await ao.result({
147
- process: processId,
148
- message: id,
149
- });
150
- if (stateResult === undefined) {
151
- throw new Error('Failed to get state result');
152
- }
153
- const { Owner } = JSON.parse(stateResult.Messages?.[0]?.Data ?? '{}');
154
- owner = Owner;
155
- logger.debug(`Successfully spawned new ANT and validated owner`, {
156
- processId,
157
- module,
158
- owner,
159
- });
160
- }
161
- catch (error) {
162
- logger.error('Failed to validate owner of spawned ANT', {
163
- processId,
164
- module,
165
- error,
166
- });
167
- throw error;
168
- }
169
- /**
170
- * Now confirm the owner of the ANT is set in the registry
171
- * This is to ensure the ANT is available via the ANT registry
172
- * for the owner to find and use the ANT.
173
- */
174
- if (owner === undefined) {
175
- throw new Error(`Spawning ANT (${processId}) failed to set owner`);
176
- }
177
- onSigningProgress?.('registering-ant', {
178
- processId,
179
- antRegistryId,
180
- owner,
181
- });
182
- // check the ACL for the owner
183
- const antRegistry = ANTRegistry.init({
184
- signer,
185
- process: new AOProcess({
186
- processId: antRegistryId,
187
- ao,
188
- logger,
189
- }),
190
- hyperbeamUrl,
191
- });
192
- let attempts = 0;
193
- const maxAttempts = 5;
194
- while (attempts < maxAttempts) {
195
- try {
196
- const acl = await antRegistry.accessControlList({ address: owner });
197
- if (acl === undefined) {
198
- throw new Error('ACL not found for owner');
199
- }
200
- const { Owned } = acl;
201
- if (!Owned.includes(processId)) {
202
- throw new Error(`Spawned ANT (${processId}) not found in registry for owner ${owner}`);
203
- }
204
- return processId;
205
- }
206
- catch (error) {
207
- logger.debug('Retrying ANT registry access control list fetch', {
208
- owner,
209
- antRegistryId,
210
- attempts,
211
- error,
212
- });
213
- attempts++;
214
- await new Promise((resolve) => setTimeout(resolve, 1000 * attempts ** 2));
215
- }
216
- }
217
- return processId;
218
- }
219
- export async function forkANT({ signer, antProcessId, logger = Logger.default, ao, moduleId, antRegistryId = ANT_REGISTRY_ID, onSigningProgress = (name, payload) => {
220
- logger.debug('Forking ANT', { name, payload });
221
- }, hyperbeamUrl, }) {
222
- // get the state of the current ANT and use it to spawn a new ANT
223
- const ant = ANT.init({
224
- process: new AOProcess({
225
- processId: antProcessId,
226
- ao,
227
- logger,
228
- }),
229
- hyperbeamUrl,
230
- });
231
- const state = await ant.getState();
232
- if (state === undefined) {
233
- throw new Error(`ANT state (${antProcessId}) is undefined and cannot be upgraded`);
234
- }
235
- const forkedProcessId = await spawnANT({
236
- signer,
237
- antRegistryId,
238
- ao,
239
- logger,
240
- module: moduleId,
241
- onSigningProgress,
242
- state: {
243
- owner: state.Owner,
244
- name: state.Name,
245
- ticker: state.Ticker,
246
- description: state.Description,
247
- keywords: state.Keywords,
248
- controllers: state.Controllers,
249
- records: state.Records,
250
- balances: state.Balances,
251
- logo: state.Logo,
252
- },
253
- hyperbeamUrl,
254
- });
255
- return forkedProcessId;
256
- }
257
- /**
258
- * @deprecated
259
- * Direct Evals are not encouraged when dealing with ANTs.
260
- * Instead, use spawnANT to fork an ANT to new module source code
261
- */
262
- export async function evolveANT({ signer, processId, luaCodeTxId = ANT_LUA_ID, ao = connect({
263
- MODE: 'legacy',
264
- }), logger = Logger.default, arweave = defaultArweave, }) {
265
- const aosClient = new AOProcess({
266
- processId,
267
- ao,
268
- logger,
269
- });
270
- logger.warn('Directly running an Eval on a process is not encouraged.');
271
- //TODO: cache locally and only fetch if not cached
272
- // We do not use arweave to get the data because it may throw on l2 tx data
273
- const { api: { host, port, protocol }, } = arweave.getConfig();
274
- const luaString = await fetch(`${protocol}://${host}:${port}/${luaCodeTxId}`).then((res) => res.text());
275
- const { id: evolveMsgId } = await aosClient.send({
276
- tags: [
277
- { name: 'Action', value: 'Eval' },
278
- { name: 'App-Name', value: 'ArNS-ANT' },
279
- { name: 'Source-Code-TX-ID', value: luaCodeTxId },
280
- ],
281
- data: luaString,
282
- signer,
283
- });
284
- logger.debug(`Evolved ANT`, {
285
- processId,
286
- luaCodeTxId,
287
- evalMsgId: evolveMsgId,
288
- });
289
- return evolveMsgId;
290
- }
291
- export function isAoSigner(value) {
292
- const TagSchema = z.object({
293
- name: z.string(),
294
- value: z.union([z.string(), z.number()]),
295
- });
296
- const AoSignerSchema = z
297
- .function()
298
- .args(z.object({
299
- data: z.union([z.string(), z.instanceof(Buffer)]),
300
- tags: z.array(TagSchema).optional(),
301
- target: z.string().optional(),
302
- anchor: z.string().optional(),
303
- }))
304
- .returns(z.promise(z.object({
305
- id: z.string(),
306
- raw: z.instanceof(ArrayBuffer),
307
- })));
308
- try {
309
- AoSignerSchema.parse(value);
310
- return true;
311
- }
312
- catch {
313
- return false;
314
- }
315
- }
316
- export function createAoSigner(signer) {
317
- if (isAoSigner(signer)) {
318
- return signer;
319
- }
320
- if (!('publicKey' in signer)) {
321
- return createDataItemSigner(signer);
322
- }
323
- const aoSigner = async ({ data, tags, target, anchor }) => {
324
- // ensure appropriate permissions are granted with injected signers.
325
- if (signer.publicKey === undefined &&
326
- 'setPublicKey' in signer &&
327
- typeof signer.setPublicKey === 'function') {
328
- await signer.setPublicKey();
329
- }
330
- if (signer instanceof ArconnectSigner) {
331
- // Sign using Arconnect signDataItem API
332
- const signedDataItem = await signer['signer'].signDataItem({
333
- data,
334
- tags,
335
- target,
336
- anchor,
337
- });
338
- const dataItem = new DataItem(Buffer.from(signedDataItem));
339
- return {
340
- id: await dataItem.id,
341
- raw: await dataItem.getRaw(),
342
- };
343
- }
344
- const dataItem = createData(data, signer, { tags, target, anchor });
345
- const signedData = dataItem.sign(signer).then(async () => ({
346
- id: await dataItem.id,
347
- raw: await dataItem.getRaw(),
348
- }));
349
- return signedData;
350
- };
351
- // eslint-disable-next-line
352
- // @ts-ignore Buffer vs ArrayBuffer type mismatch
353
- return aoSigner;
354
- }
355
- export const defaultTargetManifestId = '-k7t8xMoB8hW482609Z9F4bTFMC3MnuW8bTvTyT8pFI';
356
- export const defaultANTLogoId = 'Sie_26dvgyok0PZD_-iQAFOhOd5YxDTkczOLoqTTL_A';
357
- export function initANTStateForAddress({ owner, targetId, ttlSeconds = 3600, keywords = [], controllers = [], description = '', ticker = 'aos', name = 'ANT', logo = defaultANTLogoId, }) {
358
- return {
359
- ticker,
360
- name,
361
- description,
362
- keywords,
363
- owner,
364
- controllers: [owner, ...controllers],
365
- balances: { [owner]: 1 },
366
- records: {
367
- ['@']: {
368
- transactionId: targetId ?? defaultTargetManifestId.toString(),
369
- ttlSeconds,
370
- },
371
- },
372
- logo,
373
- };
374
- }
375
- /**
376
- * Uses zod schema to parse the epoch data
377
- */
378
- export function parseAoEpochData(value) {
379
- const epochDataSchema = z.object({
380
- startTimestamp: z.number(),
381
- startHeight: z.number(),
382
- distributions: z.any(), // TODO: add full distributed object type
383
- endTimestamp: z.number(),
384
- prescribedObservers: z.any(),
385
- prescribedNames: z.array(z.string()),
386
- observations: z.any(),
387
- epochIndex: z.number(),
388
- arnsStats: z.any(),
389
- });
390
- return epochDataSchema.parse(value);
391
- }
392
- export function errorMessageFromOutput(output) {
393
- const errorData = output.Error;
394
- // Attempt to extract error details from Messages.Tags if Error is undefined
395
- const error = errorData ??
396
- output.Messages?.[0]?.Tags?.find((tag) => tag.name === 'Error')?.value;
397
- if (error !== undefined) {
398
- const errorStackTrace = output.Messages?.[0]?.Data;
399
- const errorMessage = errorStackTrace ?? error;
400
- // Regex to match AO error messages like: [string ".src.main"]:5111: Primary name data not found
401
- // or [string "aos"]:128: some error
402
- const match = errorMessage?.match(/\[string "(.+)"\]:(\d+):\s*(.*)/);
403
- if (match) {
404
- // The first group is the src file, the second is the line number, and the third is the error message
405
- const [, , lineNumber, errorMessage] = match;
406
- const cleanError = removeUnicodeFromError(errorMessage);
407
- return `${cleanError.trim()} (line ${lineNumber.trim()})`.trim();
408
- }
409
- // With no match, just remove unicode
410
- return removeUnicodeFromError(error);
411
- }
412
- return undefined;
413
- }
414
- export function removeUnicodeFromError(error) {
415
- //The regular expression /[\u001b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g is designed to match ANSI escape codes used for terminal formatting. These are sequences that begin with \u001b (ESC character) and are often followed by [ and control codes.
416
- const ESC = String.fromCharCode(27); // Represents '\u001b' or '\x1b'
417
- return error
418
- .replace(new RegExp(`${ESC}[\\[\\]()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]`, 'g'), '')
419
- .trim();
420
- }