@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.
- package/README.md +757 -589
- 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 +227 -0
- package/lib/esm/cli/commands/gatewayWriteCommands.js +140 -23
- package/lib/esm/cli/commands/pruneCommands.js +154 -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 +303 -175
- package/lib/esm/common/ant-registry.js +17 -143
- package/lib/esm/common/ant.js +44 -1167
- package/lib/esm/common/faucet.js +17 -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 +66 -258
- 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
|
@@ -1,106 +1,71 @@
|
|
|
1
|
-
import { antRecordMetadataFromOptions,
|
|
1
|
+
import { antRecordMetadataFromOptions, assertConfirmationPrompt, customTagsFromOptions, defaultTtlSecondsCLI, requiredStringFromOptions, writeANTFromOptions, } from '../utils.js';
|
|
2
|
+
function targetProtocolFromOptions(o) {
|
|
3
|
+
const raw = o.targetProtocol;
|
|
4
|
+
if (!raw || raw === 'arweave')
|
|
5
|
+
return 0;
|
|
6
|
+
if (raw === 'ipfs')
|
|
7
|
+
return 1;
|
|
8
|
+
throw new Error(`Invalid --target-protocol "${raw}". Must be "arweave" or "ipfs".`);
|
|
9
|
+
}
|
|
2
10
|
/** @deprecated -- use set-ant-base-name and set-ant-undername */
|
|
3
11
|
export async function setAntRecordCLICommand(o) {
|
|
4
12
|
const ttlSeconds = +(o.ttlSeconds ?? defaultTtlSecondsCLI);
|
|
5
13
|
const undername = requiredStringFromOptions(o, 'undername');
|
|
6
14
|
const transactionId = requiredStringFromOptions(o, 'transactionId');
|
|
7
|
-
const
|
|
15
|
+
const targetProtocol = targetProtocolFromOptions(o);
|
|
16
|
+
const writeAnt = await writeANTFromOptions(o);
|
|
8
17
|
const recordParams = {
|
|
9
18
|
undername,
|
|
10
19
|
transactionId,
|
|
11
20
|
ttlSeconds,
|
|
21
|
+
targetProtocol,
|
|
12
22
|
...antRecordMetadataFromOptions(o),
|
|
13
23
|
};
|
|
14
24
|
if (!o.skipConfirmation) {
|
|
15
25
|
await assertConfirmationPrompt(`Are you sure you want to set this record on the ANT process ${writeAnt.processId}?\n${JSON.stringify(recordParams, null, 2)}`, o);
|
|
16
26
|
}
|
|
17
|
-
return
|
|
27
|
+
return writeAnt.setRecord(recordParams, customTagsFromOptions(o));
|
|
18
28
|
}
|
|
19
29
|
export async function setAntBaseNameCLICommand(o) {
|
|
20
30
|
const ttlSeconds = +(o.ttlSeconds ?? defaultTtlSecondsCLI);
|
|
21
31
|
const transactionId = requiredStringFromOptions(o, 'transactionId');
|
|
32
|
+
const targetProtocol = targetProtocolFromOptions(o);
|
|
22
33
|
const params = {
|
|
23
34
|
transactionId,
|
|
24
35
|
ttlSeconds,
|
|
36
|
+
targetProtocol,
|
|
25
37
|
...antRecordMetadataFromOptions(o),
|
|
26
38
|
};
|
|
27
|
-
const writeAnt = writeANTFromOptions(o);
|
|
39
|
+
const writeAnt = await writeANTFromOptions(o);
|
|
28
40
|
if (!o.skipConfirmation) {
|
|
29
41
|
await assertConfirmationPrompt(`Are you sure you want to set this base name on the ANT process ${writeAnt.processId}?\n${JSON.stringify(params, null, 2)}`, o);
|
|
30
42
|
}
|
|
31
|
-
return
|
|
43
|
+
return writeAnt.setBaseNameRecord(params, customTagsFromOptions(o));
|
|
32
44
|
}
|
|
33
45
|
export async function setAntUndernameCLICommand(o) {
|
|
34
46
|
const ttlSeconds = +(o.ttlSeconds ?? defaultTtlSecondsCLI);
|
|
35
47
|
const undername = requiredStringFromOptions(o, 'undername');
|
|
36
48
|
const transactionId = requiredStringFromOptions(o, 'transactionId');
|
|
49
|
+
const targetProtocol = targetProtocolFromOptions(o);
|
|
37
50
|
const params = {
|
|
38
51
|
undername,
|
|
39
52
|
transactionId,
|
|
40
53
|
ttlSeconds,
|
|
54
|
+
targetProtocol,
|
|
41
55
|
...antRecordMetadataFromOptions(o),
|
|
42
56
|
};
|
|
43
|
-
const writeAnt = writeANTFromOptions(o);
|
|
57
|
+
const writeAnt = await writeANTFromOptions(o);
|
|
44
58
|
if (!o.skipConfirmation) {
|
|
45
59
|
await assertConfirmationPrompt(`Are you sure you want to set this undername on the ANT process ${writeAnt.processId}?\n${JSON.stringify(params, null, 2)}`, o);
|
|
46
60
|
}
|
|
47
|
-
return
|
|
61
|
+
return writeAnt.setUndernameRecord(params, customTagsFromOptions(o));
|
|
48
62
|
}
|
|
49
63
|
export async function transferRecordOwnershipCLICommand(o) {
|
|
50
64
|
const undername = requiredStringFromOptions(o, 'undername');
|
|
51
65
|
const recipient = requiredStringFromOptions(o, 'recipient');
|
|
52
|
-
const writeAnt = writeANTFromOptions(o);
|
|
66
|
+
const writeAnt = await writeANTFromOptions(o);
|
|
53
67
|
if (!o.skipConfirmation) {
|
|
54
68
|
await assertConfirmationPrompt(`Are you sure you want to transfer ownership of "${undername}" to "${recipient}" on ANT process ${writeAnt.processId}?\n${JSON.stringify({ undername, recipient }, null, 2)}`, o);
|
|
55
69
|
}
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
export async function upgradeAntCLICommand(o) {
|
|
59
|
-
const writeAnt = writeANTFromOptions(o);
|
|
60
|
-
const arioProcessId = arioProcessIdFromOptions(o);
|
|
61
|
-
const ario = readARIOFromOptions(o);
|
|
62
|
-
const reassignAffiliatedNames = booleanFromOptions(o, 'reassignAffiliatedNames');
|
|
63
|
-
const names = stringArrayFromOptions(o, 'names') || [];
|
|
64
|
-
if (reassignAffiliatedNames) {
|
|
65
|
-
// Fetch all ArNS records that point to this ANT process
|
|
66
|
-
const allRecords = await ario.getArNSRecords({
|
|
67
|
-
filters: {
|
|
68
|
-
processId: writeAnt.processId,
|
|
69
|
-
},
|
|
70
|
-
});
|
|
71
|
-
// Filter records that belong to this ANT
|
|
72
|
-
const affiliatedNames = allRecords.items.map((record) => record.name);
|
|
73
|
-
names.push(...affiliatedNames);
|
|
74
|
-
}
|
|
75
|
-
if (names.length === 0) {
|
|
76
|
-
throw new Error('No names to reassign');
|
|
77
|
-
}
|
|
78
|
-
if (!o.skipConfirmation) {
|
|
79
|
-
await assertConfirmationPrompt(`Upgrade all names affiliated with this ANT on ARIO process?\n` +
|
|
80
|
-
`ARIO Process ID: ${arioProcessId}\n` +
|
|
81
|
-
`ANT Process ID: ${writeAnt.processId}\n` +
|
|
82
|
-
`Names that will be reassigned (${names.length}): ${names.join(', ')}`, o);
|
|
83
|
-
}
|
|
84
|
-
const result = reassignAffiliatedNames
|
|
85
|
-
? await writeANTFromOptions(o).upgrade({
|
|
86
|
-
reassignAffiliatedNames,
|
|
87
|
-
arioProcessId,
|
|
88
|
-
})
|
|
89
|
-
: await writeANTFromOptions(o).upgrade({
|
|
90
|
-
names,
|
|
91
|
-
arioProcessId,
|
|
92
|
-
});
|
|
93
|
-
// Serialize error objects for JSON compatibility
|
|
94
|
-
const serializedFailedReassignedNames = {};
|
|
95
|
-
for (const [name, failure] of Object.entries(result.failedReassignedNames)) {
|
|
96
|
-
serializedFailedReassignedNames[name] = {
|
|
97
|
-
id: failure.id,
|
|
98
|
-
error: failure.error.message,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
forkedProcessId: result.forkedProcessId,
|
|
103
|
-
reassignedNames: result.reassignedNames,
|
|
104
|
-
failedReassignedNames: serializedFailedReassignedNames,
|
|
105
|
-
};
|
|
70
|
+
return writeAnt.transferRecord({ undername, recipient }, customTagsFromOptions(o));
|
|
106
71
|
}
|
|
@@ -1,22 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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 { ANT } from '../../common/ant.js';
|
|
17
|
-
import { assertConfirmationPrompt, assertEnoughBalanceForArNSPurchase, customTagsFromOptions, fundFromFromOptions, positiveIntegerFromOptions, recordTypeFromOptions, referrerFromOptions, requiredPositiveIntegerFromOptions, requiredStringFromOptions, stringArrayFromOptions, writeARIOFromOptions, } from '../utils.js';
|
|
1
|
+
import { assertConfirmationPrompt, assertEnoughBalanceForArNSPurchase, customTagsFromOptions, fundFromFromOptions, fundingPlanFromOptions, positiveIntegerFromOptions, recordTypeFromOptions, referrerFromOptions, requiredPositiveIntegerFromOptions, requiredStringFromOptions, stringArrayFromOptions, withdrawalIdFromOptions, writeARIOFromOptions, } from '../utils.js';
|
|
2
|
+
/** Coerce the JSON-parsed funding plan to the typed `FundingSourceSpec[]`. */
|
|
3
|
+
function coerceFundingPlanSources(parsed) {
|
|
4
|
+
if (!parsed)
|
|
5
|
+
return undefined;
|
|
6
|
+
return parsed.map((s) => ({
|
|
7
|
+
kind: s.kind,
|
|
8
|
+
amount: s.amount,
|
|
9
|
+
...(s.gateway ? { gateway: s.gateway } : {}),
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
18
12
|
export async function buyRecordCLICommand(o) {
|
|
19
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
13
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
20
14
|
const name = requiredStringFromOptions(o, 'name');
|
|
21
15
|
const type = recordTypeFromOptions(o);
|
|
22
16
|
const years = positiveIntegerFromOptions(o, 'years');
|
|
@@ -42,13 +36,9 @@ export async function buyRecordCLICommand(o) {
|
|
|
42
36
|
fromAddress: signerAddress,
|
|
43
37
|
},
|
|
44
38
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const { moduleId, version } = await ANT.versions.getLatestANTVersion();
|
|
49
|
-
antSpawnConfirmation = `Note: A new ANT process will be spawned with module ${moduleId} (v${version}) and assigned to this name.`;
|
|
50
|
-
}
|
|
51
|
-
await assertConfirmationPrompt(`Are you sure you want to ${type} the record ${name}? ${antSpawnConfirmation}`, o);
|
|
39
|
+
await assertConfirmationPrompt(`Are you sure you want to ${type} the record ${name}?${processId === undefined
|
|
40
|
+
? ' Note: A new ANT (MPL Core asset) will be spawned and assigned to this name.'
|
|
41
|
+
: ''}`, o);
|
|
52
42
|
}
|
|
53
43
|
return ario.buyRecord({
|
|
54
44
|
name: requiredStringFromOptions(o, 'name'),
|
|
@@ -56,13 +46,17 @@ export async function buyRecordCLICommand(o) {
|
|
|
56
46
|
type,
|
|
57
47
|
years,
|
|
58
48
|
fundFrom: fundFromFromOptions(o),
|
|
49
|
+
gatewayAddress: o.gatewayAddress,
|
|
50
|
+
fundAsOperator: o.fundAsOperator,
|
|
51
|
+
withdrawalId: withdrawalIdFromOptions(o),
|
|
52
|
+
sources: coerceFundingPlanSources(fundingPlanFromOptions(o)),
|
|
59
53
|
paidBy: stringArrayFromOptions(o, 'paidBy'),
|
|
60
54
|
referrer,
|
|
61
55
|
}, customTagsFromOptions(o));
|
|
62
56
|
}
|
|
63
57
|
export async function upgradeRecordCLICommand(o) {
|
|
64
58
|
const name = requiredStringFromOptions(o, 'name');
|
|
65
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
59
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
66
60
|
const fundFrom = fundFromFromOptions(o);
|
|
67
61
|
const referrer = referrerFromOptions(o);
|
|
68
62
|
if (!o.skipConfirmation) {
|
|
@@ -90,6 +84,8 @@ export async function upgradeRecordCLICommand(o) {
|
|
|
90
84
|
return ario.upgradeRecord({
|
|
91
85
|
name,
|
|
92
86
|
fundFrom,
|
|
87
|
+
gatewayAddress: o.gatewayAddress,
|
|
88
|
+
fundAsOperator: o.fundAsOperator,
|
|
93
89
|
paidBy: stringArrayFromOptions(o, 'paidBy'),
|
|
94
90
|
referrer,
|
|
95
91
|
});
|
|
@@ -99,7 +95,7 @@ export async function extendLeaseCLICommand(o) {
|
|
|
99
95
|
const years = requiredPositiveIntegerFromOptions(o, 'years');
|
|
100
96
|
const fundFrom = fundFromFromOptions(o);
|
|
101
97
|
const referrer = referrerFromOptions(o);
|
|
102
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
98
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
103
99
|
if (!o.skipConfirmation) {
|
|
104
100
|
const existingRecord = await ario.getArNSRecord({
|
|
105
101
|
name,
|
|
@@ -126,6 +122,9 @@ export async function extendLeaseCLICommand(o) {
|
|
|
126
122
|
return ario.extendLease({
|
|
127
123
|
name,
|
|
128
124
|
years,
|
|
125
|
+
fundFrom,
|
|
126
|
+
gatewayAddress: o.gatewayAddress,
|
|
127
|
+
fundAsOperator: o.fundAsOperator,
|
|
129
128
|
paidBy: stringArrayFromOptions(o, 'paidBy'),
|
|
130
129
|
referrer,
|
|
131
130
|
}, customTagsFromOptions(o));
|
|
@@ -135,7 +134,7 @@ export async function increaseUndernameLimitCLICommand(o) {
|
|
|
135
134
|
const increaseCount = requiredPositiveIntegerFromOptions(o, 'increaseCount');
|
|
136
135
|
const fundFrom = fundFromFromOptions(o);
|
|
137
136
|
const referrer = referrerFromOptions(o);
|
|
138
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
137
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
139
138
|
if (!o.skipConfirmation) {
|
|
140
139
|
const existingRecord = await ario.getArNSRecord({
|
|
141
140
|
name,
|
|
@@ -159,12 +158,15 @@ export async function increaseUndernameLimitCLICommand(o) {
|
|
|
159
158
|
return ario.increaseUndernameLimit({
|
|
160
159
|
name,
|
|
161
160
|
increaseCount,
|
|
161
|
+
fundFrom,
|
|
162
|
+
gatewayAddress: o.gatewayAddress,
|
|
163
|
+
fundAsOperator: o.fundAsOperator,
|
|
162
164
|
paidBy: stringArrayFromOptions(o, 'paidBy'),
|
|
163
165
|
referrer,
|
|
164
166
|
}, customTagsFromOptions(o));
|
|
165
167
|
}
|
|
166
168
|
export async function requestPrimaryNameCLICommand(o) {
|
|
167
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
169
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
168
170
|
const fundFrom = fundFromFromOptions(o);
|
|
169
171
|
const referrer = referrerFromOptions(o);
|
|
170
172
|
const name = requiredStringFromOptions(o, 'name');
|
|
@@ -193,7 +195,7 @@ export async function requestPrimaryNameCLICommand(o) {
|
|
|
193
195
|
return result.request;
|
|
194
196
|
}
|
|
195
197
|
export async function setPrimaryNameCLICommand(o) {
|
|
196
|
-
const { ario, signerAddress } = writeARIOFromOptions(o);
|
|
198
|
+
const { ario, signerAddress } = await writeARIOFromOptions(o);
|
|
197
199
|
const name = requiredStringFromOptions(o, 'name');
|
|
198
200
|
const fundFrom = fundFromFromOptions(o);
|
|
199
201
|
const referrer = referrerFromOptions(o);
|
|
@@ -202,3 +204,19 @@ export async function setPrimaryNameCLICommand(o) {
|
|
|
202
204
|
}
|
|
203
205
|
return ario.setPrimaryName({ name, fundFrom, referrer });
|
|
204
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Reconcile the on-chain ANT Attributes plugin (`ArNS Name`, `Type`,
|
|
209
|
+
* `Undername Limit`) with the current `ArnsRecord` state. Permissionless.
|
|
210
|
+
*
|
|
211
|
+
* Use after a `buy-record` where the buyer was not the ANT NFT holder
|
|
212
|
+
* (the ANT-side trait CPI gets skipped at runtime in that case so the
|
|
213
|
+
* plugin stays empty until the actual holder reconciles).
|
|
214
|
+
*/
|
|
215
|
+
export async function syncAttributesCLICommand(o) {
|
|
216
|
+
const name = requiredStringFromOptions(o, 'name');
|
|
217
|
+
const { ario } = await writeARIOFromOptions(o);
|
|
218
|
+
if (!o.skipConfirmation) {
|
|
219
|
+
await assertConfirmationPrompt(`Sync on-chain ANT traits for "${name}" to match the current ArnsRecord?`, o);
|
|
220
|
+
}
|
|
221
|
+
return ario.syncAttributes({ name });
|
|
222
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
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
|
+
/**
|
|
17
|
+
* CLI commands for `ario-ant-escrow` — trustless multi-protocol ANT custody.
|
|
18
|
+
*
|
|
19
|
+
* Each command instantiates an {@link ANTEscrow} with options-driven RPC +
|
|
20
|
+
* signer wiring (mirrors the rest of the Solana CLI surface — see
|
|
21
|
+
* `arnsPurchaseCommands.ts`). All read commands work without a signer; all
|
|
22
|
+
* write commands require `--wallet-file` or `--private-key`.
|
|
23
|
+
*
|
|
24
|
+
* Recipient pubkey loading:
|
|
25
|
+
* - Arweave: `--recipient-arweave <jwk-file>` reads the JWK JSON, decodes
|
|
26
|
+
* the base64url `n` field to 512 raw bytes (RSA-4096 modulus).
|
|
27
|
+
* - Ethereum: `--recipient-ethereum 0x...` parses the 20-byte hex address.
|
|
28
|
+
*/
|
|
29
|
+
import { readFileSync } from 'node:fs';
|
|
30
|
+
import { address, createKeyPairSignerFromBytes, createSolanaRpcSubscriptions, } from '@solana/kit';
|
|
31
|
+
import bs58 from 'bs58';
|
|
32
|
+
import { ARIO_ANT_ESCROW_PROGRAM_ID } from '../../solana/constants.js';
|
|
33
|
+
import { ANTEscrow } from '../../solana/escrow.js';
|
|
34
|
+
import { createCircuitBreakerRpc, defaultFallbackUrl, } from '../../solana/rpc-circuit-breaker.js';
|
|
35
|
+
// =========================================
|
|
36
|
+
// Wiring helpers
|
|
37
|
+
// =========================================
|
|
38
|
+
function wsUrlFromRpcUrl(rpcUrl) {
|
|
39
|
+
return rpcUrl.replace(/^http/, 'ws');
|
|
40
|
+
}
|
|
41
|
+
function escrowProgramIdFrom(options) {
|
|
42
|
+
return options.escrowProgramId
|
|
43
|
+
? address(options.escrowProgramId)
|
|
44
|
+
: ARIO_ANT_ESCROW_PROGRAM_ID;
|
|
45
|
+
}
|
|
46
|
+
async function readEscrowReader(options) {
|
|
47
|
+
const rpcUrl = options.rpcUrl ?? 'https://api.mainnet-beta.solana.com';
|
|
48
|
+
return ANTEscrow.init({
|
|
49
|
+
rpc: createCircuitBreakerRpc({
|
|
50
|
+
primaryUrl: rpcUrl,
|
|
51
|
+
fallbackUrl: defaultFallbackUrl(rpcUrl),
|
|
52
|
+
}),
|
|
53
|
+
programId: escrowProgramIdFrom(options),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async function writeEscrowFromOptions(options) {
|
|
57
|
+
let secretKey;
|
|
58
|
+
if (options.privateKey) {
|
|
59
|
+
secretKey = bs58.decode(options.privateKey);
|
|
60
|
+
}
|
|
61
|
+
else if (options.walletFile) {
|
|
62
|
+
const raw = readFileSync(options.walletFile, 'utf-8');
|
|
63
|
+
secretKey = new Uint8Array(JSON.parse(raw));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
throw new Error('escrow write operations require a signer. Provide --wallet-file <path> or --private-key <base58>');
|
|
67
|
+
}
|
|
68
|
+
const signer = await createKeyPairSignerFromBytes(secretKey);
|
|
69
|
+
const rpcUrl = options.rpcUrl ?? 'https://api.mainnet-beta.solana.com';
|
|
70
|
+
return ANTEscrow.init({
|
|
71
|
+
rpc: createCircuitBreakerRpc({
|
|
72
|
+
primaryUrl: rpcUrl,
|
|
73
|
+
fallbackUrl: defaultFallbackUrl(rpcUrl),
|
|
74
|
+
}),
|
|
75
|
+
rpcSubscriptions: createSolanaRpcSubscriptions(wsUrlFromRpcUrl(rpcUrl)),
|
|
76
|
+
signer,
|
|
77
|
+
programId: escrowProgramIdFrom(options),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// =========================================
|
|
81
|
+
// Recipient pubkey parsing
|
|
82
|
+
// =========================================
|
|
83
|
+
function base64UrlDecode(s) {
|
|
84
|
+
// Convert base64url → base64, then decode.
|
|
85
|
+
let b64 = s.replace(/-/g, '+').replace(/_/g, '/');
|
|
86
|
+
while (b64.length % 4 !== 0)
|
|
87
|
+
b64 += '=';
|
|
88
|
+
return new Uint8Array(Buffer.from(b64, 'base64'));
|
|
89
|
+
}
|
|
90
|
+
/** Load an Arweave RSA-4096 modulus from a JWK file (`.json` with `n` field). */
|
|
91
|
+
function loadArweaveModulusFromJwk(filePath) {
|
|
92
|
+
const raw = readFileSync(filePath, 'utf-8');
|
|
93
|
+
const jwk = JSON.parse(raw);
|
|
94
|
+
if (jwk.kty !== 'RSA' || !jwk.n) {
|
|
95
|
+
throw new Error(`Not a valid Arweave RSA JWK (missing kty=RSA or n field)`);
|
|
96
|
+
}
|
|
97
|
+
const modulus = base64UrlDecode(jwk.n);
|
|
98
|
+
if (modulus.length !== 512) {
|
|
99
|
+
throw new Error(`Arweave modulus must be 512 bytes (4096-bit RSA); got ${modulus.length}`);
|
|
100
|
+
}
|
|
101
|
+
return modulus;
|
|
102
|
+
}
|
|
103
|
+
/** Parse an Ethereum address (`0xabc...`) into 20 raw bytes. */
|
|
104
|
+
function parseEthereumAddress(hex) {
|
|
105
|
+
const cleaned = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
106
|
+
if (cleaned.length !== 40 || !/^[0-9a-fA-F]+$/.test(cleaned)) {
|
|
107
|
+
throw new Error(`Ethereum address must be 0x-prefixed 40-char hex; got "${hex}"`);
|
|
108
|
+
}
|
|
109
|
+
return Uint8Array.from(Buffer.from(cleaned, 'hex'));
|
|
110
|
+
}
|
|
111
|
+
function recipientFromDepositOptions(o) {
|
|
112
|
+
if (o.recipientArweave && o.recipientEthereum) {
|
|
113
|
+
throw new Error('--recipient-arweave and --recipient-ethereum are mutually exclusive');
|
|
114
|
+
}
|
|
115
|
+
if (o.recipientArweave) {
|
|
116
|
+
return {
|
|
117
|
+
protocol: 'arweave',
|
|
118
|
+
publicKey: loadArweaveModulusFromJwk(o.recipientArweave),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (o.recipientEthereum) {
|
|
122
|
+
return {
|
|
123
|
+
protocol: 'ethereum',
|
|
124
|
+
publicKey: parseEthereumAddress(o.recipientEthereum),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
throw new Error('one of --recipient-arweave or --recipient-ethereum is required');
|
|
128
|
+
}
|
|
129
|
+
function recipientFromUpdateOptions(o) {
|
|
130
|
+
return recipientFromDepositOptions({
|
|
131
|
+
recipientArweave: o.newRecipientArweave,
|
|
132
|
+
recipientEthereum: o.newRecipientEthereum,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function antFromOptions(o) {
|
|
136
|
+
if (!o.ant)
|
|
137
|
+
throw new Error('--ant <mint> is required');
|
|
138
|
+
return address(o.ant);
|
|
139
|
+
}
|
|
140
|
+
// =========================================
|
|
141
|
+
// CLI handlers
|
|
142
|
+
// =========================================
|
|
143
|
+
/** `ar.io escrow status --ant <mint>` */
|
|
144
|
+
export async function escrowStatusCLICommand(o) {
|
|
145
|
+
const escrow = await readEscrowReader(o);
|
|
146
|
+
const ant = antFromOptions(o);
|
|
147
|
+
const state = await escrow.get(ant);
|
|
148
|
+
if (!state) {
|
|
149
|
+
return { active: false, antMint: ant };
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
active: true,
|
|
153
|
+
antMint: state.antMint,
|
|
154
|
+
depositor: state.depositor,
|
|
155
|
+
recipientProtocol: state.recipientProtocol,
|
|
156
|
+
recipientPubkeyHex: Buffer.from(state.recipientPubkey).toString('hex'),
|
|
157
|
+
nonceHex: Buffer.from(state.nonce).toString('hex'),
|
|
158
|
+
depositSlot: state.depositSlot.toString(),
|
|
159
|
+
version: state.version,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/** `ar.io escrow deposit --ant <mint> --recipient-{arweave|ethereum} ...` */
|
|
163
|
+
export async function escrowDepositCLICommand(o) {
|
|
164
|
+
const recipient = recipientFromDepositOptions(o);
|
|
165
|
+
const escrow = await writeEscrowFromOptions(o);
|
|
166
|
+
const sig = await escrow.deposit({ antMint: antFromOptions(o), recipient });
|
|
167
|
+
return { signature: sig };
|
|
168
|
+
}
|
|
169
|
+
/** `ar.io escrow cancel --ant <mint>` */
|
|
170
|
+
export async function escrowCancelCLICommand(o) {
|
|
171
|
+
const escrow = await writeEscrowFromOptions(o);
|
|
172
|
+
const sig = await escrow.cancel({ antMint: antFromOptions(o) });
|
|
173
|
+
return { signature: sig };
|
|
174
|
+
}
|
|
175
|
+
/** `ar.io escrow update-recipient --ant <mint> --new-recipient-{arweave|ethereum} ...` */
|
|
176
|
+
export async function escrowUpdateRecipientCLICommand(o) {
|
|
177
|
+
const newRecipient = recipientFromUpdateOptions(o);
|
|
178
|
+
const escrow = await writeEscrowFromOptions(o);
|
|
179
|
+
const sig = await escrow.updateRecipient({
|
|
180
|
+
antMint: antFromOptions(o),
|
|
181
|
+
newRecipient,
|
|
182
|
+
});
|
|
183
|
+
return { signature: sig };
|
|
184
|
+
}
|
|
185
|
+
/** `ar.io escrow claim-arweave --ant <mint> --signature-file <bin> --claimant <pubkey> [--salt-len 32]` */
|
|
186
|
+
export async function escrowClaimArweaveCLICommand(o) {
|
|
187
|
+
if (!o.signatureFile)
|
|
188
|
+
throw new Error('--signature-file <path> is required');
|
|
189
|
+
if (!o.claimant)
|
|
190
|
+
throw new Error('--claimant <pubkey> is required');
|
|
191
|
+
const sigBytes = new Uint8Array(readFileSync(o.signatureFile));
|
|
192
|
+
if (sigBytes.length !== 512) {
|
|
193
|
+
throw new Error(`signature file must be 512 bytes; got ${sigBytes.length}`);
|
|
194
|
+
}
|
|
195
|
+
// RSA-PSS salt length: 0 is a valid value, so only reject NaN / negative /
|
|
196
|
+
// non-integer. An unset flag defaults to 32 (a full SHA-256 digest).
|
|
197
|
+
const saltLen = o.saltLen ? Number.parseInt(o.saltLen, 10) : 32;
|
|
198
|
+
if (!Number.isInteger(saltLen) || saltLen < 0) {
|
|
199
|
+
throw new Error(`--salt-len must be a non-negative integer (got '${o.saltLen}')`);
|
|
200
|
+
}
|
|
201
|
+
const escrow = await writeEscrowFromOptions(o);
|
|
202
|
+
const sig = await escrow.claimArweave({
|
|
203
|
+
antMint: antFromOptions(o),
|
|
204
|
+
claimant: address(o.claimant),
|
|
205
|
+
signature: sigBytes,
|
|
206
|
+
saltLen,
|
|
207
|
+
});
|
|
208
|
+
return { signature: sig };
|
|
209
|
+
}
|
|
210
|
+
/** `ar.io escrow claim-ethereum --ant <mint> --signature-file <bin> --claimant <pubkey>` */
|
|
211
|
+
export async function escrowClaimEthereumCLICommand(o) {
|
|
212
|
+
if (!o.signatureFile)
|
|
213
|
+
throw new Error('--signature-file <path> is required');
|
|
214
|
+
if (!o.claimant)
|
|
215
|
+
throw new Error('--claimant <pubkey> is required');
|
|
216
|
+
const sigBytes = new Uint8Array(readFileSync(o.signatureFile));
|
|
217
|
+
if (sigBytes.length !== 65) {
|
|
218
|
+
throw new Error(`signature file must be 65 bytes (r||s||v); got ${sigBytes.length}`);
|
|
219
|
+
}
|
|
220
|
+
const escrow = await writeEscrowFromOptions(o);
|
|
221
|
+
const sig = await escrow.claimEthereum({
|
|
222
|
+
antMint: antFromOptions(o),
|
|
223
|
+
claimant: address(o.claimant),
|
|
224
|
+
signature: sigBytes,
|
|
225
|
+
});
|
|
226
|
+
return { signature: sig };
|
|
227
|
+
}
|