@ar.io/sdk 3.24.0 → 4.0.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 +682 -600
- package/lib/esm/cli/cli.js +188 -152
- package/lib/esm/cli/commands/antCommands.js +23 -58
- package/lib/esm/cli/commands/arnsPurchaseCommands.js +48 -30
- package/lib/esm/cli/commands/escrowCommands.js +221 -0
- package/lib/esm/cli/commands/gatewayWriteCommands.js +142 -23
- package/lib/esm/cli/commands/pruneCommands.js +150 -0
- package/lib/esm/cli/commands/readCommands.js +22 -3
- package/lib/esm/cli/commands/transfer.js +6 -6
- package/lib/esm/cli/options.js +124 -58
- package/lib/esm/cli/utils.js +280 -174
- package/lib/esm/common/ant-registry.js +17 -143
- package/lib/esm/common/ant.js +44 -1167
- package/lib/esm/common/faucet.js +11 -6
- package/lib/esm/common/index.js +0 -4
- package/lib/esm/common/io.js +25 -1412
- package/lib/esm/constants.js +13 -19
- package/lib/esm/solana/ant-readable.js +724 -0
- package/lib/esm/solana/ant-registry-readable.js +133 -0
- package/lib/esm/solana/ant-registry-writeable.js +472 -0
- package/lib/esm/solana/ant-writeable.js +384 -0
- package/lib/esm/solana/ata.js +70 -0
- package/lib/esm/solana/canonical-message.js +128 -0
- package/lib/esm/solana/clusters.js +111 -0
- package/lib/esm/solana/constants.js +146 -0
- package/lib/esm/solana/delegation-math.js +112 -0
- package/lib/esm/solana/deserialize.js +711 -0
- package/lib/esm/solana/escrow.js +839 -0
- package/lib/{cjs/utils/json.js → esm/solana/events.js} +15 -10
- package/lib/esm/solana/funding-plan.js +699 -0
- package/lib/esm/solana/index.js +126 -0
- package/lib/esm/solana/instruction.js +39 -0
- package/lib/esm/solana/io-readable.js +2182 -0
- package/lib/esm/solana/io-writeable.js +3196 -0
- package/lib/esm/solana/json-rpc.js +90 -0
- package/lib/esm/solana/metadata.js +81 -0
- package/lib/esm/solana/mpl-core.js +192 -0
- package/lib/esm/solana/pda.js +332 -0
- package/lib/esm/solana/predict-prescribed-observers.js +110 -0
- package/lib/esm/solana/retry.js +117 -0
- package/lib/esm/solana/rpc-circuit-breaker.js +258 -0
- package/lib/esm/solana/send.js +372 -0
- package/lib/esm/solana/spawn-ant.js +224 -0
- package/lib/esm/solana/types.js +1 -0
- package/lib/esm/types/ant.js +27 -15
- package/lib/esm/types/io.js +8 -11
- package/lib/esm/utils/ant.js +0 -63
- package/lib/esm/utils/index.js +0 -3
- package/lib/esm/version.js +1 -1
- package/lib/types/cli/commands/antCommands.d.ts +5 -13
- package/lib/types/cli/commands/arnsPurchaseCommands.d.ts +33 -7
- package/lib/types/cli/commands/escrowCommands.d.ts +68 -0
- package/lib/types/cli/commands/gatewayWriteCommands.d.ts +12 -11
- package/lib/types/cli/commands/pruneCommands.d.ts +31 -0
- package/lib/types/cli/commands/readCommands.d.ts +27 -22
- package/lib/types/cli/commands/transfer.d.ts +9 -9
- package/lib/types/cli/options.d.ts +76 -21
- package/lib/types/cli/types.d.ts +11 -13
- package/lib/types/cli/utils.d.ts +71 -31
- package/lib/types/common/ant-registry.d.ts +49 -47
- package/lib/types/common/ant.d.ts +54 -539
- package/lib/types/common/faucet.d.ts +20 -8
- package/lib/types/common/index.d.ts +0 -3
- package/lib/types/common/io.d.ts +51 -263
- package/lib/types/constants.d.ts +11 -18
- package/lib/types/solana/ant-readable.d.ts +180 -0
- package/lib/types/solana/ant-registry-readable.d.ts +105 -0
- package/lib/types/solana/ant-registry-writeable.d.ts +249 -0
- package/lib/types/solana/ant-writeable.d.ts +177 -0
- package/lib/types/solana/ata.d.ts +44 -0
- package/lib/types/solana/canonical-message.d.ts +121 -0
- package/lib/types/solana/clusters.d.ts +109 -0
- package/lib/types/solana/constants.d.ts +119 -0
- package/lib/types/solana/delegation-math.d.ts +45 -0
- package/lib/types/solana/deserialize.d.ts +262 -0
- package/lib/types/solana/escrow.d.ts +480 -0
- package/lib/types/solana/events.d.ts +38 -0
- package/lib/types/solana/funding-plan.d.ts +225 -0
- package/lib/types/solana/index.d.ts +87 -0
- package/lib/types/solana/instruction.d.ts +39 -0
- package/lib/types/solana/io-readable.d.ts +499 -0
- package/lib/types/solana/io-writeable.d.ts +893 -0
- package/lib/types/solana/json-rpc.d.ts +47 -0
- package/lib/types/solana/metadata.d.ts +84 -0
- package/lib/types/solana/mpl-core.d.ts +120 -0
- package/lib/types/solana/pda.d.ts +95 -0
- package/lib/types/solana/predict-prescribed-observers.d.ts +28 -0
- package/lib/types/solana/retry.d.ts +62 -0
- package/lib/types/solana/rpc-circuit-breaker.d.ts +78 -0
- package/lib/types/solana/send.d.ts +94 -0
- package/lib/types/solana/spawn-ant.d.ts +145 -0
- package/lib/types/solana/types.d.ts +82 -0
- package/lib/types/types/ant-registry.d.ts +43 -4
- package/lib/types/types/ant.d.ts +114 -96
- package/lib/types/types/common.d.ts +18 -74
- package/lib/types/types/faucet.d.ts +2 -2
- package/lib/types/types/io.d.ts +244 -158
- package/lib/types/types/token.d.ts +0 -12
- package/lib/types/utils/ant.d.ts +1 -12
- package/lib/types/utils/index.d.ts +0 -3
- package/lib/types/version.d.ts +1 -1
- package/package.json +36 -33
- package/lib/cjs/cli/cli.js +0 -822
- package/lib/cjs/cli/commands/antCommands.js +0 -113
- package/lib/cjs/cli/commands/arnsPurchaseCommands.js +0 -212
- package/lib/cjs/cli/commands/gatewayWriteCommands.js +0 -210
- package/lib/cjs/cli/commands/readCommands.js +0 -215
- package/lib/cjs/cli/commands/transfer.js +0 -159
- package/lib/cjs/cli/options.js +0 -470
- package/lib/cjs/cli/types.js +0 -2
- package/lib/cjs/cli/utils.js +0 -639
- package/lib/cjs/common/ant-registry.js +0 -155
- package/lib/cjs/common/ant-versions.js +0 -93
- package/lib/cjs/common/ant.js +0 -1182
- package/lib/cjs/common/arweave.js +0 -27
- package/lib/cjs/common/contracts/ao-process.js +0 -224
- package/lib/cjs/common/error.js +0 -64
- package/lib/cjs/common/faucet.js +0 -150
- package/lib/cjs/common/hyperbeam/hb.js +0 -173
- package/lib/cjs/common/index.js +0 -42
- package/lib/cjs/common/io.js +0 -1423
- package/lib/cjs/common/logger.js +0 -83
- package/lib/cjs/common/loggers/winston.js +0 -68
- package/lib/cjs/common/marketplace.js +0 -731
- package/lib/cjs/common/turbo.js +0 -223
- package/lib/cjs/constants.js +0 -41
- package/lib/cjs/node/index.js +0 -39
- package/lib/cjs/package.json +0 -1
- package/lib/cjs/types/ant-registry.js +0 -2
- package/lib/cjs/types/ant.js +0 -168
- package/lib/cjs/types/common.js +0 -2
- package/lib/cjs/types/faucet.js +0 -2
- package/lib/cjs/types/index.js +0 -37
- package/lib/cjs/types/io.js +0 -51
- package/lib/cjs/types/token.js +0 -116
- package/lib/cjs/utils/ant.js +0 -108
- package/lib/cjs/utils/ao.js +0 -432
- package/lib/cjs/utils/arweave.js +0 -285
- package/lib/cjs/utils/base64.js +0 -62
- package/lib/cjs/utils/hash.js +0 -56
- package/lib/cjs/utils/index.js +0 -38
- package/lib/cjs/utils/processes.js +0 -173
- package/lib/cjs/utils/random.js +0 -30
- package/lib/cjs/utils/schema.js +0 -15
- package/lib/cjs/utils/url.js +0 -37
- package/lib/cjs/version.js +0 -20
- package/lib/cjs/web/index.js +0 -41
- package/lib/esm/common/ant-versions.js +0 -87
- package/lib/esm/common/arweave.js +0 -21
- package/lib/esm/common/contracts/ao-process.js +0 -220
- package/lib/esm/common/hyperbeam/hb.js +0 -169
- package/lib/esm/common/marketplace.js +0 -724
- package/lib/esm/common/turbo.js +0 -215
- package/lib/esm/node/index.js +0 -20
- package/lib/esm/utils/ao.js +0 -420
- package/lib/esm/utils/arweave.js +0 -271
- package/lib/esm/utils/processes.js +0 -167
- package/lib/esm/web/index.js +0 -20
- package/lib/types/common/ant-versions.d.ts +0 -39
- package/lib/types/common/arweave.d.ts +0 -17
- package/lib/types/common/contracts/ao-process.d.ts +0 -47
- package/lib/types/common/hyperbeam/hb.d.ts +0 -88
- package/lib/types/common/marketplace.d.ts +0 -568
- package/lib/types/common/turbo.d.ts +0 -61
- package/lib/types/node/index.d.ts +0 -20
- package/lib/types/utils/ao.d.ts +0 -80
- package/lib/types/utils/arweave.d.ts +0 -79
- package/lib/types/utils/processes.d.ts +0 -39
- package/lib/types/web/index.d.ts +0 -20
package/lib/cjs/types/token.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.mARIOToken = exports.ARIOToken = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
6
|
-
*
|
|
7
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
-
* you may not use this file except in compliance with the License.
|
|
9
|
-
* You may obtain a copy of the License at
|
|
10
|
-
*
|
|
11
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
-
*
|
|
13
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
-
* See the License for the specific language governing permissions and
|
|
17
|
-
* limitations under the License.
|
|
18
|
-
*/
|
|
19
|
-
const constants_js_1 = require("../constants.js");
|
|
20
|
-
class PositiveFiniteInteger {
|
|
21
|
-
positiveFiniteInteger;
|
|
22
|
-
constructor(positiveFiniteInteger) {
|
|
23
|
-
this.positiveFiniteInteger = positiveFiniteInteger;
|
|
24
|
-
if (!Number.isFinite(this.positiveFiniteInteger) ||
|
|
25
|
-
!Number.isInteger(this.positiveFiniteInteger) ||
|
|
26
|
-
this.positiveFiniteInteger < 0) {
|
|
27
|
-
throw new Error(`Number must be a non-negative integer value! ${positiveFiniteInteger}`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
[Symbol.toPrimitive](hint) {
|
|
31
|
-
if (hint === 'string') {
|
|
32
|
-
this.toString();
|
|
33
|
-
}
|
|
34
|
-
return this.positiveFiniteInteger;
|
|
35
|
-
}
|
|
36
|
-
plus(positiveFiniteInteger) {
|
|
37
|
-
return new PositiveFiniteInteger(this.positiveFiniteInteger + positiveFiniteInteger.positiveFiniteInteger);
|
|
38
|
-
}
|
|
39
|
-
minus(positiveFiniteInteger) {
|
|
40
|
-
return new PositiveFiniteInteger(this.positiveFiniteInteger - positiveFiniteInteger.positiveFiniteInteger);
|
|
41
|
-
}
|
|
42
|
-
isGreaterThan(positiveFiniteInteger) {
|
|
43
|
-
return (this.positiveFiniteInteger > positiveFiniteInteger.positiveFiniteInteger);
|
|
44
|
-
}
|
|
45
|
-
isGreaterThanOrEqualTo(positiveFiniteInteger) {
|
|
46
|
-
return (this.positiveFiniteInteger >= positiveFiniteInteger.positiveFiniteInteger);
|
|
47
|
-
}
|
|
48
|
-
isLessThan(positiveFiniteInteger) {
|
|
49
|
-
return (this.positiveFiniteInteger < positiveFiniteInteger.positiveFiniteInteger);
|
|
50
|
-
}
|
|
51
|
-
isLessThanOrEqualTo(positiveFiniteInteger) {
|
|
52
|
-
return (this.positiveFiniteInteger <= positiveFiniteInteger.positiveFiniteInteger);
|
|
53
|
-
}
|
|
54
|
-
toString() {
|
|
55
|
-
return `${this.positiveFiniteInteger}`;
|
|
56
|
-
}
|
|
57
|
-
valueOf() {
|
|
58
|
-
return this.positiveFiniteInteger;
|
|
59
|
-
}
|
|
60
|
-
toJSON() {
|
|
61
|
-
return this.positiveFiniteInteger;
|
|
62
|
-
}
|
|
63
|
-
equals(other) {
|
|
64
|
-
return this.positiveFiniteInteger === other.positiveFiniteInteger;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
class ARIOToken {
|
|
68
|
-
value;
|
|
69
|
-
constructor(value) {
|
|
70
|
-
if (!Number.isFinite(value) || value < 0) {
|
|
71
|
-
throw new Error('ARIOToken must be a non-negative finite number');
|
|
72
|
-
}
|
|
73
|
-
this.value = +value.toFixed(6);
|
|
74
|
-
}
|
|
75
|
-
valueOf() {
|
|
76
|
-
return this.value;
|
|
77
|
-
}
|
|
78
|
-
toMARIO() {
|
|
79
|
-
return new mARIOToken(Math.floor(this.value * constants_js_1.MARIO_PER_ARIO));
|
|
80
|
-
}
|
|
81
|
-
toString() {
|
|
82
|
-
return `${this.value}`;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
exports.ARIOToken = ARIOToken;
|
|
86
|
-
class mARIOToken extends PositiveFiniteInteger {
|
|
87
|
-
constructor(value) {
|
|
88
|
-
super(value);
|
|
89
|
-
}
|
|
90
|
-
multiply(multiplier) {
|
|
91
|
-
// always round down on multiplication and division
|
|
92
|
-
const result = Math.floor(this.valueOf() * multiplier.valueOf());
|
|
93
|
-
return new mARIOToken(result);
|
|
94
|
-
}
|
|
95
|
-
divide(divisor) {
|
|
96
|
-
if (divisor.valueOf() === 0) {
|
|
97
|
-
// TODO: how should we handle this
|
|
98
|
-
throw new Error('Cannot divide by zero');
|
|
99
|
-
}
|
|
100
|
-
// always round down on multiplication and division
|
|
101
|
-
const result = Math.floor(this.valueOf() / divisor.valueOf());
|
|
102
|
-
return new mARIOToken(result);
|
|
103
|
-
}
|
|
104
|
-
plus(addend) {
|
|
105
|
-
const result = super.plus(addend);
|
|
106
|
-
return new mARIOToken(result.valueOf());
|
|
107
|
-
}
|
|
108
|
-
minus(subtractHend) {
|
|
109
|
-
const result = super.minus(subtractHend);
|
|
110
|
-
return new mARIOToken(result.valueOf());
|
|
111
|
-
}
|
|
112
|
-
toARIO() {
|
|
113
|
-
return new ARIOToken(this.valueOf() / constants_js_1.MARIO_PER_ARIO);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
exports.mARIOToken = mARIOToken;
|
package/lib/cjs/utils/ant.js
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.convertHyperBeamStateToAoANTState = exports.isHyperBeamANTState = exports.sortANTRecords = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Sorts ANT records by priority and then lexicographically.
|
|
6
|
-
*
|
|
7
|
-
* Note: javascript guarantees that the order of objects in an object is persistent. Still, adding index to each record is useful for enforcing against undername limits.
|
|
8
|
-
*
|
|
9
|
-
* Reference: https://github.com/ar-io/ar-io-node/blob/e0a9ec56559cad1b3e35d668563871afb8649913/docs/madr/003-arns-undername-limits.md
|
|
10
|
-
*
|
|
11
|
-
* @param antRecords - The ANT records to sort.
|
|
12
|
-
*/
|
|
13
|
-
const sortANTRecords = (antRecords) => {
|
|
14
|
-
const sortedEntries = Object.entries(antRecords).sort(([a, aRecord], [b, bRecord]) => {
|
|
15
|
-
// '@' is the root name and should be resolved first
|
|
16
|
-
if (a === '@') {
|
|
17
|
-
return -1;
|
|
18
|
-
}
|
|
19
|
-
if (b === '@') {
|
|
20
|
-
return 1;
|
|
21
|
-
}
|
|
22
|
-
// if a record has a priority, it should be resolved before any other record without a priority
|
|
23
|
-
if ('priority' in aRecord && !('priority' in bRecord)) {
|
|
24
|
-
return -1;
|
|
25
|
-
}
|
|
26
|
-
if (!('priority' in aRecord) && 'priority' in bRecord) {
|
|
27
|
-
return 1;
|
|
28
|
-
}
|
|
29
|
-
// if both records have a priority, sort by priority and fallback to lexicographic sorting
|
|
30
|
-
if (aRecord.priority !== undefined && bRecord.priority !== undefined) {
|
|
31
|
-
if (aRecord.priority === bRecord.priority) {
|
|
32
|
-
// use deterministic comparison instead of localeCompare to avoid locale-specific sorting
|
|
33
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
34
|
-
}
|
|
35
|
-
return aRecord.priority - bRecord.priority;
|
|
36
|
-
}
|
|
37
|
-
// all other records are sorted lexicographically, using deterministic comparison instead of localeCompare to avoid locale-specific sorting
|
|
38
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
39
|
-
});
|
|
40
|
-
// 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
|
|
41
|
-
return Object.fromEntries(sortedEntries.map(([a, aRecord], index) => [a, { ...aRecord, index }]));
|
|
42
|
-
};
|
|
43
|
-
exports.sortANTRecords = sortANTRecords;
|
|
44
|
-
/**
|
|
45
|
-
* @deprecated - this is no longer necessary because HyperBeam now uses the AoANTState type
|
|
46
|
-
*/
|
|
47
|
-
const isHyperBeamANTState = (state) => {
|
|
48
|
-
return ('name' in state &&
|
|
49
|
-
'ticker' in state &&
|
|
50
|
-
'description' in state &&
|
|
51
|
-
'keywords' in state &&
|
|
52
|
-
'denomination' in state &&
|
|
53
|
-
'owner' in state &&
|
|
54
|
-
'controllers' in state &&
|
|
55
|
-
'records' in state &&
|
|
56
|
-
'balances' in state &&
|
|
57
|
-
'logo' in state &&
|
|
58
|
-
'totalsupply' in state &&
|
|
59
|
-
'initialized' in state);
|
|
60
|
-
};
|
|
61
|
-
exports.isHyperBeamANTState = isHyperBeamANTState;
|
|
62
|
-
/**
|
|
63
|
-
* Convert HyperBeam serialized ANT state to backwards compatible format.
|
|
64
|
-
*
|
|
65
|
-
* @deprecated - this is no longer necessary because HyperBeam now uses the AOANTState type
|
|
66
|
-
* @param state - The HyperBeam serialized ANT state.
|
|
67
|
-
*/
|
|
68
|
-
const convertHyperBeamStateToAoANTState = (initialState) => {
|
|
69
|
-
function lowerCaseKeys(obj) {
|
|
70
|
-
return Object.fromEntries(Object.entries(obj).map(([key, value]) => {
|
|
71
|
-
if (key.toLowerCase().includes('balances')) {
|
|
72
|
-
return [key.toLowerCase(), value];
|
|
73
|
-
}
|
|
74
|
-
if (typeof value === 'object' &&
|
|
75
|
-
!Array.isArray(value) &&
|
|
76
|
-
value !== null) {
|
|
77
|
-
return [key.toLowerCase(), lowerCaseKeys(value)];
|
|
78
|
-
}
|
|
79
|
-
return [key.toLowerCase(), value];
|
|
80
|
-
}));
|
|
81
|
-
}
|
|
82
|
-
// we need to ensure keys are lower cased because hyperbeam json serializes keys to lowercase inconsistently
|
|
83
|
-
const state = lowerCaseKeys(initialState);
|
|
84
|
-
return {
|
|
85
|
-
Name: state.name,
|
|
86
|
-
Ticker: state.ticker,
|
|
87
|
-
Description: state.description,
|
|
88
|
-
Keywords: state.keywords,
|
|
89
|
-
Denomination: parseInt(state.denomination),
|
|
90
|
-
Owner: state.owner,
|
|
91
|
-
Controllers: state.controllers,
|
|
92
|
-
Records: Object.entries(state.records).reduce((acc, [key, record]) => {
|
|
93
|
-
acc[key] = {
|
|
94
|
-
transactionId: record.transactionid,
|
|
95
|
-
ttlSeconds: record.ttlseconds,
|
|
96
|
-
...(record.priority !== undefined
|
|
97
|
-
? { priority: record.priority }
|
|
98
|
-
: {}),
|
|
99
|
-
};
|
|
100
|
-
return acc;
|
|
101
|
-
}, {}),
|
|
102
|
-
Balances: state.balances,
|
|
103
|
-
Logo: state.logo,
|
|
104
|
-
TotalSupply: state.totalsupply || 1,
|
|
105
|
-
Initialized: state.initialized,
|
|
106
|
-
};
|
|
107
|
-
};
|
|
108
|
-
exports.convertHyperBeamStateToAoANTState = convertHyperBeamStateToAoANTState;
|
package/lib/cjs/utils/ao.js
DELETED
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.defaultANTLogoId = exports.defaultTargetManifestId = void 0;
|
|
4
|
-
exports.spawnANT = spawnANT;
|
|
5
|
-
exports.forkANT = forkANT;
|
|
6
|
-
exports.evolveANT = evolveANT;
|
|
7
|
-
exports.isAoSigner = isAoSigner;
|
|
8
|
-
exports.createAoSigner = createAoSigner;
|
|
9
|
-
exports.initANTStateForAddress = initANTStateForAddress;
|
|
10
|
-
exports.parseAoEpochData = parseAoEpochData;
|
|
11
|
-
exports.errorMessageFromOutput = errorMessageFromOutput;
|
|
12
|
-
exports.removeUnicodeFromError = removeUnicodeFromError;
|
|
13
|
-
/**
|
|
14
|
-
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
|
15
|
-
*
|
|
16
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
17
|
-
* you may not use this file except in compliance with the License.
|
|
18
|
-
* You may obtain a copy of the License at
|
|
19
|
-
*
|
|
20
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
21
|
-
*
|
|
22
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
23
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
24
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
25
|
-
* See the License for the specific language governing permissions and
|
|
26
|
-
* limitations under the License.
|
|
27
|
-
*/
|
|
28
|
-
const arbundles_1 = require("@dha-team/arbundles");
|
|
29
|
-
const aoconnect_1 = require("@permaweb/aoconnect");
|
|
30
|
-
const zod_1 = require("zod");
|
|
31
|
-
const ant_registry_js_1 = require("../common/ant-registry.js");
|
|
32
|
-
const ant_versions_js_1 = require("../common/ant-versions.js");
|
|
33
|
-
const arweave_js_1 = require("../common/arweave.js");
|
|
34
|
-
const index_js_1 = require("../common/index.js");
|
|
35
|
-
const constants_js_1 = require("../constants.js");
|
|
36
|
-
const ant_js_1 = require("../types/ant.js");
|
|
37
|
-
const schema_js_1 = require("./schema.js");
|
|
38
|
-
async function spawnANT({ signer, module, ao = (0, aoconnect_1.connect)({
|
|
39
|
-
MODE: 'legacy',
|
|
40
|
-
}), scheduler = constants_js_1.DEFAULT_SCHEDULER_ID, state, tags = [], antRegistryId = constants_js_1.ANT_REGISTRY_ID, logger = index_js_1.Logger.default, authority = constants_js_1.AO_AUTHORITY, onSigningProgress = (name, payload) => {
|
|
41
|
-
logger.debug('Signing progress', { name, payload });
|
|
42
|
-
}, hyperbeamUrl, }) {
|
|
43
|
-
if (state) {
|
|
44
|
-
(0, schema_js_1.parseSchemaResult)(ant_js_1.SpawnANTStateSchema, state);
|
|
45
|
-
}
|
|
46
|
-
let version;
|
|
47
|
-
if (module === undefined) {
|
|
48
|
-
const antRegistry = ant_versions_js_1.ANTVersions.init({
|
|
49
|
-
process: new index_js_1.AOProcess({
|
|
50
|
-
processId: antRegistryId,
|
|
51
|
-
ao,
|
|
52
|
-
logger,
|
|
53
|
-
}),
|
|
54
|
-
});
|
|
55
|
-
const { moduleId: latestAntModule, version: latestVersion } = await antRegistry.getLatestANTVersion();
|
|
56
|
-
logger.debug('Spawning new ANT with latest module from ANT registry', {
|
|
57
|
-
moduleId: latestAntModule,
|
|
58
|
-
version: latestVersion,
|
|
59
|
-
antRegistryId,
|
|
60
|
-
});
|
|
61
|
-
module = latestAntModule;
|
|
62
|
-
version = latestVersion;
|
|
63
|
-
}
|
|
64
|
-
onSigningProgress?.('spawning-ant', {
|
|
65
|
-
moduleId: module,
|
|
66
|
-
antRegistryId,
|
|
67
|
-
version,
|
|
68
|
-
state,
|
|
69
|
-
});
|
|
70
|
-
const processId = await ao.spawn({
|
|
71
|
-
module,
|
|
72
|
-
scheduler,
|
|
73
|
-
signer,
|
|
74
|
-
data: state ? JSON.stringify(state) : undefined,
|
|
75
|
-
tags: [
|
|
76
|
-
// Required for AOS to initialize the authorities table
|
|
77
|
-
{
|
|
78
|
-
name: 'Authority',
|
|
79
|
-
value: authority,
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
name: 'ANT-Registry-Id',
|
|
83
|
-
value: antRegistryId,
|
|
84
|
-
},
|
|
85
|
-
...tags,
|
|
86
|
-
],
|
|
87
|
-
});
|
|
88
|
-
/**
|
|
89
|
-
* Note: if we are given a state, ensure the ANT was initialized with it
|
|
90
|
-
* there is a bug in the ANT source where we try to parse the empty default
|
|
91
|
-
* 'Data' string as JSON that causes the Invalid-Boot-Notice error, even though
|
|
92
|
-
* the ANT was initialized with the default state set by the ANT source code.
|
|
93
|
-
*
|
|
94
|
-
* Reference: https://github.com/ar-io/ar-io-ant-process/blob/b89018ffcce079add2e90e7ab82d0bbc9b671346/src/common/main.lua#L355-L358
|
|
95
|
-
*/
|
|
96
|
-
if (state !== undefined) {
|
|
97
|
-
let bootRes;
|
|
98
|
-
let attempts = 0;
|
|
99
|
-
while (attempts < 5 && bootRes === undefined) {
|
|
100
|
-
try {
|
|
101
|
-
// TODO: could add a progress event here to show the boot progress and number of attempts
|
|
102
|
-
if (bootRes === undefined) {
|
|
103
|
-
bootRes = await ao.result({
|
|
104
|
-
process: processId,
|
|
105
|
-
message: processId,
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
logger.debug('Retrying ANT boot result fetch', {
|
|
112
|
-
processId,
|
|
113
|
-
module,
|
|
114
|
-
scheduler,
|
|
115
|
-
attempts,
|
|
116
|
-
error,
|
|
117
|
-
});
|
|
118
|
-
attempts++;
|
|
119
|
-
await new Promise((resolve) => setTimeout(resolve, 1000 * attempts ** 2));
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
if (bootRes === undefined ||
|
|
123
|
-
bootRes.Messages?.some((m) => m?.Tags?.some((t) => t.value === 'Invalid-Boot-Notice'))) {
|
|
124
|
-
if (bootRes === undefined) {
|
|
125
|
-
throw new Error('Failed to get boot result');
|
|
126
|
-
}
|
|
127
|
-
const bootError = errorMessageFromOutput(bootRes);
|
|
128
|
-
logger.error('ANT failed to boot correctly', {
|
|
129
|
-
processId,
|
|
130
|
-
module,
|
|
131
|
-
scheduler,
|
|
132
|
-
bootRes,
|
|
133
|
-
bootError,
|
|
134
|
-
});
|
|
135
|
-
throw new Error(`ANT failed to boot correctly: ${bootError}`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
onSigningProgress?.('verifying-state', {
|
|
139
|
-
processId,
|
|
140
|
-
moduleId: module,
|
|
141
|
-
antRegistryId,
|
|
142
|
-
});
|
|
143
|
-
// Note: for hyperbeam caching, due to a SU issue, we need to send a second message to the ANT to cache the state
|
|
144
|
-
// We wait for the first message to be processed before sending the second one to ensure this is the second message
|
|
145
|
-
// We use the resulting state to check the owner of the ANT is set in the registry. Should this be patched on MUs,
|
|
146
|
-
// we can convert to just a simple dry-run to avoid sending/signing another message.
|
|
147
|
-
let owner;
|
|
148
|
-
try {
|
|
149
|
-
const processApi = new index_js_1.AOProcess({
|
|
150
|
-
processId,
|
|
151
|
-
ao,
|
|
152
|
-
logger,
|
|
153
|
-
});
|
|
154
|
-
const { id } = await processApi.send({
|
|
155
|
-
tags: [{ name: 'Action', value: 'State' }],
|
|
156
|
-
signer,
|
|
157
|
-
});
|
|
158
|
-
const stateResult = await ao.result({
|
|
159
|
-
process: processId,
|
|
160
|
-
message: id,
|
|
161
|
-
});
|
|
162
|
-
if (stateResult === undefined) {
|
|
163
|
-
throw new Error('Failed to get state result');
|
|
164
|
-
}
|
|
165
|
-
const { Owner } = JSON.parse(stateResult.Messages?.[0]?.Data ?? '{}');
|
|
166
|
-
owner = Owner;
|
|
167
|
-
logger.debug(`Successfully spawned new ANT and validated owner`, {
|
|
168
|
-
processId,
|
|
169
|
-
module,
|
|
170
|
-
owner,
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
catch (error) {
|
|
174
|
-
logger.error('Failed to validate owner of spawned ANT', {
|
|
175
|
-
processId,
|
|
176
|
-
module,
|
|
177
|
-
error,
|
|
178
|
-
});
|
|
179
|
-
throw error;
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Now confirm the owner of the ANT is set in the registry
|
|
183
|
-
* This is to ensure the ANT is available via the ANT registry
|
|
184
|
-
* for the owner to find and use the ANT.
|
|
185
|
-
*/
|
|
186
|
-
if (owner === undefined) {
|
|
187
|
-
throw new Error(`Spawning ANT (${processId}) failed to set owner`);
|
|
188
|
-
}
|
|
189
|
-
onSigningProgress?.('registering-ant', {
|
|
190
|
-
processId,
|
|
191
|
-
antRegistryId,
|
|
192
|
-
owner,
|
|
193
|
-
});
|
|
194
|
-
// check the ACL for the owner
|
|
195
|
-
const antRegistry = ant_registry_js_1.ANTRegistry.init({
|
|
196
|
-
signer,
|
|
197
|
-
process: new index_js_1.AOProcess({
|
|
198
|
-
processId: antRegistryId,
|
|
199
|
-
ao,
|
|
200
|
-
logger,
|
|
201
|
-
}),
|
|
202
|
-
hyperbeamUrl,
|
|
203
|
-
});
|
|
204
|
-
let attempts = 0;
|
|
205
|
-
const maxAttempts = 5;
|
|
206
|
-
while (attempts < maxAttempts) {
|
|
207
|
-
try {
|
|
208
|
-
const acl = await antRegistry.accessControlList({ address: owner });
|
|
209
|
-
if (acl === undefined) {
|
|
210
|
-
throw new Error('ACL not found for owner');
|
|
211
|
-
}
|
|
212
|
-
const { Owned } = acl;
|
|
213
|
-
if (!Owned.includes(processId)) {
|
|
214
|
-
throw new Error(`Spawned ANT (${processId}) not found in registry for owner ${owner}`);
|
|
215
|
-
}
|
|
216
|
-
return processId;
|
|
217
|
-
}
|
|
218
|
-
catch (error) {
|
|
219
|
-
logger.debug('Retrying ANT registry access control list fetch', {
|
|
220
|
-
owner,
|
|
221
|
-
antRegistryId,
|
|
222
|
-
attempts,
|
|
223
|
-
error,
|
|
224
|
-
});
|
|
225
|
-
attempts++;
|
|
226
|
-
await new Promise((resolve) => setTimeout(resolve, 1000 * attempts ** 2));
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return processId;
|
|
230
|
-
}
|
|
231
|
-
async function forkANT({ signer, antProcessId, logger = index_js_1.Logger.default, ao, moduleId, antRegistryId = constants_js_1.ANT_REGISTRY_ID, onSigningProgress = (name, payload) => {
|
|
232
|
-
logger.debug('Forking ANT', { name, payload });
|
|
233
|
-
}, hyperbeamUrl, }) {
|
|
234
|
-
// get the state of the current ANT and use it to spawn a new ANT
|
|
235
|
-
const ant = index_js_1.ANT.init({
|
|
236
|
-
process: new index_js_1.AOProcess({
|
|
237
|
-
processId: antProcessId,
|
|
238
|
-
ao,
|
|
239
|
-
logger,
|
|
240
|
-
}),
|
|
241
|
-
hyperbeamUrl,
|
|
242
|
-
});
|
|
243
|
-
const state = await ant.getState();
|
|
244
|
-
if (state === undefined) {
|
|
245
|
-
throw new Error(`ANT state (${antProcessId}) is undefined and cannot be upgraded`);
|
|
246
|
-
}
|
|
247
|
-
const forkedProcessId = await spawnANT({
|
|
248
|
-
signer,
|
|
249
|
-
antRegistryId,
|
|
250
|
-
ao,
|
|
251
|
-
logger,
|
|
252
|
-
module: moduleId,
|
|
253
|
-
onSigningProgress,
|
|
254
|
-
state: {
|
|
255
|
-
owner: state.Owner,
|
|
256
|
-
name: state.Name,
|
|
257
|
-
ticker: state.Ticker,
|
|
258
|
-
description: state.Description,
|
|
259
|
-
keywords: state.Keywords,
|
|
260
|
-
controllers: state.Controllers,
|
|
261
|
-
records: state.Records,
|
|
262
|
-
balances: state.Balances,
|
|
263
|
-
logo: state.Logo,
|
|
264
|
-
},
|
|
265
|
-
hyperbeamUrl,
|
|
266
|
-
});
|
|
267
|
-
return forkedProcessId;
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* @deprecated
|
|
271
|
-
* Direct Evals are not encouraged when dealing with ANTs.
|
|
272
|
-
* Instead, use spawnANT to fork an ANT to new module source code
|
|
273
|
-
*/
|
|
274
|
-
async function evolveANT({ signer, processId, luaCodeTxId = constants_js_1.ANT_LUA_ID, ao = (0, aoconnect_1.connect)({
|
|
275
|
-
MODE: 'legacy',
|
|
276
|
-
}), logger = index_js_1.Logger.default, arweave = arweave_js_1.defaultArweave, }) {
|
|
277
|
-
const aosClient = new index_js_1.AOProcess({
|
|
278
|
-
processId,
|
|
279
|
-
ao,
|
|
280
|
-
logger,
|
|
281
|
-
});
|
|
282
|
-
logger.warn('Directly running an Eval on a process is not encouraged.');
|
|
283
|
-
//TODO: cache locally and only fetch if not cached
|
|
284
|
-
// We do not use arweave to get the data because it may throw on l2 tx data
|
|
285
|
-
const { api: { host, port, protocol }, } = arweave.getConfig();
|
|
286
|
-
const luaString = await fetch(`${protocol}://${host}:${port}/${luaCodeTxId}`).then((res) => res.text());
|
|
287
|
-
const { id: evolveMsgId } = await aosClient.send({
|
|
288
|
-
tags: [
|
|
289
|
-
{ name: 'Action', value: 'Eval' },
|
|
290
|
-
{ name: 'App-Name', value: 'ArNS-ANT' },
|
|
291
|
-
{ name: 'Source-Code-TX-ID', value: luaCodeTxId },
|
|
292
|
-
],
|
|
293
|
-
data: luaString,
|
|
294
|
-
signer,
|
|
295
|
-
});
|
|
296
|
-
logger.debug(`Evolved ANT`, {
|
|
297
|
-
processId,
|
|
298
|
-
luaCodeTxId,
|
|
299
|
-
evalMsgId: evolveMsgId,
|
|
300
|
-
});
|
|
301
|
-
return evolveMsgId;
|
|
302
|
-
}
|
|
303
|
-
function isAoSigner(value) {
|
|
304
|
-
const TagSchema = zod_1.z.object({
|
|
305
|
-
name: zod_1.z.string(),
|
|
306
|
-
value: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]),
|
|
307
|
-
});
|
|
308
|
-
const AoSignerSchema = zod_1.z
|
|
309
|
-
.function()
|
|
310
|
-
.args(zod_1.z.object({
|
|
311
|
-
data: zod_1.z.union([zod_1.z.string(), zod_1.z.instanceof(Buffer)]),
|
|
312
|
-
tags: zod_1.z.array(TagSchema).optional(),
|
|
313
|
-
target: zod_1.z.string().optional(),
|
|
314
|
-
anchor: zod_1.z.string().optional(),
|
|
315
|
-
}))
|
|
316
|
-
.returns(zod_1.z.promise(zod_1.z.object({
|
|
317
|
-
id: zod_1.z.string(),
|
|
318
|
-
raw: zod_1.z.instanceof(ArrayBuffer),
|
|
319
|
-
})));
|
|
320
|
-
try {
|
|
321
|
-
AoSignerSchema.parse(value);
|
|
322
|
-
return true;
|
|
323
|
-
}
|
|
324
|
-
catch {
|
|
325
|
-
return false;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
function createAoSigner(signer) {
|
|
329
|
-
if (isAoSigner(signer)) {
|
|
330
|
-
return signer;
|
|
331
|
-
}
|
|
332
|
-
if (!('publicKey' in signer)) {
|
|
333
|
-
return (0, aoconnect_1.createDataItemSigner)(signer);
|
|
334
|
-
}
|
|
335
|
-
const aoSigner = async ({ data, tags, target, anchor }) => {
|
|
336
|
-
// ensure appropriate permissions are granted with injected signers.
|
|
337
|
-
if (signer.publicKey === undefined &&
|
|
338
|
-
'setPublicKey' in signer &&
|
|
339
|
-
typeof signer.setPublicKey === 'function') {
|
|
340
|
-
await signer.setPublicKey();
|
|
341
|
-
}
|
|
342
|
-
if (signer instanceof arbundles_1.ArconnectSigner) {
|
|
343
|
-
// Sign using Arconnect signDataItem API
|
|
344
|
-
const signedDataItem = await signer['signer'].signDataItem({
|
|
345
|
-
data,
|
|
346
|
-
tags,
|
|
347
|
-
target,
|
|
348
|
-
anchor,
|
|
349
|
-
});
|
|
350
|
-
const dataItem = new arbundles_1.DataItem(Buffer.from(signedDataItem));
|
|
351
|
-
return {
|
|
352
|
-
id: await dataItem.id,
|
|
353
|
-
raw: await dataItem.getRaw(),
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
const dataItem = (0, arbundles_1.createData)(data, signer, { tags, target, anchor });
|
|
357
|
-
const signedData = dataItem.sign(signer).then(async () => ({
|
|
358
|
-
id: await dataItem.id,
|
|
359
|
-
raw: await dataItem.getRaw(),
|
|
360
|
-
}));
|
|
361
|
-
return signedData;
|
|
362
|
-
};
|
|
363
|
-
// eslint-disable-next-line
|
|
364
|
-
// @ts-ignore Buffer vs ArrayBuffer type mismatch
|
|
365
|
-
return aoSigner;
|
|
366
|
-
}
|
|
367
|
-
exports.defaultTargetManifestId = '-k7t8xMoB8hW482609Z9F4bTFMC3MnuW8bTvTyT8pFI';
|
|
368
|
-
exports.defaultANTLogoId = 'Sie_26dvgyok0PZD_-iQAFOhOd5YxDTkczOLoqTTL_A';
|
|
369
|
-
function initANTStateForAddress({ owner, targetId, ttlSeconds = 3600, keywords = [], controllers = [], description = '', ticker = 'aos', name = 'ANT', logo = exports.defaultANTLogoId, }) {
|
|
370
|
-
return {
|
|
371
|
-
ticker,
|
|
372
|
-
name,
|
|
373
|
-
description,
|
|
374
|
-
keywords,
|
|
375
|
-
owner,
|
|
376
|
-
controllers: [owner, ...controllers],
|
|
377
|
-
balances: { [owner]: 1 },
|
|
378
|
-
records: {
|
|
379
|
-
['@']: {
|
|
380
|
-
transactionId: targetId ?? exports.defaultTargetManifestId.toString(),
|
|
381
|
-
ttlSeconds,
|
|
382
|
-
},
|
|
383
|
-
},
|
|
384
|
-
logo,
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* Uses zod schema to parse the epoch data
|
|
389
|
-
*/
|
|
390
|
-
function parseAoEpochData(value) {
|
|
391
|
-
const epochDataSchema = zod_1.z.object({
|
|
392
|
-
startTimestamp: zod_1.z.number(),
|
|
393
|
-
startHeight: zod_1.z.number(),
|
|
394
|
-
distributions: zod_1.z.any(), // TODO: add full distributed object type
|
|
395
|
-
endTimestamp: zod_1.z.number(),
|
|
396
|
-
prescribedObservers: zod_1.z.any(),
|
|
397
|
-
prescribedNames: zod_1.z.array(zod_1.z.string()),
|
|
398
|
-
observations: zod_1.z.any(),
|
|
399
|
-
epochIndex: zod_1.z.number(),
|
|
400
|
-
arnsStats: zod_1.z.any(),
|
|
401
|
-
});
|
|
402
|
-
return epochDataSchema.parse(value);
|
|
403
|
-
}
|
|
404
|
-
function errorMessageFromOutput(output) {
|
|
405
|
-
const errorData = output.Error;
|
|
406
|
-
// Attempt to extract error details from Messages.Tags if Error is undefined
|
|
407
|
-
const error = errorData ??
|
|
408
|
-
output.Messages?.[0]?.Tags?.find((tag) => tag.name === 'Error')?.value;
|
|
409
|
-
if (error !== undefined) {
|
|
410
|
-
const errorStackTrace = output.Messages?.[0]?.Data;
|
|
411
|
-
const errorMessage = errorStackTrace ?? error;
|
|
412
|
-
// Regex to match AO error messages like: [string ".src.main"]:5111: Primary name data not found
|
|
413
|
-
// or [string "aos"]:128: some error
|
|
414
|
-
const match = errorMessage?.match(/\[string "(.+)"\]:(\d+):\s*(.*)/);
|
|
415
|
-
if (match) {
|
|
416
|
-
// The first group is the src file, the second is the line number, and the third is the error message
|
|
417
|
-
const [, , lineNumber, errorMessage] = match;
|
|
418
|
-
const cleanError = removeUnicodeFromError(errorMessage);
|
|
419
|
-
return `${cleanError.trim()} (line ${lineNumber.trim()})`.trim();
|
|
420
|
-
}
|
|
421
|
-
// With no match, just remove unicode
|
|
422
|
-
return removeUnicodeFromError(error);
|
|
423
|
-
}
|
|
424
|
-
return undefined;
|
|
425
|
-
}
|
|
426
|
-
function removeUnicodeFromError(error) {
|
|
427
|
-
//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.
|
|
428
|
-
const ESC = String.fromCharCode(27); // Represents '\u001b' or '\x1b'
|
|
429
|
-
return error
|
|
430
|
-
.replace(new RegExp(`${ESC}[\\[\\]()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]`, 'g'), '')
|
|
431
|
-
.trim();
|
|
432
|
-
}
|