@attestify/cli 0.1.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 +81 -0
- package/dist/index.js +1184 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1184 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/index.ts
|
|
27
|
+
var import_commander = require("commander");
|
|
28
|
+
var import_fs = require("fs");
|
|
29
|
+
|
|
30
|
+
// src/config.ts
|
|
31
|
+
var import_dotenv = require("dotenv");
|
|
32
|
+
var import_sdk = require("@attestify/sdk");
|
|
33
|
+
(0, import_dotenv.config)();
|
|
34
|
+
function loadConfig() {
|
|
35
|
+
const accountId = process.env.HEDERA_ACCOUNT_ID;
|
|
36
|
+
const privateKey = process.env.HEDERA_PRIVATE_KEY;
|
|
37
|
+
if (!accountId) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
"Missing HEDERA_ACCOUNT_ID environment variable. Set it in your environment or in a .env file."
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
if (!privateKey) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
"Missing HEDERA_PRIVATE_KEY environment variable. Set it in your environment or in a .env file."
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
const hcsTopicSchemas = process.env.HCS_TOPIC_SCHEMAS;
|
|
48
|
+
const hcsTopicAttestations = process.env.HCS_TOPIC_ATTESTATIONS;
|
|
49
|
+
const hcsTopicAuthorities = process.env.HCS_TOPIC_AUTHORITIES;
|
|
50
|
+
const hcsTopicId = process.env.HCS_TOPIC_ID;
|
|
51
|
+
const hcsTopicIds = hcsTopicSchemas || hcsTopicAttestations || hcsTopicAuthorities ? {
|
|
52
|
+
schemas: hcsTopicSchemas,
|
|
53
|
+
attestations: hcsTopicAttestations,
|
|
54
|
+
authorities: hcsTopicAuthorities
|
|
55
|
+
} : void 0;
|
|
56
|
+
return {
|
|
57
|
+
...import_sdk.DEFAULT_CONFIG,
|
|
58
|
+
operatorAccountId: accountId,
|
|
59
|
+
operatorPrivateKey: privateKey,
|
|
60
|
+
indexerUrl: process.env.INDEXER_URL || void 0,
|
|
61
|
+
resolverAddresses: import_sdk.TESTNET_RESOLVER_ADDRESSES,
|
|
62
|
+
...hcsTopicIds ? { hcsTopicIds } : {},
|
|
63
|
+
...hcsTopicId && !hcsTopicIds ? { hcsTopicId } : {}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/output.ts
|
|
68
|
+
function formatOutput(data, json) {
|
|
69
|
+
if (json) {
|
|
70
|
+
return JSON.stringify({ success: true, data }, null, 2);
|
|
71
|
+
}
|
|
72
|
+
const lines = [];
|
|
73
|
+
for (const [key, value] of Object.entries(data)) {
|
|
74
|
+
if (typeof value === "object" && value !== null) {
|
|
75
|
+
lines.push(`${key}: ${JSON.stringify(value)}`);
|
|
76
|
+
} else {
|
|
77
|
+
lines.push(`${key}: ${value}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return lines.join("\n");
|
|
81
|
+
}
|
|
82
|
+
function formatError(type, message, json) {
|
|
83
|
+
if (json) {
|
|
84
|
+
return JSON.stringify({ success: false, error: { type, message } }, null, 2);
|
|
85
|
+
}
|
|
86
|
+
return `Error [${type}]: ${message}`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/index.ts
|
|
90
|
+
async function createService() {
|
|
91
|
+
const config = loadConfig();
|
|
92
|
+
const { HederaAttestService } = await import("@attestify/sdk");
|
|
93
|
+
return new HederaAttestService(config);
|
|
94
|
+
}
|
|
95
|
+
function readJsonFile(filePath) {
|
|
96
|
+
return JSON.parse((0, import_fs.readFileSync)(filePath, "utf-8"));
|
|
97
|
+
}
|
|
98
|
+
var program = new import_commander.Command();
|
|
99
|
+
program.name("attestify").description("Attestify CLI \u2014 interact with the Hedera attestation protocol").version("0.1.0").option("--json", "Output results as JSON");
|
|
100
|
+
var schema = program.command("schema").description("Manage attestation schemas");
|
|
101
|
+
schema.command("create").description("Register a new schema").option("--definition <definition>", "Schema definition string").option("--revocable", "Whether attestations can be revoked", false).option("--resolver <resolver>", "Resolver contract address").option("--file <file>", "Path to JSON file with schema parameters").action(async (opts) => {
|
|
102
|
+
const jsonFlag = program.opts().json;
|
|
103
|
+
try {
|
|
104
|
+
let definition;
|
|
105
|
+
let revocable;
|
|
106
|
+
let resolver;
|
|
107
|
+
if (opts.file) {
|
|
108
|
+
const d = readJsonFile(opts.file);
|
|
109
|
+
definition = d.definition;
|
|
110
|
+
revocable = d.revocable ?? false;
|
|
111
|
+
resolver = d.resolver;
|
|
112
|
+
} else {
|
|
113
|
+
if (!opts.definition) throw new Error("Either --definition or --file is required");
|
|
114
|
+
definition = opts.definition;
|
|
115
|
+
revocable = opts.revocable;
|
|
116
|
+
resolver = opts.resolver;
|
|
117
|
+
}
|
|
118
|
+
const service = await createService();
|
|
119
|
+
const result = await service.registerSchema({ definition, revocable, resolver });
|
|
120
|
+
if (result.success) {
|
|
121
|
+
console.log(formatOutput({ schemaUid: result.data.schemaUid }, jsonFlag));
|
|
122
|
+
} else {
|
|
123
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
124
|
+
process.exitCode = 1;
|
|
125
|
+
}
|
|
126
|
+
} catch (err) {
|
|
127
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
128
|
+
process.exitCode = 1;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
schema.command("fetch").description("Get schema by UID").requiredOption("--uid <uid>", "Schema UID to fetch").action(async (opts) => {
|
|
132
|
+
const jsonFlag = program.opts().json;
|
|
133
|
+
try {
|
|
134
|
+
const service = await createService();
|
|
135
|
+
const result = await service.getSchema(opts.uid);
|
|
136
|
+
if (result.success) {
|
|
137
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
138
|
+
} else {
|
|
139
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
140
|
+
process.exitCode = 1;
|
|
141
|
+
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
144
|
+
process.exitCode = 1;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
schema.command("list").description("List schemas (optionally filter by authority address)").option("--authority <address>", "Filter by authority address").option("--limit <limit>", "Max results", "25").action(async (opts) => {
|
|
148
|
+
const jsonFlag = program.opts().json;
|
|
149
|
+
try {
|
|
150
|
+
const service = await createService();
|
|
151
|
+
const result = await service.listSchemas({
|
|
152
|
+
authority: opts.authority,
|
|
153
|
+
limit: parseInt(opts.limit, 10) || 25
|
|
154
|
+
});
|
|
155
|
+
if (result.success) {
|
|
156
|
+
const schemas = result.data;
|
|
157
|
+
if (jsonFlag) {
|
|
158
|
+
console.log(JSON.stringify({ success: true, count: schemas.length, data: schemas }, null, 2));
|
|
159
|
+
} else {
|
|
160
|
+
console.log(`Found ${schemas.length} schema(s)
|
|
161
|
+
`);
|
|
162
|
+
for (const s of schemas) {
|
|
163
|
+
console.log(` UID: ${s.uid}`);
|
|
164
|
+
console.log(` Definition: ${s.definition}`);
|
|
165
|
+
console.log(` Authority: ${s.authorityAddress}`);
|
|
166
|
+
console.log(` Revocable: ${s.revocable}`);
|
|
167
|
+
console.log(` HCS Topic: ${s.hcsTopicId || "N/A"}`);
|
|
168
|
+
console.log(` Created: ${s.createdAt}`);
|
|
169
|
+
console.log("");
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
174
|
+
process.exitCode = 1;
|
|
175
|
+
}
|
|
176
|
+
} catch (err) {
|
|
177
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
178
|
+
process.exitCode = 1;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
var attestation = program.command("attestation").description("Manage attestations");
|
|
182
|
+
attestation.command("create").description("Create a new attestation").requiredOption("--schema-uid <uid>", "Schema UID to attest against").requiredOption("--subject <address>", "Subject address").requiredOption("--data <data>", "ABI-encoded attestation data (hex)").option("--expiration <timestamp>", "Expiration timestamp (0 = no expiration)").option("--file <file>", "Path to JSON file with attestation parameters").action(async (opts) => {
|
|
183
|
+
const jsonFlag = program.opts().json;
|
|
184
|
+
try {
|
|
185
|
+
let schemaUid;
|
|
186
|
+
let subject;
|
|
187
|
+
let data;
|
|
188
|
+
let expirationTime;
|
|
189
|
+
if (opts.file) {
|
|
190
|
+
const d = readJsonFile(opts.file);
|
|
191
|
+
schemaUid = d.schemaUid;
|
|
192
|
+
subject = d.subject;
|
|
193
|
+
data = d.data;
|
|
194
|
+
expirationTime = d.expirationTime;
|
|
195
|
+
} else {
|
|
196
|
+
schemaUid = opts.schemaUid;
|
|
197
|
+
subject = opts.subject;
|
|
198
|
+
data = opts.data;
|
|
199
|
+
expirationTime = opts.expiration ? parseInt(opts.expiration, 10) : void 0;
|
|
200
|
+
}
|
|
201
|
+
const service = await createService();
|
|
202
|
+
const result = await service.createAttestation({ schemaUid, subject, data, expirationTime });
|
|
203
|
+
if (result.success) {
|
|
204
|
+
console.log(formatOutput({ attestationUid: result.data.attestationUid }, jsonFlag));
|
|
205
|
+
} else {
|
|
206
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
207
|
+
process.exitCode = 1;
|
|
208
|
+
}
|
|
209
|
+
} catch (err) {
|
|
210
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
211
|
+
process.exitCode = 1;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
attestation.command("fetch").description("Get attestation by UID").requiredOption("--uid <uid>", "Attestation UID to fetch").action(async (opts) => {
|
|
215
|
+
const jsonFlag = program.opts().json;
|
|
216
|
+
try {
|
|
217
|
+
const service = await createService();
|
|
218
|
+
const result = await service.getAttestation(opts.uid);
|
|
219
|
+
if (result.success) {
|
|
220
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
221
|
+
} else {
|
|
222
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
223
|
+
process.exitCode = 1;
|
|
224
|
+
}
|
|
225
|
+
} catch (err) {
|
|
226
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
227
|
+
process.exitCode = 1;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
attestation.command("list").description("List attestations (filter by attester, subject, or schema)").option("--attester <address>", "Filter by attester address").option("--subject <address>", "Filter by subject address").option("--schema-uid <uid>", "Filter by schema UID").option("--limit <limit>", "Max results", "25").action(async (opts) => {
|
|
231
|
+
const jsonFlag = program.opts().json;
|
|
232
|
+
try {
|
|
233
|
+
const service = await createService();
|
|
234
|
+
const result = await service.listAttestations({
|
|
235
|
+
attester: opts.attester,
|
|
236
|
+
subject: opts.subject,
|
|
237
|
+
schemaUid: opts.schemaUid,
|
|
238
|
+
limit: parseInt(opts.limit, 10) || 25
|
|
239
|
+
});
|
|
240
|
+
if (result.success) {
|
|
241
|
+
const attestations = result.data;
|
|
242
|
+
if (jsonFlag) {
|
|
243
|
+
console.log(JSON.stringify({ success: true, count: attestations.length, data: attestations }, null, 2));
|
|
244
|
+
} else {
|
|
245
|
+
console.log(`Found ${attestations.length} attestation(s)
|
|
246
|
+
`);
|
|
247
|
+
for (const a of attestations) {
|
|
248
|
+
const status = a.revoked ? "Revoked" : a.expirationTime && new Date(a.expirationTime) < /* @__PURE__ */ new Date() ? "Expired" : "Active";
|
|
249
|
+
console.log(` UID: ${a.uid}`);
|
|
250
|
+
console.log(` Schema: ${a.schemaUid}`);
|
|
251
|
+
console.log(` Attester: ${a.attesterAddress}`);
|
|
252
|
+
console.log(` Subject: ${a.subjectAddress}`);
|
|
253
|
+
console.log(` Status: ${status}`);
|
|
254
|
+
console.log(` Created: ${a.createdAt}`);
|
|
255
|
+
console.log("");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
260
|
+
process.exitCode = 1;
|
|
261
|
+
}
|
|
262
|
+
} catch (err) {
|
|
263
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
264
|
+
process.exitCode = 1;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
attestation.command("revoke").description("Revoke an attestation").requiredOption("--uid <uid>", "Attestation UID to revoke").action(async (opts) => {
|
|
268
|
+
const jsonFlag = program.opts().json;
|
|
269
|
+
try {
|
|
270
|
+
const service = await createService();
|
|
271
|
+
const result = await service.revokeAttestation(opts.uid);
|
|
272
|
+
if (result.success) {
|
|
273
|
+
console.log(formatOutput({ revoked: true, uid: opts.uid }, jsonFlag));
|
|
274
|
+
} else {
|
|
275
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
276
|
+
process.exitCode = 1;
|
|
277
|
+
}
|
|
278
|
+
} catch (err) {
|
|
279
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
280
|
+
process.exitCode = 1;
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
var authority = program.command("authority").description("Manage authorities");
|
|
284
|
+
authority.command("register").description("Register as an authority").requiredOption("--metadata <metadata>", "Authority metadata string").action(async (opts) => {
|
|
285
|
+
const jsonFlag = program.opts().json;
|
|
286
|
+
try {
|
|
287
|
+
const service = await createService();
|
|
288
|
+
const result = await service.registerAuthority(opts.metadata);
|
|
289
|
+
if (result.success) {
|
|
290
|
+
console.log(formatOutput({ registered: true }, jsonFlag));
|
|
291
|
+
} else {
|
|
292
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
293
|
+
process.exitCode = 1;
|
|
294
|
+
}
|
|
295
|
+
} catch (err) {
|
|
296
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
297
|
+
process.exitCode = 1;
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
authority.command("fetch").description("Get authority info by address").requiredOption("--address <address>", "Authority address to fetch").action(async (opts) => {
|
|
301
|
+
const jsonFlag = program.opts().json;
|
|
302
|
+
try {
|
|
303
|
+
const service = await createService();
|
|
304
|
+
const result = await service.getAuthority(opts.address);
|
|
305
|
+
if (result.success) {
|
|
306
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
307
|
+
} else {
|
|
308
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
309
|
+
process.exitCode = 1;
|
|
310
|
+
}
|
|
311
|
+
} catch (err) {
|
|
312
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
313
|
+
process.exitCode = 1;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
authority.command("verify").description("Verify or unverify an authority (admin only \u2014 contract owner)").requiredOption("--address <address>", "Authority address to verify/unverify").option("--revoke", "Unverify the authority instead of verifying", false).action(async (opts) => {
|
|
317
|
+
const jsonFlag = program.opts().json;
|
|
318
|
+
try {
|
|
319
|
+
const service = await createService();
|
|
320
|
+
const verified = !opts.revoke;
|
|
321
|
+
const result = await service.setAuthorityVerification(opts.address, verified);
|
|
322
|
+
if (result.success) {
|
|
323
|
+
console.log(formatOutput({ address: opts.address, verified }, jsonFlag));
|
|
324
|
+
} else {
|
|
325
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
326
|
+
process.exitCode = 1;
|
|
327
|
+
}
|
|
328
|
+
} catch (err) {
|
|
329
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
330
|
+
process.exitCode = 1;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
program.command("profile").description("View full profile for an address (authority, schemas, attestations)").requiredOption("--address <address>", "Wallet address to look up").action(async (opts) => {
|
|
334
|
+
const jsonFlag = program.opts().json;
|
|
335
|
+
try {
|
|
336
|
+
const service = await createService();
|
|
337
|
+
const result = await service.getProfile(opts.address);
|
|
338
|
+
if (result.success) {
|
|
339
|
+
const p = result.data;
|
|
340
|
+
if (jsonFlag) {
|
|
341
|
+
console.log(JSON.stringify({ success: true, data: p }, null, 2));
|
|
342
|
+
} else {
|
|
343
|
+
console.log(`Profile: ${p.address}
|
|
344
|
+
`);
|
|
345
|
+
if (p.authority) {
|
|
346
|
+
console.log("\u2500\u2500 Authority \u2500\u2500");
|
|
347
|
+
console.log(` Status: ${p.authority.isVerified ? "Verified \u2713" : "Unverified"}`);
|
|
348
|
+
console.log(` Metadata: ${p.authority.metadata || "\u2014"}`);
|
|
349
|
+
console.log(` Since: ${p.authority.createdAt}`);
|
|
350
|
+
console.log("");
|
|
351
|
+
} else {
|
|
352
|
+
console.log("\u2500\u2500 Authority \u2500\u2500");
|
|
353
|
+
console.log(" Not registered as an authority\n");
|
|
354
|
+
}
|
|
355
|
+
console.log(`\u2500\u2500 Schemas (${p.schemas.length}) \u2500\u2500`);
|
|
356
|
+
if (p.schemas.length === 0) {
|
|
357
|
+
console.log(" No schemas created\n");
|
|
358
|
+
} else {
|
|
359
|
+
for (const s of p.schemas) {
|
|
360
|
+
console.log(` ${s.uid}`);
|
|
361
|
+
console.log(` ${s.definition}`);
|
|
362
|
+
console.log(` Revocable: ${s.revocable} | HCS: ${s.hcsTopicId || "N/A"} | ${s.createdAt}`);
|
|
363
|
+
}
|
|
364
|
+
console.log("");
|
|
365
|
+
}
|
|
366
|
+
console.log(`\u2500\u2500 Attestations Issued (${p.attestationsIssued.length}) \u2500\u2500`);
|
|
367
|
+
if (p.attestationsIssued.length === 0) {
|
|
368
|
+
console.log(" No attestations issued\n");
|
|
369
|
+
} else {
|
|
370
|
+
for (const a of p.attestationsIssued) {
|
|
371
|
+
console.log(` ${a.uid}`);
|
|
372
|
+
console.log(` Subject: ${a.subjectAddress} | ${a.revoked ? "Revoked" : "Active"} | ${a.createdAt}`);
|
|
373
|
+
}
|
|
374
|
+
console.log("");
|
|
375
|
+
}
|
|
376
|
+
console.log(`\u2500\u2500 Attestations Received (${p.attestationsReceived.length}) \u2500\u2500`);
|
|
377
|
+
if (p.attestationsReceived.length === 0) {
|
|
378
|
+
console.log(" No attestations about this address\n");
|
|
379
|
+
} else {
|
|
380
|
+
for (const a of p.attestationsReceived) {
|
|
381
|
+
console.log(` ${a.uid}`);
|
|
382
|
+
console.log(` Attester: ${a.attesterAddress} | ${a.revoked ? "Revoked" : "Active"} | ${a.createdAt}`);
|
|
383
|
+
}
|
|
384
|
+
console.log("");
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
} else {
|
|
388
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
389
|
+
process.exitCode = 1;
|
|
390
|
+
}
|
|
391
|
+
} catch (err) {
|
|
392
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
393
|
+
process.exitCode = 1;
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
var hcs = program.command("hcs").description("HCS audit log operations");
|
|
397
|
+
hcs.command("topics").description("List configured HCS topic IDs").action(async () => {
|
|
398
|
+
const jsonFlag = program.opts().json;
|
|
399
|
+
try {
|
|
400
|
+
const config = loadConfig();
|
|
401
|
+
const topics = {};
|
|
402
|
+
if (config.hcsTopicIds?.schemas) topics.schemas = config.hcsTopicIds.schemas;
|
|
403
|
+
if (config.hcsTopicIds?.attestations) topics.attestations = config.hcsTopicIds.attestations;
|
|
404
|
+
if (config.hcsTopicIds?.authorities) topics.authorities = config.hcsTopicIds.authorities;
|
|
405
|
+
if (config.hcsTopicId && Object.keys(topics).length === 0) topics.default = config.hcsTopicId;
|
|
406
|
+
if (Object.keys(topics).length === 0) {
|
|
407
|
+
console.log(formatError("CONFIGURATION_ERROR", "No HCS topics configured. Set HCS_TOPIC_SCHEMAS, HCS_TOPIC_ATTESTATIONS, HCS_TOPIC_AUTHORITIES env vars.", jsonFlag));
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
const data = {};
|
|
411
|
+
for (const [name, id] of Object.entries(topics)) {
|
|
412
|
+
data[name] = { topicId: id, hashscanUrl: `https://hashscan.io/testnet/topic/${id}` };
|
|
413
|
+
}
|
|
414
|
+
console.log(formatOutput(data, jsonFlag));
|
|
415
|
+
} catch (err) {
|
|
416
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
417
|
+
process.exitCode = 1;
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
hcs.command("messages").description("Fetch HCS audit messages from a topic").requiredOption("--topic <topicId>", "HCS topic ID (e.g. 0.0.12345)").option("--limit <limit>", "Number of messages to fetch", "25").option("--order <order>", "Sort order: asc or desc", "desc").action(async (opts) => {
|
|
421
|
+
const jsonFlag = program.opts().json;
|
|
422
|
+
try {
|
|
423
|
+
const limit = Math.min(parseInt(opts.limit, 10) || 25, 100);
|
|
424
|
+
const order = opts.order === "asc" ? "asc" : "desc";
|
|
425
|
+
const mirrorUrl = "https://testnet.mirrornode.hedera.com";
|
|
426
|
+
const url = `${mirrorUrl}/api/v1/topics/${opts.topic}/messages?limit=${limit}&order=${order}`;
|
|
427
|
+
const response = await fetch(url);
|
|
428
|
+
if (!response.ok) {
|
|
429
|
+
console.error(formatError("NETWORK_ERROR", `Mirror node returned ${response.status}`, jsonFlag));
|
|
430
|
+
process.exitCode = 1;
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const raw = await response.json();
|
|
434
|
+
const messages = (raw.messages || []).map((msg) => {
|
|
435
|
+
let decoded = null;
|
|
436
|
+
try {
|
|
437
|
+
const buf = Buffer.from(msg.message, "base64");
|
|
438
|
+
decoded = JSON.parse(buf.toString("utf-8"));
|
|
439
|
+
} catch {
|
|
440
|
+
decoded = msg.message;
|
|
441
|
+
}
|
|
442
|
+
return {
|
|
443
|
+
sequenceNumber: msg.sequence_number,
|
|
444
|
+
consensusTimestamp: msg.consensus_timestamp,
|
|
445
|
+
payer: msg.payer_account_id,
|
|
446
|
+
content: decoded
|
|
447
|
+
};
|
|
448
|
+
});
|
|
449
|
+
const data = {
|
|
450
|
+
topicId: opts.topic,
|
|
451
|
+
hashscanUrl: `https://hashscan.io/testnet/topic/${opts.topic}`,
|
|
452
|
+
messageCount: messages.length,
|
|
453
|
+
messages
|
|
454
|
+
};
|
|
455
|
+
console.log(formatOutput(data, jsonFlag));
|
|
456
|
+
} catch (err) {
|
|
457
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
458
|
+
process.exitCode = 1;
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
var whitelist = program.command("whitelist").description("WhitelistResolver operations");
|
|
462
|
+
whitelist.command("add").description("Add an address to the whitelist (admin only)").requiredOption("--account <address>", "Address to whitelist").action(async (opts) => {
|
|
463
|
+
const jsonFlag = program.opts().json;
|
|
464
|
+
try {
|
|
465
|
+
const service = await createService();
|
|
466
|
+
const result = await service.whitelistAdd(opts.account);
|
|
467
|
+
if (result.success) {
|
|
468
|
+
console.log(formatOutput({ added: true, account: opts.account }, jsonFlag));
|
|
469
|
+
} else {
|
|
470
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
471
|
+
process.exitCode = 1;
|
|
472
|
+
}
|
|
473
|
+
} catch (err) {
|
|
474
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
475
|
+
process.exitCode = 1;
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
whitelist.command("remove").description("Remove an address from the whitelist (admin only)").requiredOption("--account <address>", "Address to remove").action(async (opts) => {
|
|
479
|
+
const jsonFlag = program.opts().json;
|
|
480
|
+
try {
|
|
481
|
+
const service = await createService();
|
|
482
|
+
const result = await service.whitelistRemove(opts.account);
|
|
483
|
+
if (result.success) {
|
|
484
|
+
console.log(formatOutput({ removed: true, account: opts.account }, jsonFlag));
|
|
485
|
+
} else {
|
|
486
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
487
|
+
process.exitCode = 1;
|
|
488
|
+
}
|
|
489
|
+
} catch (err) {
|
|
490
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
491
|
+
process.exitCode = 1;
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
whitelist.command("check").description("Check if an address is whitelisted").requiredOption("--account <address>", "Address to check").action(async (opts) => {
|
|
495
|
+
const jsonFlag = program.opts().json;
|
|
496
|
+
try {
|
|
497
|
+
const service = await createService();
|
|
498
|
+
const result = await service.whitelistCheck(opts.account);
|
|
499
|
+
if (result.success) {
|
|
500
|
+
console.log(formatOutput({ account: opts.account, whitelisted: result.data.whitelisted }, jsonFlag));
|
|
501
|
+
} else {
|
|
502
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
503
|
+
process.exitCode = 1;
|
|
504
|
+
}
|
|
505
|
+
} catch (err) {
|
|
506
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
507
|
+
process.exitCode = 1;
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
whitelist.command("owner").description("Get the whitelist resolver owner address").action(async () => {
|
|
511
|
+
const jsonFlag = program.opts().json;
|
|
512
|
+
try {
|
|
513
|
+
const service = await createService();
|
|
514
|
+
const result = await service.whitelistOwner();
|
|
515
|
+
if (result.success) {
|
|
516
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
517
|
+
} else {
|
|
518
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
519
|
+
process.exitCode = 1;
|
|
520
|
+
}
|
|
521
|
+
} catch (err) {
|
|
522
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
523
|
+
process.exitCode = 1;
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
var fee = program.command("fee").description("FeeResolver operations");
|
|
527
|
+
fee.command("deposit").description("Deposit HBAR into the fee resolver").requiredOption("--amount <hbar>", "Amount of HBAR to deposit").action(async (opts) => {
|
|
528
|
+
const jsonFlag = program.opts().json;
|
|
529
|
+
try {
|
|
530
|
+
const service = await createService();
|
|
531
|
+
const result = await service.feeDeposit(opts.amount);
|
|
532
|
+
if (result.success) {
|
|
533
|
+
console.log(formatOutput({ deposited: true, amount: opts.amount }, jsonFlag));
|
|
534
|
+
} else {
|
|
535
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
536
|
+
process.exitCode = 1;
|
|
537
|
+
}
|
|
538
|
+
} catch (err) {
|
|
539
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
540
|
+
process.exitCode = 1;
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
fee.command("set-fee").description("Set the attestation fee amount (admin only)").requiredOption("--amount <wei>", "Fee amount in wei (tinybar)").action(async (opts) => {
|
|
544
|
+
const jsonFlag = program.opts().json;
|
|
545
|
+
try {
|
|
546
|
+
const service = await createService();
|
|
547
|
+
const result = await service.feeSetFee(opts.amount);
|
|
548
|
+
if (result.success) {
|
|
549
|
+
console.log(formatOutput({ feeSet: true, amount: opts.amount }, jsonFlag));
|
|
550
|
+
} else {
|
|
551
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
552
|
+
process.exitCode = 1;
|
|
553
|
+
}
|
|
554
|
+
} catch (err) {
|
|
555
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
556
|
+
process.exitCode = 1;
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
fee.command("withdraw").description("Withdraw collected fees (admin only)").action(async () => {
|
|
560
|
+
const jsonFlag = program.opts().json;
|
|
561
|
+
try {
|
|
562
|
+
const service = await createService();
|
|
563
|
+
const result = await service.feeWithdraw();
|
|
564
|
+
if (result.success) {
|
|
565
|
+
console.log(formatOutput({ withdrawn: true }, jsonFlag));
|
|
566
|
+
} else {
|
|
567
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
568
|
+
process.exitCode = 1;
|
|
569
|
+
}
|
|
570
|
+
} catch (err) {
|
|
571
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
572
|
+
process.exitCode = 1;
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
fee.command("get-fee").description("Get the current attestation fee").action(async () => {
|
|
576
|
+
const jsonFlag = program.opts().json;
|
|
577
|
+
try {
|
|
578
|
+
const service = await createService();
|
|
579
|
+
const result = await service.feeGetFee();
|
|
580
|
+
if (result.success) {
|
|
581
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
582
|
+
} else {
|
|
583
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
584
|
+
process.exitCode = 1;
|
|
585
|
+
}
|
|
586
|
+
} catch (err) {
|
|
587
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
588
|
+
process.exitCode = 1;
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
fee.command("balance").description("Check deposited balance for an address").requiredOption("--account <address>", "Address to check").action(async (opts) => {
|
|
592
|
+
const jsonFlag = program.opts().json;
|
|
593
|
+
try {
|
|
594
|
+
const service = await createService();
|
|
595
|
+
const result = await service.feeGetBalance(opts.account);
|
|
596
|
+
if (result.success) {
|
|
597
|
+
console.log(formatOutput({ account: opts.account, ...result.data }, jsonFlag));
|
|
598
|
+
} else {
|
|
599
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
600
|
+
process.exitCode = 1;
|
|
601
|
+
}
|
|
602
|
+
} catch (err) {
|
|
603
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
604
|
+
process.exitCode = 1;
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
fee.command("owner").description("Get the fee resolver owner address").action(async () => {
|
|
608
|
+
const jsonFlag = program.opts().json;
|
|
609
|
+
try {
|
|
610
|
+
const service = await createService();
|
|
611
|
+
const result = await service.feeOwner();
|
|
612
|
+
if (result.success) {
|
|
613
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
614
|
+
} else {
|
|
615
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
616
|
+
process.exitCode = 1;
|
|
617
|
+
}
|
|
618
|
+
} catch (err) {
|
|
619
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
620
|
+
process.exitCode = 1;
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
var tokenGated = program.command("token-gated").description("TokenGatedResolver operations");
|
|
624
|
+
tokenGated.command("set-config").description("Set token address and minimum balance (admin only)").requiredOption("--token <address>", "HTS token address").requiredOption("--min-balance <amount>", "Minimum token balance required").action(async (opts) => {
|
|
625
|
+
const jsonFlag = program.opts().json;
|
|
626
|
+
try {
|
|
627
|
+
const service = await createService();
|
|
628
|
+
const result = await service.tokenGatedSetConfig(opts.token, opts.minBalance);
|
|
629
|
+
if (result.success) {
|
|
630
|
+
console.log(formatOutput({ configured: true, token: opts.token, minBalance: opts.minBalance }, jsonFlag));
|
|
631
|
+
} else {
|
|
632
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
633
|
+
process.exitCode = 1;
|
|
634
|
+
}
|
|
635
|
+
} catch (err) {
|
|
636
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
637
|
+
process.exitCode = 1;
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
tokenGated.command("get-config").description("Get current token gate configuration").action(async () => {
|
|
641
|
+
const jsonFlag = program.opts().json;
|
|
642
|
+
try {
|
|
643
|
+
const service = await createService();
|
|
644
|
+
const result = await service.tokenGatedGetConfig();
|
|
645
|
+
if (result.success) {
|
|
646
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
647
|
+
} else {
|
|
648
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
649
|
+
process.exitCode = 1;
|
|
650
|
+
}
|
|
651
|
+
} catch (err) {
|
|
652
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
653
|
+
process.exitCode = 1;
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
tokenGated.command("owner").description("Get the token gated resolver owner address").action(async () => {
|
|
657
|
+
const jsonFlag = program.opts().json;
|
|
658
|
+
try {
|
|
659
|
+
const service = await createService();
|
|
660
|
+
const result = await service.tokenGatedOwner();
|
|
661
|
+
if (result.success) {
|
|
662
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
663
|
+
} else {
|
|
664
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
665
|
+
process.exitCode = 1;
|
|
666
|
+
}
|
|
667
|
+
} catch (err) {
|
|
668
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
669
|
+
process.exitCode = 1;
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
program.command("nft-mint").description("Mint an HTS NFT credential for an attestation").requiredOption("--subject <address>", "Subject address to receive the NFT").requiredOption("--attestation-uid <uid>", "Attestation UID to embed in metadata").requiredOption("--token-id <tokenId>", "HTS token ID for the NFT collection").action(async (opts) => {
|
|
673
|
+
const jsonFlag = program.opts().json;
|
|
674
|
+
try {
|
|
675
|
+
const service = await createService();
|
|
676
|
+
const result = await service.mintNFT({
|
|
677
|
+
subject: opts.subject,
|
|
678
|
+
attestationUid: opts.attestationUid,
|
|
679
|
+
tokenId: opts.tokenId
|
|
680
|
+
});
|
|
681
|
+
if (result.success) {
|
|
682
|
+
console.log(formatOutput({ minted: true, serialNumber: result.data.serialNumber }, jsonFlag));
|
|
683
|
+
} else {
|
|
684
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
685
|
+
process.exitCode = 1;
|
|
686
|
+
}
|
|
687
|
+
} catch (err) {
|
|
688
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
689
|
+
process.exitCode = 1;
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
var delegate = program.command("delegate").description("Delegation operations");
|
|
693
|
+
delegate.command("add").description("Add a delegate who can attest/revoke on your behalf").requiredOption("--address <address>", "Delegate address to authorize").action(async (opts) => {
|
|
694
|
+
const jsonFlag = program.opts().json;
|
|
695
|
+
try {
|
|
696
|
+
const service = await createService();
|
|
697
|
+
const result = await service.addDelegate(opts.address);
|
|
698
|
+
if (result.success) {
|
|
699
|
+
console.log(formatOutput({ added: true, delegate: opts.address }, jsonFlag));
|
|
700
|
+
} else {
|
|
701
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
702
|
+
process.exitCode = 1;
|
|
703
|
+
}
|
|
704
|
+
} catch (err) {
|
|
705
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
706
|
+
process.exitCode = 1;
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
delegate.command("remove").description("Remove a delegate").requiredOption("--address <address>", "Delegate address to remove").action(async (opts) => {
|
|
710
|
+
const jsonFlag = program.opts().json;
|
|
711
|
+
try {
|
|
712
|
+
const service = await createService();
|
|
713
|
+
const result = await service.removeDelegate(opts.address);
|
|
714
|
+
if (result.success) {
|
|
715
|
+
console.log(formatOutput({ removed: true, delegate: opts.address }, jsonFlag));
|
|
716
|
+
} else {
|
|
717
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
718
|
+
process.exitCode = 1;
|
|
719
|
+
}
|
|
720
|
+
} catch (err) {
|
|
721
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
722
|
+
process.exitCode = 1;
|
|
723
|
+
}
|
|
724
|
+
});
|
|
725
|
+
delegate.command("check").description("Check if an address is a delegate of an authority").requiredOption("--authority <address>", "Authority address").requiredOption("--delegate <address>", "Delegate address to check").action(async (opts) => {
|
|
726
|
+
const jsonFlag = program.opts().json;
|
|
727
|
+
try {
|
|
728
|
+
const service = await createService();
|
|
729
|
+
const result = await service.isDelegate(opts.authority, opts.delegate);
|
|
730
|
+
if (result.success) {
|
|
731
|
+
console.log(formatOutput({ authority: opts.authority, delegate: opts.delegate, isDelegate: result.data.isDelegate }, jsonFlag));
|
|
732
|
+
} else {
|
|
733
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
734
|
+
process.exitCode = 1;
|
|
735
|
+
}
|
|
736
|
+
} catch (err) {
|
|
737
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
738
|
+
process.exitCode = 1;
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
delegate.command("list").description("List all delegates for an authority").requiredOption("--authority <address>", "Authority address").action(async (opts) => {
|
|
742
|
+
const jsonFlag = program.opts().json;
|
|
743
|
+
try {
|
|
744
|
+
const service = await createService();
|
|
745
|
+
const result = await service.getDelegates(opts.authority);
|
|
746
|
+
if (result.success) {
|
|
747
|
+
if (jsonFlag) {
|
|
748
|
+
console.log(JSON.stringify({ success: true, data: result.data.delegates }, null, 2));
|
|
749
|
+
} else {
|
|
750
|
+
const delegates = result.data.delegates;
|
|
751
|
+
console.log(`Delegates for ${opts.authority}: ${delegates.length}
|
|
752
|
+
`);
|
|
753
|
+
for (const d of delegates) {
|
|
754
|
+
console.log(` ${d}`);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
} else {
|
|
758
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
759
|
+
process.exitCode = 1;
|
|
760
|
+
}
|
|
761
|
+
} catch (err) {
|
|
762
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
763
|
+
process.exitCode = 1;
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
delegate.command("attest").description("Create an attestation on behalf of an authority (delegated)").requiredOption("--authority <address>", "Authority address you are delegating for").requiredOption("--schema-uid <uid>", "Schema UID").requiredOption("--subject <address>", "Subject address").requiredOption("--data <data>", "ABI-encoded attestation data (hex)").option("--expiration <timestamp>", "Expiration timestamp").action(async (opts) => {
|
|
767
|
+
const jsonFlag = program.opts().json;
|
|
768
|
+
try {
|
|
769
|
+
const service = await createService();
|
|
770
|
+
const result = await service.attestOnBehalf({
|
|
771
|
+
authority: opts.authority,
|
|
772
|
+
schemaUid: opts.schemaUid,
|
|
773
|
+
subject: opts.subject,
|
|
774
|
+
data: opts.data,
|
|
775
|
+
expirationTime: opts.expiration ? parseInt(opts.expiration, 10) : void 0
|
|
776
|
+
});
|
|
777
|
+
if (result.success) {
|
|
778
|
+
console.log(formatOutput({ attestationUid: result.data.attestationUid }, jsonFlag));
|
|
779
|
+
} else {
|
|
780
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
781
|
+
process.exitCode = 1;
|
|
782
|
+
}
|
|
783
|
+
} catch (err) {
|
|
784
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
785
|
+
process.exitCode = 1;
|
|
786
|
+
}
|
|
787
|
+
});
|
|
788
|
+
delegate.command("revoke").description("Revoke an attestation on behalf of the original attester (delegated)").requiredOption("--uid <uid>", "Attestation UID to revoke").action(async (opts) => {
|
|
789
|
+
const jsonFlag = program.opts().json;
|
|
790
|
+
try {
|
|
791
|
+
const service = await createService();
|
|
792
|
+
const result = await service.revokeOnBehalf(opts.uid);
|
|
793
|
+
if (result.success) {
|
|
794
|
+
console.log(formatOutput({ revoked: true, uid: opts.uid }, jsonFlag));
|
|
795
|
+
} else {
|
|
796
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
797
|
+
process.exitCode = 1;
|
|
798
|
+
}
|
|
799
|
+
} catch (err) {
|
|
800
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
801
|
+
process.exitCode = 1;
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
var tokenReward = program.command("token-reward").description("TokenRewardResolver operations");
|
|
805
|
+
tokenReward.command("set-config").description("Set reward token and amount (admin only)").requiredOption("--resolver <address>", "TokenRewardResolver contract address").requiredOption("--token <address>", "HTS reward token address").requiredOption("--amount <amount>", "Reward amount per attestation").action(async (opts) => {
|
|
806
|
+
const jsonFlag = program.opts().json;
|
|
807
|
+
try {
|
|
808
|
+
const service = await createService();
|
|
809
|
+
const result = await service.tokenRewardSetConfig(opts.resolver, opts.token, opts.amount);
|
|
810
|
+
if (result.success) {
|
|
811
|
+
console.log(formatOutput({ configured: true, token: opts.token, amount: opts.amount }, jsonFlag));
|
|
812
|
+
} else {
|
|
813
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
814
|
+
process.exitCode = 1;
|
|
815
|
+
}
|
|
816
|
+
} catch (err) {
|
|
817
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
818
|
+
process.exitCode = 1;
|
|
819
|
+
}
|
|
820
|
+
});
|
|
821
|
+
tokenReward.command("get-config").description("Get current reward configuration").requiredOption("--resolver <address>", "TokenRewardResolver contract address").action(async (opts) => {
|
|
822
|
+
const jsonFlag = program.opts().json;
|
|
823
|
+
try {
|
|
824
|
+
const service = await createService();
|
|
825
|
+
const result = await service.tokenRewardGetConfig(opts.resolver);
|
|
826
|
+
if (result.success) {
|
|
827
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
828
|
+
} else {
|
|
829
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
830
|
+
process.exitCode = 1;
|
|
831
|
+
}
|
|
832
|
+
} catch (err) {
|
|
833
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
834
|
+
process.exitCode = 1;
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
tokenReward.command("distributed").description("Check total rewards distributed to a subject").requiredOption("--resolver <address>", "TokenRewardResolver contract address").requiredOption("--subject <address>", "Subject address to check").action(async (opts) => {
|
|
838
|
+
const jsonFlag = program.opts().json;
|
|
839
|
+
try {
|
|
840
|
+
const service = await createService();
|
|
841
|
+
const result = await service.tokenRewardGetDistributed(opts.resolver, opts.subject);
|
|
842
|
+
if (result.success) {
|
|
843
|
+
console.log(formatOutput({ subject: opts.subject, ...result.data }, jsonFlag));
|
|
844
|
+
} else {
|
|
845
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
846
|
+
process.exitCode = 1;
|
|
847
|
+
}
|
|
848
|
+
} catch (err) {
|
|
849
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
850
|
+
process.exitCode = 1;
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
tokenReward.command("owner").description("Get the token reward resolver owner").requiredOption("--resolver <address>", "TokenRewardResolver contract address").action(async (opts) => {
|
|
854
|
+
const jsonFlag = program.opts().json;
|
|
855
|
+
try {
|
|
856
|
+
const service = await createService();
|
|
857
|
+
const result = await service.tokenRewardOwner(opts.resolver);
|
|
858
|
+
if (result.success) {
|
|
859
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
860
|
+
} else {
|
|
861
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
862
|
+
process.exitCode = 1;
|
|
863
|
+
}
|
|
864
|
+
} catch (err) {
|
|
865
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
866
|
+
process.exitCode = 1;
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
var crossContract = program.command("cross-contract").description("CrossContractResolver operations");
|
|
870
|
+
crossContract.command("set-pipeline").description("Set the resolver pipeline (admin only)").requiredOption("--resolver <address>", "CrossContractResolver contract address").requiredOption("--resolvers <addresses>", "Comma-separated list of resolver addresses").action(async (opts) => {
|
|
871
|
+
const jsonFlag = program.opts().json;
|
|
872
|
+
try {
|
|
873
|
+
const resolvers = opts.resolvers.split(",").map((a) => a.trim());
|
|
874
|
+
const service = await createService();
|
|
875
|
+
const result = await service.crossContractSetPipeline(opts.resolver, resolvers);
|
|
876
|
+
if (result.success) {
|
|
877
|
+
console.log(formatOutput({ configured: true, pipeline: resolvers }, jsonFlag));
|
|
878
|
+
} else {
|
|
879
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
880
|
+
process.exitCode = 1;
|
|
881
|
+
}
|
|
882
|
+
} catch (err) {
|
|
883
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
884
|
+
process.exitCode = 1;
|
|
885
|
+
}
|
|
886
|
+
});
|
|
887
|
+
crossContract.command("get-pipeline").description("Get the current resolver pipeline").requiredOption("--resolver <address>", "CrossContractResolver contract address").action(async (opts) => {
|
|
888
|
+
const jsonFlag = program.opts().json;
|
|
889
|
+
try {
|
|
890
|
+
const service = await createService();
|
|
891
|
+
const result = await service.crossContractGetPipeline(opts.resolver);
|
|
892
|
+
if (result.success) {
|
|
893
|
+
if (jsonFlag) {
|
|
894
|
+
console.log(JSON.stringify({ success: true, data: result.data.pipeline }, null, 2));
|
|
895
|
+
} else {
|
|
896
|
+
const pipeline = result.data.pipeline;
|
|
897
|
+
console.log(`Pipeline (${pipeline.length} resolvers):
|
|
898
|
+
`);
|
|
899
|
+
pipeline.forEach((addr, i) => {
|
|
900
|
+
console.log(` ${i + 1}. ${addr}`);
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
} else {
|
|
904
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
905
|
+
process.exitCode = 1;
|
|
906
|
+
}
|
|
907
|
+
} catch (err) {
|
|
908
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
909
|
+
process.exitCode = 1;
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
crossContract.command("owner").description("Get the cross-contract resolver owner").requiredOption("--resolver <address>", "CrossContractResolver contract address").action(async (opts) => {
|
|
913
|
+
const jsonFlag = program.opts().json;
|
|
914
|
+
try {
|
|
915
|
+
const service = await createService();
|
|
916
|
+
const result = await service.crossContractOwner(opts.resolver);
|
|
917
|
+
if (result.success) {
|
|
918
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
919
|
+
} else {
|
|
920
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
921
|
+
process.exitCode = 1;
|
|
922
|
+
}
|
|
923
|
+
} catch (err) {
|
|
924
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
925
|
+
process.exitCode = 1;
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
var schedule = program.command("schedule").description("Hedera Scheduled Transactions");
|
|
929
|
+
schedule.command("revoke").description("Schedule an automatic revocation at a future time").requiredOption("--uid <uid>", "Attestation UID to revoke").requiredOption("--execute-at <timestamp>", "Unix timestamp (seconds) when revocation should execute").action(async (opts) => {
|
|
930
|
+
const jsonFlag = program.opts().json;
|
|
931
|
+
try {
|
|
932
|
+
const service = await createService();
|
|
933
|
+
const result = await service.scheduleRevocation({
|
|
934
|
+
attestationUid: opts.uid,
|
|
935
|
+
executeAt: parseInt(opts.executeAt, 10)
|
|
936
|
+
});
|
|
937
|
+
if (result.success) {
|
|
938
|
+
console.log(formatOutput({
|
|
939
|
+
scheduled: true,
|
|
940
|
+
scheduleId: result.data.scheduleId,
|
|
941
|
+
transactionId: result.data.transactionId,
|
|
942
|
+
executeAt: new Date(parseInt(opts.executeAt, 10) * 1e3).toISOString()
|
|
943
|
+
}, jsonFlag));
|
|
944
|
+
} else {
|
|
945
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
946
|
+
process.exitCode = 1;
|
|
947
|
+
}
|
|
948
|
+
} catch (err) {
|
|
949
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
950
|
+
process.exitCode = 1;
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
schedule.command("status").description("Check the status of a scheduled revocation").requiredOption("--schedule-id <id>", "Hedera Schedule ID (e.g. 0.0.12345)").action(async (opts) => {
|
|
954
|
+
const jsonFlag = program.opts().json;
|
|
955
|
+
try {
|
|
956
|
+
const service = await createService();
|
|
957
|
+
const result = await service.getScheduledRevocation(opts.scheduleId);
|
|
958
|
+
if (result.success) {
|
|
959
|
+
console.log(formatOutput({
|
|
960
|
+
scheduleId: result.data.scheduleId,
|
|
961
|
+
executed: result.data.executed,
|
|
962
|
+
deleted: result.data.deleted,
|
|
963
|
+
expirationTime: result.data.expirationTime
|
|
964
|
+
}, jsonFlag));
|
|
965
|
+
} else {
|
|
966
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
967
|
+
process.exitCode = 1;
|
|
968
|
+
}
|
|
969
|
+
} catch (err) {
|
|
970
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
971
|
+
process.exitCode = 1;
|
|
972
|
+
}
|
|
973
|
+
});
|
|
974
|
+
var multisig = program.command("multisig").description("Multi-sig authority operations");
|
|
975
|
+
multisig.command("create").description("Create a multi-sig authority account with threshold keys").requiredOption("--keys <keys>", "Comma-separated ECDSA public keys (hex or DER)").requiredOption("--threshold <threshold>", "Number of required signatures").option("--initial-balance <hbar>", "Initial HBAR balance", "10").action(async (opts) => {
|
|
976
|
+
const jsonFlag = program.opts().json;
|
|
977
|
+
try {
|
|
978
|
+
const publicKeys = opts.keys.split(",").map((k) => k.trim());
|
|
979
|
+
const threshold = parseInt(opts.threshold, 10);
|
|
980
|
+
const service = await createService();
|
|
981
|
+
const result = await service.createMultiSigAuthority({
|
|
982
|
+
publicKeys,
|
|
983
|
+
threshold,
|
|
984
|
+
initialBalance: opts.initialBalance
|
|
985
|
+
});
|
|
986
|
+
if (result.success) {
|
|
987
|
+
console.log(formatOutput({
|
|
988
|
+
created: true,
|
|
989
|
+
accountId: result.data.accountId,
|
|
990
|
+
threshold: result.data.threshold,
|
|
991
|
+
totalKeys: result.data.totalKeys
|
|
992
|
+
}, jsonFlag));
|
|
993
|
+
} else {
|
|
994
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
995
|
+
process.exitCode = 1;
|
|
996
|
+
}
|
|
997
|
+
} catch (err) {
|
|
998
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
999
|
+
process.exitCode = 1;
|
|
1000
|
+
}
|
|
1001
|
+
});
|
|
1002
|
+
multisig.command("info").description("Get key structure info for a Hedera account").requiredOption("--account <accountId>", "Hedera account ID (e.g. 0.0.12345)").action(async (opts) => {
|
|
1003
|
+
const jsonFlag = program.opts().json;
|
|
1004
|
+
try {
|
|
1005
|
+
const service = await createService();
|
|
1006
|
+
const result = await service.getAccountKeyInfo(opts.account);
|
|
1007
|
+
if (result.success) {
|
|
1008
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
1009
|
+
} else {
|
|
1010
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
1011
|
+
process.exitCode = 1;
|
|
1012
|
+
}
|
|
1013
|
+
} catch (err) {
|
|
1014
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
1015
|
+
process.exitCode = 1;
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
1018
|
+
var staking = program.command("staking").description("HTS token staking for authorities");
|
|
1019
|
+
staking.command("stake").description("Stake HTS tokens as an authority").requiredOption("--token <address>", "HTS token address").requiredOption("--amount <amount>", "Amount to stake").action(async (opts) => {
|
|
1020
|
+
const jsonFlag = program.opts().json;
|
|
1021
|
+
try {
|
|
1022
|
+
const service = await createService();
|
|
1023
|
+
const result = await service.stakeTokens(opts.token, opts.amount);
|
|
1024
|
+
if (result.success) {
|
|
1025
|
+
console.log(formatOutput({ staked: true, token: opts.token, amount: opts.amount }, jsonFlag));
|
|
1026
|
+
} else {
|
|
1027
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
1028
|
+
process.exitCode = 1;
|
|
1029
|
+
}
|
|
1030
|
+
} catch (err) {
|
|
1031
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
1032
|
+
process.exitCode = 1;
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1035
|
+
staking.command("unstake").description("Unstake HTS tokens").requiredOption("--token <address>", "HTS token address").requiredOption("--amount <amount>", "Amount to unstake").action(async (opts) => {
|
|
1036
|
+
const jsonFlag = program.opts().json;
|
|
1037
|
+
try {
|
|
1038
|
+
const service = await createService();
|
|
1039
|
+
const result = await service.unstakeTokens(opts.token, opts.amount);
|
|
1040
|
+
if (result.success) {
|
|
1041
|
+
console.log(formatOutput({ unstaked: true, token: opts.token, amount: opts.amount }, jsonFlag));
|
|
1042
|
+
} else {
|
|
1043
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
1044
|
+
process.exitCode = 1;
|
|
1045
|
+
}
|
|
1046
|
+
} catch (err) {
|
|
1047
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
1048
|
+
process.exitCode = 1;
|
|
1049
|
+
}
|
|
1050
|
+
});
|
|
1051
|
+
staking.command("balance").description("Check staked token balance for an authority").requiredOption("--token <address>", "HTS token address").requiredOption("--authority <address>", "Authority address or account ID").action(async (opts) => {
|
|
1052
|
+
const jsonFlag = program.opts().json;
|
|
1053
|
+
try {
|
|
1054
|
+
const service = await createService();
|
|
1055
|
+
const result = await service.getStake(opts.token, opts.authority);
|
|
1056
|
+
if (result.success) {
|
|
1057
|
+
console.log(formatOutput({ authority: opts.authority, ...result.data }, jsonFlag));
|
|
1058
|
+
} else {
|
|
1059
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
1060
|
+
process.exitCode = 1;
|
|
1061
|
+
}
|
|
1062
|
+
} catch (err) {
|
|
1063
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
1064
|
+
process.exitCode = 1;
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
var fileService = program.command("file-schema").description("Hedera File Service schema storage");
|
|
1068
|
+
fileService.command("upload").description("Upload a schema definition to Hedera File Service").requiredOption("--definition <definition>", "Schema definition string").option("--memo <memo>", "File memo").action(async (opts) => {
|
|
1069
|
+
const jsonFlag = program.opts().json;
|
|
1070
|
+
try {
|
|
1071
|
+
const service = await createService();
|
|
1072
|
+
const result = await service.uploadSchemaFile(opts.definition, opts.memo);
|
|
1073
|
+
if (result.success) {
|
|
1074
|
+
console.log(formatOutput({
|
|
1075
|
+
uploaded: true,
|
|
1076
|
+
fileId: result.data.fileId,
|
|
1077
|
+
definition: result.data.definition
|
|
1078
|
+
}, jsonFlag));
|
|
1079
|
+
} else {
|
|
1080
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
1081
|
+
process.exitCode = 1;
|
|
1082
|
+
}
|
|
1083
|
+
} catch (err) {
|
|
1084
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
1085
|
+
process.exitCode = 1;
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
fileService.command("read").description("Read a schema definition from Hedera File Service").requiredOption("--file-id <fileId>", "Hedera File ID (e.g. 0.0.12345)").action(async (opts) => {
|
|
1089
|
+
const jsonFlag = program.opts().json;
|
|
1090
|
+
try {
|
|
1091
|
+
const service = await createService();
|
|
1092
|
+
const result = await service.readSchemaFile(opts.fileId);
|
|
1093
|
+
if (result.success) {
|
|
1094
|
+
console.log(formatOutput(result.data, jsonFlag));
|
|
1095
|
+
} else {
|
|
1096
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
1097
|
+
process.exitCode = 1;
|
|
1098
|
+
}
|
|
1099
|
+
} catch (err) {
|
|
1100
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
1101
|
+
process.exitCode = 1;
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
fileService.command("register").description("Register a schema from a Hedera File ID (reads definition from File Service)").requiredOption("--file-id <fileId>", "Hedera File ID containing the schema definition").option("--revocable", "Whether attestations can be revoked", false).option("--resolver <resolver>", "Resolver contract address").action(async (opts) => {
|
|
1105
|
+
const jsonFlag = program.opts().json;
|
|
1106
|
+
try {
|
|
1107
|
+
const service = await createService();
|
|
1108
|
+
const result = await service.registerSchemaFromFile({
|
|
1109
|
+
fileId: opts.fileId,
|
|
1110
|
+
revocable: opts.revocable,
|
|
1111
|
+
resolver: opts.resolver
|
|
1112
|
+
});
|
|
1113
|
+
if (result.success) {
|
|
1114
|
+
console.log(formatOutput({ schemaUid: result.data.schemaUid, fileId: opts.fileId }, jsonFlag));
|
|
1115
|
+
} else {
|
|
1116
|
+
console.error(formatError(result.error.type, result.error.message, jsonFlag));
|
|
1117
|
+
process.exitCode = 1;
|
|
1118
|
+
}
|
|
1119
|
+
} catch (err) {
|
|
1120
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
1121
|
+
process.exitCode = 1;
|
|
1122
|
+
}
|
|
1123
|
+
});
|
|
1124
|
+
var ai = program.command("ai").description("Chat with the Attestify AI Agent \u2014 natural language interface to the protocol").argument("[message]", "Message to send (omit for interactive mode)").option("--model <model>", "OpenAI model name", "gpt-4o-mini").action(async (message, opts) => {
|
|
1125
|
+
const jsonFlag = program.opts().json;
|
|
1126
|
+
try {
|
|
1127
|
+
const openAIApiKey = process.env.OPENAI_API_KEY;
|
|
1128
|
+
if (!openAIApiKey) {
|
|
1129
|
+
console.error(formatError("CONFIGURATION_ERROR", "Missing OPENAI_API_KEY environment variable.", jsonFlag));
|
|
1130
|
+
process.exitCode = 1;
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
const config = loadConfig();
|
|
1134
|
+
const { createAttestifyAgent } = await import("@attestify/sdk/ai");
|
|
1135
|
+
const { processMessage } = await createAttestifyAgent({
|
|
1136
|
+
accountId: config.operatorAccountId,
|
|
1137
|
+
privateKey: config.operatorPrivateKey,
|
|
1138
|
+
indexerUrl: config.indexerUrl,
|
|
1139
|
+
openAIApiKey,
|
|
1140
|
+
modelName: opts.model
|
|
1141
|
+
});
|
|
1142
|
+
console.log("[Attestify AI] Agent initialized with 17 tools\n");
|
|
1143
|
+
if (message) {
|
|
1144
|
+
const response = await processMessage(message);
|
|
1145
|
+
if (jsonFlag) {
|
|
1146
|
+
console.log(JSON.stringify({ success: true, response }, null, 2));
|
|
1147
|
+
} else {
|
|
1148
|
+
console.log(response);
|
|
1149
|
+
}
|
|
1150
|
+
} else {
|
|
1151
|
+
const readline = await import("readline");
|
|
1152
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1153
|
+
console.log('Interactive mode \u2014 type your message and press Enter. Type "exit" to quit.\n');
|
|
1154
|
+
const ask = () => {
|
|
1155
|
+
rl.question("You: ", async (input) => {
|
|
1156
|
+
const trimmed = input.trim();
|
|
1157
|
+
if (!trimmed || trimmed.toLowerCase() === "exit") {
|
|
1158
|
+
console.log("\nGoodbye!");
|
|
1159
|
+
rl.close();
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
try {
|
|
1163
|
+
const response = await processMessage(trimmed);
|
|
1164
|
+
console.log(`
|
|
1165
|
+
Agent: ${response}
|
|
1166
|
+
`);
|
|
1167
|
+
} catch (err) {
|
|
1168
|
+
console.error(`
|
|
1169
|
+
Error: ${err.message}
|
|
1170
|
+
`);
|
|
1171
|
+
}
|
|
1172
|
+
ask();
|
|
1173
|
+
});
|
|
1174
|
+
};
|
|
1175
|
+
ask();
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
} catch (err) {
|
|
1179
|
+
console.error(formatError("UNKNOWN_ERROR", err.message, jsonFlag));
|
|
1180
|
+
process.exitCode = 1;
|
|
1181
|
+
}
|
|
1182
|
+
});
|
|
1183
|
+
program.parse();
|
|
1184
|
+
//# sourceMappingURL=index.js.map
|