@halot/cli 1.0.0
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/.env.example +14 -0
- package/README.md +374 -0
- package/dist/features/browse/browse.command.js +15 -0
- package/dist/features/jobs/job-create.command.js +57 -0
- package/dist/features/jobs/job-funding.service.js +95 -0
- package/dist/features/jobs/job-result.command.js +10 -0
- package/dist/features/jobs/job-watch.command.js +18 -0
- package/dist/features/provider/provider-init.command.js +33 -0
- package/dist/features/provider/provider-register.command.js +72 -0
- package/dist/features/provider/provider-run.command.js +148 -0
- package/dist/features/provider/provider-services.command.js +13 -0
- package/dist/features/provider/provider-stats.command.js +13 -0
- package/dist/features/provider/provider-update.command.js +35 -0
- package/dist/features/quotes/quote.command.js +13 -0
- package/dist/features/requester/requester-init.command.js +22 -0
- package/dist/features/service/service-create.command.js +57 -0
- package/dist/features/service/service-init.command.js +89 -0
- package/dist/features/service/service-list.command.js +23 -0
- package/dist/features/service/service-remove.command.js +21 -0
- package/dist/features/service/service-update.command.js +65 -0
- package/dist/features/verifier/verifier-init.command.js +69 -0
- package/dist/features/verifier/verifier-register.command.js +90 -0
- package/dist/features/verifier/verifier-run.command.js +143 -0
- package/dist/features/verifier/verifier-stats.command.js +13 -0
- package/dist/features/verifier/verifier-unstake.command.js +31 -0
- package/dist/index.js +136 -0
- package/dist/shared/auth/actor-headers.service.js +13 -0
- package/dist/shared/config/env.js +77 -0
- package/dist/shared/http/api-client.js +66 -0
- package/dist/shared/http/event-stream.js +75 -0
- package/dist/shared/integrations/agent-id/agent-id-register.service.js +159 -0
- package/dist/shared/integrations/space-id/space-id-register.service.js +467 -0
- package/dist/shared/integrations/zero-g/verifier-registry.service.js +55 -0
- package/dist/shared/output/print.util.js +10 -0
- package/dist/shared/wallet/authority.util.js +62 -0
- package/dist/shared/wallet/wallet.manager.js +41 -0
- package/dist/shared/workspace/workspace.service.js +192 -0
- package/package.json +47 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveAuthorityWallet = resolveAuthorityWallet;
|
|
4
|
+
exports.resolveActorWallet = resolveActorWallet;
|
|
5
|
+
exports.resolveAuthorityAddress = resolveAuthorityAddress;
|
|
6
|
+
exports.deriveVerifierSigningPublicKey = deriveVerifierSigningPublicKey;
|
|
7
|
+
exports.createDefaultSettlementWallets = createDefaultSettlementWallets;
|
|
8
|
+
exports.resolveZeroGAuthorityProfile = resolveZeroGAuthorityProfile;
|
|
9
|
+
exports.isMainnetAuthority = isMainnetAuthority;
|
|
10
|
+
const stellar_sdk_1 = require("@stellar/stellar-sdk");
|
|
11
|
+
const ethers_1 = require("ethers");
|
|
12
|
+
const zeroGAuthorityProfiles = {
|
|
13
|
+
'0g:testnet': {
|
|
14
|
+
networkMode: 'testnet',
|
|
15
|
+
chainId: 16602,
|
|
16
|
+
rpcUrl: 'https://evmrpc-testnet.0g.ai',
|
|
17
|
+
},
|
|
18
|
+
'0g:mainnet': {
|
|
19
|
+
networkMode: 'mainnet',
|
|
20
|
+
chainId: 16661,
|
|
21
|
+
rpcUrl: 'https://evmrpc.0g.ai',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
function resolveAuthorityWallet(wallets, authority) {
|
|
25
|
+
return wallets.authorities[authority];
|
|
26
|
+
}
|
|
27
|
+
function resolveActorWallet(wallets, authority) {
|
|
28
|
+
return new ethers_1.Wallet(resolveAuthorityWallet(wallets, authority).privateKey);
|
|
29
|
+
}
|
|
30
|
+
function resolveAuthorityAddress(wallets, authority) {
|
|
31
|
+
const privateKey = resolveAuthorityWallet(wallets, authority).privateKey;
|
|
32
|
+
if (authority.startsWith('0g:')) {
|
|
33
|
+
return new ethers_1.Wallet(privateKey).address;
|
|
34
|
+
}
|
|
35
|
+
if (authority.startsWith('stellar:')) {
|
|
36
|
+
return stellar_sdk_1.Keypair.fromSecret(privateKey).publicKey();
|
|
37
|
+
}
|
|
38
|
+
throw new Error(`Unsupported authority ${authority}`);
|
|
39
|
+
}
|
|
40
|
+
function deriveVerifierSigningPublicKey(wallets, authority) {
|
|
41
|
+
return new ethers_1.SigningKey(resolveAuthorityWallet(wallets, asZeroGAuthority(authority)).privateKey).publicKey;
|
|
42
|
+
}
|
|
43
|
+
function createDefaultSettlementWallets(wallets) {
|
|
44
|
+
return {
|
|
45
|
+
'0g:testnet': resolveAuthorityAddress(wallets, '0g:testnet'),
|
|
46
|
+
'0g:mainnet': resolveAuthorityAddress(wallets, '0g:mainnet'),
|
|
47
|
+
'stellar:testnet': resolveAuthorityAddress(wallets, 'stellar:testnet'),
|
|
48
|
+
'stellar:mainnet': resolveAuthorityAddress(wallets, 'stellar:mainnet'),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function resolveZeroGAuthorityProfile(authority) {
|
|
52
|
+
return zeroGAuthorityProfiles[asZeroGAuthority(authority)];
|
|
53
|
+
}
|
|
54
|
+
function isMainnetAuthority(authority) {
|
|
55
|
+
return zeroGAuthorityProfiles[asZeroGAuthority(authority)].networkMode === 'mainnet';
|
|
56
|
+
}
|
|
57
|
+
function asZeroGAuthority(authority) {
|
|
58
|
+
if (!authority.startsWith('0g:')) {
|
|
59
|
+
throw new Error(`Expected a 0G authority, received ${authority}`);
|
|
60
|
+
}
|
|
61
|
+
return authority;
|
|
62
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WalletManager = void 0;
|
|
4
|
+
const stellar_sdk_1 = require("@stellar/stellar-sdk");
|
|
5
|
+
const ethers_1 = require("ethers");
|
|
6
|
+
const workspace_service_1 = require("@halot/cli/shared/workspace/workspace.service");
|
|
7
|
+
class WalletManager {
|
|
8
|
+
workspaceService;
|
|
9
|
+
constructor(workspaceService = new workspace_service_1.WorkspaceService()) {
|
|
10
|
+
this.workspaceService = workspaceService;
|
|
11
|
+
}
|
|
12
|
+
createWallets() {
|
|
13
|
+
const zeroGTestnetWallet = ethers_1.Wallet.createRandom();
|
|
14
|
+
const zeroGMainnetWallet = ethers_1.Wallet.createRandom();
|
|
15
|
+
const stellarTestnetWallet = stellar_sdk_1.Keypair.random();
|
|
16
|
+
const stellarMainnetWallet = stellar_sdk_1.Keypair.random();
|
|
17
|
+
const wallets = {
|
|
18
|
+
authorities: {
|
|
19
|
+
'0g:testnet': {
|
|
20
|
+
privateKey: zeroGTestnetWallet.privateKey,
|
|
21
|
+
},
|
|
22
|
+
'0g:mainnet': {
|
|
23
|
+
privateKey: zeroGMainnetWallet.privateKey,
|
|
24
|
+
},
|
|
25
|
+
'stellar:testnet': {
|
|
26
|
+
privateKey: stellarTestnetWallet.secret(),
|
|
27
|
+
},
|
|
28
|
+
'stellar:mainnet': {
|
|
29
|
+
privateKey: stellarMainnetWallet.secret(),
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
this.workspaceService.writeWallets(wallets);
|
|
34
|
+
this.workspaceService.ensureGitignoreIncludesWallet();
|
|
35
|
+
return wallets;
|
|
36
|
+
}
|
|
37
|
+
getWallets() {
|
|
38
|
+
return this.workspaceService.readWallets();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.WalletManager = WalletManager;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.WorkspaceService = void 0;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const stellar_sdk_1 = require("@stellar/stellar-sdk");
|
|
10
|
+
const ethers_1 = require("ethers");
|
|
11
|
+
const sdk_1 = require("@halot/sdk");
|
|
12
|
+
class WorkspaceService {
|
|
13
|
+
baseDir;
|
|
14
|
+
constructor(baseDir = process.cwd()) {
|
|
15
|
+
this.baseDir = baseDir;
|
|
16
|
+
}
|
|
17
|
+
getPath(fileName) {
|
|
18
|
+
return node_path_1.default.join(this.baseDir, fileName);
|
|
19
|
+
}
|
|
20
|
+
ensureGitignoreIncludesWallet() {
|
|
21
|
+
(0, sdk_1.ensureDirectory)(this.baseDir);
|
|
22
|
+
const gitignorePath = this.getPath('.gitignore');
|
|
23
|
+
const current = node_fs_1.default.existsSync(gitignorePath) ? node_fs_1.default.readFileSync(gitignorePath, 'utf8') : '';
|
|
24
|
+
const entries = ['wallets.json', 'wallet.json', '.halot/'];
|
|
25
|
+
const missing = entries.filter((entry) => !current.includes(entry));
|
|
26
|
+
if (missing.length > 0) {
|
|
27
|
+
const suffix = missing.map((entry) => `${entry}\n`).join('');
|
|
28
|
+
const next = `${current}${current.endsWith('\n') || current.length === 0 ? '' : '\n'}${suffix}`;
|
|
29
|
+
node_fs_1.default.writeFileSync(gitignorePath, next);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
ensureServicesDirectory() {
|
|
33
|
+
const directory = this.getPath('services');
|
|
34
|
+
(0, sdk_1.ensureDirectory)(directory);
|
|
35
|
+
return directory;
|
|
36
|
+
}
|
|
37
|
+
readStreamCursor(key) {
|
|
38
|
+
const state = this.readStreamCursorState();
|
|
39
|
+
return state.cursors[key];
|
|
40
|
+
}
|
|
41
|
+
writeStreamCursor(key, eventId) {
|
|
42
|
+
const state = this.readStreamCursorState();
|
|
43
|
+
state.cursors[key] = eventId;
|
|
44
|
+
(0, sdk_1.writeJsonFile)(this.getStreamCursorPath(), state);
|
|
45
|
+
}
|
|
46
|
+
readProviderConfig() {
|
|
47
|
+
return sdk_1.ProviderConfigSchema.parse((0, sdk_1.readJsonFile)(this.getPath('halot.provider.json')));
|
|
48
|
+
}
|
|
49
|
+
writeProviderConfig(config) {
|
|
50
|
+
(0, sdk_1.writeJsonFile)(this.getPath('halot.provider.json'), sdk_1.ProviderConfigSchema.parse(config));
|
|
51
|
+
}
|
|
52
|
+
readVerifierConfig() {
|
|
53
|
+
return sdk_1.VerifierConfigSchema.parse((0, sdk_1.readJsonFile)(this.getPath('halot.verifier.json')));
|
|
54
|
+
}
|
|
55
|
+
writeVerifierConfig(config) {
|
|
56
|
+
(0, sdk_1.writeJsonFile)(this.getPath('halot.verifier.json'), sdk_1.VerifierConfigSchema.parse(config));
|
|
57
|
+
}
|
|
58
|
+
readRequesterConfig() {
|
|
59
|
+
return sdk_1.RequesterConfigSchema.parse((0, sdk_1.readJsonFile)(this.getPath('halot.requester.json')));
|
|
60
|
+
}
|
|
61
|
+
writeRequesterConfig(config) {
|
|
62
|
+
(0, sdk_1.writeJsonFile)(this.getPath('halot.requester.json'), sdk_1.RequesterConfigSchema.parse(config));
|
|
63
|
+
}
|
|
64
|
+
readWallets(filePath = './wallets.json') {
|
|
65
|
+
const preferredPath = this.getPath(filePath);
|
|
66
|
+
if (node_fs_1.default.existsSync(preferredPath)) {
|
|
67
|
+
return sdk_1.WalletBundleSchema.parse(normalizeWalletBundle((0, sdk_1.readJsonFile)(preferredPath)));
|
|
68
|
+
}
|
|
69
|
+
const legacyPath = this.getPath('wallet.json');
|
|
70
|
+
return sdk_1.WalletBundleSchema.parse(normalizeWalletBundle((0, sdk_1.readJsonFile)(legacyPath)));
|
|
71
|
+
}
|
|
72
|
+
writeWallets(wallets, filePath = './wallets.json') {
|
|
73
|
+
(0, sdk_1.writeJsonFile)(this.getPath(filePath), sdk_1.WalletBundleSchema.parse(wallets));
|
|
74
|
+
}
|
|
75
|
+
readServices() {
|
|
76
|
+
return this.listServiceFiles()
|
|
77
|
+
.map((fileName) => this.readServiceFile(fileName));
|
|
78
|
+
}
|
|
79
|
+
writeService(fileName, service) {
|
|
80
|
+
(0, sdk_1.writeJsonFile)(node_path_1.default.join(this.ensureServicesDirectory(), fileName), sdk_1.ServiceSchema.parse(service));
|
|
81
|
+
}
|
|
82
|
+
readServiceFile(fileName) {
|
|
83
|
+
return sdk_1.ServiceSchema.parse((0, sdk_1.readJsonFile)(node_path_1.default.join(this.ensureServicesDirectory(), fileName)));
|
|
84
|
+
}
|
|
85
|
+
listServiceFiles() {
|
|
86
|
+
const servicesDir = this.ensureServicesDirectory();
|
|
87
|
+
return node_fs_1.default.readdirSync(servicesDir)
|
|
88
|
+
.filter((fileName) => fileName.endsWith('.json'))
|
|
89
|
+
.sort();
|
|
90
|
+
}
|
|
91
|
+
nextServiceDraftFileName() {
|
|
92
|
+
const nextIndex = this.listServiceFiles()
|
|
93
|
+
.map((fileName) => /^service-(\d+)\.json$/.exec(fileName))
|
|
94
|
+
.map((match) => Number(match?.[1] ?? 0))
|
|
95
|
+
.reduce((max, current) => Math.max(max, current), 0) + 1;
|
|
96
|
+
return `service-${String(nextIndex).padStart(3, '0')}.json`;
|
|
97
|
+
}
|
|
98
|
+
removeService(fileName) {
|
|
99
|
+
const filePath = node_path_1.default.join(this.ensureServicesDirectory(), fileName);
|
|
100
|
+
if (node_fs_1.default.existsSync(filePath)) {
|
|
101
|
+
node_fs_1.default.rmSync(filePath);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
replaceServiceFile(currentFileName, nextFileName, service) {
|
|
105
|
+
this.writeService(nextFileName, service);
|
|
106
|
+
if (currentFileName !== nextFileName) {
|
|
107
|
+
this.removeService(currentFileName);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
readModelConfig() {
|
|
111
|
+
return sdk_1.ModelConfigSchema.parse((0, sdk_1.readJsonFile)(this.getPath('model.config.json')));
|
|
112
|
+
}
|
|
113
|
+
writeModelConfig(config) {
|
|
114
|
+
(0, sdk_1.writeJsonFile)(this.getPath('model.config.json'), sdk_1.ModelConfigSchema.parse(config));
|
|
115
|
+
}
|
|
116
|
+
readInferenceTemplate() {
|
|
117
|
+
return sdk_1.InferenceTemplateSchema.parse((0, sdk_1.readJsonFile)(this.getPath('inference.json')));
|
|
118
|
+
}
|
|
119
|
+
writeInferenceTemplate(template) {
|
|
120
|
+
(0, sdk_1.writeJsonFile)(this.getPath('inference.json'), sdk_1.InferenceTemplateSchema.parse(template));
|
|
121
|
+
}
|
|
122
|
+
readSpecializations() {
|
|
123
|
+
return sdk_1.SpecializationsSchema.parse((0, sdk_1.readJsonFile)(this.getPath('specializations.json')));
|
|
124
|
+
}
|
|
125
|
+
writeSpecializations(specializations) {
|
|
126
|
+
(0, sdk_1.writeJsonFile)(this.getPath('specializations.json'), sdk_1.SpecializationsSchema.parse(specializations));
|
|
127
|
+
}
|
|
128
|
+
ensureRuntimeDirectory() {
|
|
129
|
+
const directory = this.getPath('.halot');
|
|
130
|
+
(0, sdk_1.ensureDirectory)(directory);
|
|
131
|
+
return directory;
|
|
132
|
+
}
|
|
133
|
+
getStreamCursorPath() {
|
|
134
|
+
return node_path_1.default.join(this.ensureRuntimeDirectory(), 'stream-cursors.json');
|
|
135
|
+
}
|
|
136
|
+
readStreamCursorState() {
|
|
137
|
+
const statePath = this.getStreamCursorPath();
|
|
138
|
+
if (!node_fs_1.default.existsSync(statePath)) {
|
|
139
|
+
return { cursors: {} };
|
|
140
|
+
}
|
|
141
|
+
return (0, sdk_1.readJsonFile)(statePath);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
exports.WorkspaceService = WorkspaceService;
|
|
145
|
+
function normalizeWalletBundle(input) {
|
|
146
|
+
if (isRecord(input) && isRecord(input.authorities)) {
|
|
147
|
+
return {
|
|
148
|
+
authorities: {
|
|
149
|
+
'0g:testnet': normalizeAuthorityEntry(input.authorities['0g:testnet']),
|
|
150
|
+
'0g:mainnet': normalizeAuthorityEntry(input.authorities['0g:mainnet']),
|
|
151
|
+
'stellar:testnet': normalizeAuthorityEntry(input.authorities['stellar:testnet']),
|
|
152
|
+
'stellar:mainnet': normalizeAuthorityEntry(input.authorities['stellar:mainnet']),
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (isRecord(input) && input.zeroG && input.stellar) {
|
|
157
|
+
const zeroG = normalizeAuthorityEntry(input.zeroG);
|
|
158
|
+
const stellar = normalizeAuthorityEntry(input.stellar);
|
|
159
|
+
return {
|
|
160
|
+
authorities: {
|
|
161
|
+
'0g:testnet': zeroG,
|
|
162
|
+
'0g:mainnet': zeroG,
|
|
163
|
+
'stellar:testnet': stellar,
|
|
164
|
+
'stellar:mainnet': stellar,
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return sdk_1.WalletBundleSchema.parse(input);
|
|
169
|
+
}
|
|
170
|
+
function normalizeAuthorityEntry(input) {
|
|
171
|
+
if (!isRecord(input) || typeof input.privateKey !== 'string' || input.privateKey.length === 0) {
|
|
172
|
+
throw new Error('Invalid wallet authority entry');
|
|
173
|
+
}
|
|
174
|
+
if (typeof input.address === 'string' && input.address.length > 0) {
|
|
175
|
+
if (input.privateKey.startsWith('0x')) {
|
|
176
|
+
const derived = new ethers_1.Wallet(input.privateKey).address;
|
|
177
|
+
if (derived.toLowerCase() !== input.address.toLowerCase()) {
|
|
178
|
+
throw new Error('Wallet address does not match the provided private key');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
const derived = stellar_sdk_1.Keypair.fromSecret(input.privateKey).publicKey();
|
|
183
|
+
if (derived !== input.address) {
|
|
184
|
+
throw new Error('Wallet address does not match the provided private key');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return { privateKey: input.privateKey };
|
|
189
|
+
}
|
|
190
|
+
function isRecord(value) {
|
|
191
|
+
return typeof value === 'object' && value !== null;
|
|
192
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@halot/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Halot protocol CLI",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"halot": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "rm -rf dist && tsc -p tsconfig.json",
|
|
11
|
+
"clean": "rm -rf dist",
|
|
12
|
+
"test": "npm run build && node --test dist/tests/*.test.js",
|
|
13
|
+
"prepack": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"halot",
|
|
17
|
+
"cli"
|
|
18
|
+
],
|
|
19
|
+
"author": "",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"type": "commonjs",
|
|
22
|
+
"files": [
|
|
23
|
+
"dist/features",
|
|
24
|
+
"dist/shared",
|
|
25
|
+
"dist/index.js",
|
|
26
|
+
".env.example",
|
|
27
|
+
"README.md"
|
|
28
|
+
],
|
|
29
|
+
"exports": {
|
|
30
|
+
".": "./dist/index.js",
|
|
31
|
+
"./*": "./dist/*.js"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@halot/sdk": "^1.0.0",
|
|
35
|
+
"@stellar/stellar-sdk": "^15.0.1",
|
|
36
|
+
"@web3-name-sdk/core": "^0.1.18",
|
|
37
|
+
"commander": "^14.0.3",
|
|
38
|
+
"ethers": "6.13.1",
|
|
39
|
+
"inquirer": "^13.3.2",
|
|
40
|
+
"viem": "^2.47.10"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/inquirer": "^9.0.9",
|
|
44
|
+
"@types/node": "^25.5.2",
|
|
45
|
+
"typescript": "^6.0.2"
|
|
46
|
+
}
|
|
47
|
+
}
|