@certen.io/cli 0.2.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/LICENSE +21 -0
- package/dist/commands/admin.d.ts +2 -0
- package/dist/commands/admin.js +93 -0
- package/dist/commands/admin.js.map +1 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +68 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/governance.d.ts +2 -0
- package/dist/commands/governance.js +37 -0
- package/dist/commands/governance.js.map +1 -0
- package/dist/commands/identity.d.ts +2 -0
- package/dist/commands/identity.js +61 -0
- package/dist/commands/identity.js.map +1 -0
- package/dist/commands/pending.d.ts +2 -0
- package/dist/commands/pending.js +59 -0
- package/dist/commands/pending.js.map +1 -0
- package/dist/commands/portfolio.d.ts +2 -0
- package/dist/commands/portfolio.js +18 -0
- package/dist/commands/portfolio.js.map +1 -0
- package/dist/commands/transaction.d.ts +2 -0
- package/dist/commands/transaction.js +95 -0
- package/dist/commands/transaction.js.map +1 -0
- package/dist/config.d.ts +39 -0
- package/dist/config.js +147 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +6 -0
- package/dist/output.js +54 -0
- package/dist/output.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Certen IO
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { CertenClient } from '@certen.io/sdk';
|
|
2
|
+
import { getApiKey, getApiUrl } from '../config.js';
|
|
3
|
+
import { printOutput } from '../output.js';
|
|
4
|
+
async function getClient() {
|
|
5
|
+
return new CertenClient({ apiKey: await getApiKey(), baseUrl: getApiUrl() });
|
|
6
|
+
}
|
|
7
|
+
export function registerAdminCommands(program) {
|
|
8
|
+
const admin = program.command('admin').description('Administration');
|
|
9
|
+
// API Keys management
|
|
10
|
+
const apiKeys = admin.command('api-keys').description('API key management');
|
|
11
|
+
apiKeys
|
|
12
|
+
.command('list')
|
|
13
|
+
.description('List API keys')
|
|
14
|
+
.action(async () => {
|
|
15
|
+
const client = await getClient();
|
|
16
|
+
const result = await client.admin.listApiKeys();
|
|
17
|
+
printOutput(result);
|
|
18
|
+
});
|
|
19
|
+
apiKeys
|
|
20
|
+
.command('create')
|
|
21
|
+
.description('Create a new API key')
|
|
22
|
+
.requiredOption('--name <name>', 'Key name')
|
|
23
|
+
.requiredOption('--org-id <id>', 'Organization ID')
|
|
24
|
+
.option('--permissions <perms>', 'Comma-separated permissions')
|
|
25
|
+
.option('--rate-limit <rpm>', 'Rate limit RPM', parseInt)
|
|
26
|
+
.option('--expires-at <date>', 'Expiration date (ISO)')
|
|
27
|
+
.action(async (opts) => {
|
|
28
|
+
const client = await getClient();
|
|
29
|
+
const result = await client.admin.createApiKey({
|
|
30
|
+
name: opts.name,
|
|
31
|
+
orgId: opts.orgId,
|
|
32
|
+
permissions: opts.permissions ? opts.permissions.split(',') : undefined,
|
|
33
|
+
rateLimitRpm: opts.rateLimit,
|
|
34
|
+
expiresAt: opts.expiresAt,
|
|
35
|
+
});
|
|
36
|
+
printOutput(result);
|
|
37
|
+
});
|
|
38
|
+
apiKeys
|
|
39
|
+
.command('rotate')
|
|
40
|
+
.description('Rotate an API key (mints a new key + deactivates the old)')
|
|
41
|
+
.requiredOption('--id <uuid>', 'ID of the API key to rotate')
|
|
42
|
+
.action(async (opts) => {
|
|
43
|
+
const client = await getClient();
|
|
44
|
+
const result = await client.admin.rotateApiKey(opts.id);
|
|
45
|
+
printOutput(result);
|
|
46
|
+
});
|
|
47
|
+
apiKeys
|
|
48
|
+
.command('revoke')
|
|
49
|
+
.description('Revoke an API key (DELETE)')
|
|
50
|
+
.requiredOption('--id <uuid>', 'ID of the API key to revoke')
|
|
51
|
+
.action(async (opts) => {
|
|
52
|
+
const client = await getClient();
|
|
53
|
+
const result = await client.admin.revokeApiKey(opts.id);
|
|
54
|
+
printOutput(result);
|
|
55
|
+
});
|
|
56
|
+
// Audit log
|
|
57
|
+
admin
|
|
58
|
+
.command('audit-log')
|
|
59
|
+
.description('View audit log')
|
|
60
|
+
.option('--action <action>', 'Filter by action')
|
|
61
|
+
.option('--resource-type <type>', 'Filter by resource type')
|
|
62
|
+
.option('--from <date>', 'From date (ISO)')
|
|
63
|
+
.option('--to <date>', 'To date (ISO)')
|
|
64
|
+
.option('--limit <n>', 'Max results', parseInt)
|
|
65
|
+
.option('--offset <n>', 'Offset', parseInt)
|
|
66
|
+
.action(async (opts) => {
|
|
67
|
+
const client = await getClient();
|
|
68
|
+
const result = await client.admin.getAuditLog({
|
|
69
|
+
action: opts.action,
|
|
70
|
+
resourceType: opts.resourceType,
|
|
71
|
+
from: opts.from,
|
|
72
|
+
to: opts.to,
|
|
73
|
+
limit: opts.limit,
|
|
74
|
+
offset: opts.offset,
|
|
75
|
+
});
|
|
76
|
+
printOutput(result);
|
|
77
|
+
});
|
|
78
|
+
// Usage
|
|
79
|
+
admin
|
|
80
|
+
.command('usage')
|
|
81
|
+
.description('View usage summary')
|
|
82
|
+
.option('--from <date>', 'From date (ISO)')
|
|
83
|
+
.option('--to <date>', 'To date (ISO)')
|
|
84
|
+
.action(async (opts) => {
|
|
85
|
+
const client = await getClient();
|
|
86
|
+
const result = await client.admin.getUsage({
|
|
87
|
+
from: opts.from,
|
|
88
|
+
to: opts.to,
|
|
89
|
+
});
|
|
90
|
+
printOutput(result);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=admin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/commands/admin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { readConfig, writeConfig, setApiKey, clearApiKey, DEFAULT_API_URL } from '../config.js';
|
|
2
|
+
import { printOutput } from '../output.js';
|
|
3
|
+
export function registerAuthCommands(program) {
|
|
4
|
+
const auth = program.command('auth').description('Authentication management');
|
|
5
|
+
auth
|
|
6
|
+
.command('login')
|
|
7
|
+
.description('Save API key (OS keyring by default; --no-keyring stores in ~/.certen/config.json with 0600 perms)')
|
|
8
|
+
.requiredOption('--api-key <key>', 'API key to save')
|
|
9
|
+
.option('--api-url <url>', 'API base URL')
|
|
10
|
+
.option('--no-keyring', 'Store in ~/.certen/config.json instead of the OS keyring')
|
|
11
|
+
.action(async (opts) => {
|
|
12
|
+
const useKeyring = opts.keyring !== false;
|
|
13
|
+
try {
|
|
14
|
+
await setApiKey(opts.apiKey, useKeyring);
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
18
|
+
console.error(`Failed to save API key: ${msg}`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
if (opts.apiUrl) {
|
|
22
|
+
const cfg = readConfig();
|
|
23
|
+
cfg.api_url = opts.apiUrl;
|
|
24
|
+
writeConfig(cfg);
|
|
25
|
+
}
|
|
26
|
+
console.log(useKeyring ? 'API key saved to OS keyring' : 'API key saved to ~/.certen/config.json (mode 0600)');
|
|
27
|
+
});
|
|
28
|
+
auth
|
|
29
|
+
.command('logout')
|
|
30
|
+
.description('Remove the saved API key from keyring or config file')
|
|
31
|
+
.action(async () => {
|
|
32
|
+
await clearApiKey();
|
|
33
|
+
console.log('API key cleared');
|
|
34
|
+
});
|
|
35
|
+
auth
|
|
36
|
+
.command('status')
|
|
37
|
+
.description('Show current authentication config (prefix-only — never reveals the full key)')
|
|
38
|
+
.action(() => {
|
|
39
|
+
const cfg = readConfig();
|
|
40
|
+
// Round-2 #43: when storage=keyring the prefix is persisted at login
|
|
41
|
+
// time, so we can still display "which key is selected" without
|
|
42
|
+
// round-tripping through the OS keyring. The prefix has zero
|
|
43
|
+
// exfiltration risk — it's used as the public lookup field.
|
|
44
|
+
let apiKey;
|
|
45
|
+
if (process.env.CERTEN_API_KEY) {
|
|
46
|
+
apiKey = `${process.env.CERTEN_API_KEY.substring(0, 12)}... (from CERTEN_API_KEY env)`;
|
|
47
|
+
}
|
|
48
|
+
else if (cfg.api_key) {
|
|
49
|
+
apiKey = `${cfg.api_key.substring(0, 12)}...`;
|
|
50
|
+
}
|
|
51
|
+
else if (cfg.storage === 'keyring' && cfg.key_prefix) {
|
|
52
|
+
apiKey = `${cfg.key_prefix}... (in OS keyring)`;
|
|
53
|
+
}
|
|
54
|
+
else if (cfg.storage === 'keyring') {
|
|
55
|
+
apiKey = '(in OS keyring; prefix unknown — re-run `certen auth login` to record it)';
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
apiKey = '(not set)';
|
|
59
|
+
}
|
|
60
|
+
printOutput({
|
|
61
|
+
storage: cfg.storage ?? 'file (default)',
|
|
62
|
+
api_key: apiKey,
|
|
63
|
+
api_url: cfg.api_url ?? `${DEFAULT_API_URL} (default)`,
|
|
64
|
+
output: cfg.output ?? 'table (default)',
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { CertenClient } from '@certen.io/sdk';
|
|
2
|
+
import { getApiKey, getApiUrl } from '../config.js';
|
|
3
|
+
import { printOutput } from '../output.js';
|
|
4
|
+
async function getClient() {
|
|
5
|
+
return new CertenClient({ apiKey: await getApiKey(), baseUrl: getApiUrl() });
|
|
6
|
+
}
|
|
7
|
+
export function registerGovernanceCommands(program) {
|
|
8
|
+
const governance = program.command('governance').description('Governance operations');
|
|
9
|
+
governance
|
|
10
|
+
.command('add-delegate')
|
|
11
|
+
// `--identity` is the ADI (acc://org.acme), not a uuid — the governance endpoint keys on the ADI.
|
|
12
|
+
.description('Add a delegate to an identity key book')
|
|
13
|
+
.requiredOption('--identity <adi>', 'Identity ADI, e.g. acc://org.acme')
|
|
14
|
+
.requiredOption('--delegate-url <url>', 'Delegate URL to add')
|
|
15
|
+
.action(async (opts) => {
|
|
16
|
+
const client = await getClient();
|
|
17
|
+
const result = await client.governance.create({
|
|
18
|
+
identity: opts.identity,
|
|
19
|
+
operations: [{ type: 'add_delegate', delegate_url: opts.delegateUrl }],
|
|
20
|
+
});
|
|
21
|
+
printOutput(result);
|
|
22
|
+
});
|
|
23
|
+
governance
|
|
24
|
+
.command('set-threshold')
|
|
25
|
+
.description('Set the M-of-N acceptThreshold on an identity key page')
|
|
26
|
+
.requiredOption('--identity <adi>', 'Identity ADI, e.g. acc://org.acme')
|
|
27
|
+
.requiredOption('--threshold <n>', 'New threshold', parseInt)
|
|
28
|
+
.action(async (opts) => {
|
|
29
|
+
const client = await getClient();
|
|
30
|
+
const result = await client.governance.create({
|
|
31
|
+
identity: opts.identity,
|
|
32
|
+
operations: [{ type: 'set_threshold', threshold: opts.threshold }],
|
|
33
|
+
});
|
|
34
|
+
printOutput(result);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=governance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"governance.js","sourceRoot":"","sources":["../../src/commands/governance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,KAAK,UAAU,SAAS;IACtB,OAAO,IAAI,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,OAAgB;IACzD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAEtF,UAAU;SACP,OAAO,CAAC,cAAc,CAAC;QACxB,kGAAkG;SACjG,WAAW,CAAC,wCAAwC,CAAC;SACrD,cAAc,CAAC,kBAAkB,EAAE,mCAAmC,CAAC;SACvE,cAAc,CAAC,sBAAsB,EAAE,qBAAqB,CAAC;SAC7D,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;YAC5C,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;SACvE,CAAC,CAAC;QACH,WAAW,CAAC,MAA4C,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEL,UAAU;SACP,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,wDAAwD,CAAC;SACrE,cAAc,CAAC,kBAAkB,EAAE,mCAAmC,CAAC;SACvE,cAAc,CAAC,iBAAiB,EAAE,eAAe,EAAE,QAAQ,CAAC;SAC5D,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;YAC5C,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;SACnE,CAAC,CAAC;QACH,WAAW,CAAC,MAA4C,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { CertenClient } from '@certen.io/sdk';
|
|
2
|
+
import { getApiKey, getApiUrl } from '../config.js';
|
|
3
|
+
import { printOutput } from '../output.js';
|
|
4
|
+
async function getClient() {
|
|
5
|
+
return new CertenClient({ apiKey: await getApiKey(), baseUrl: getApiUrl() });
|
|
6
|
+
}
|
|
7
|
+
export function registerIdentityCommands(program) {
|
|
8
|
+
const identity = program.command('identity').description('Identity management');
|
|
9
|
+
identity
|
|
10
|
+
.command('create')
|
|
11
|
+
.description('Create a new identity')
|
|
12
|
+
.requiredOption('--name <name>', 'Identity name')
|
|
13
|
+
.requiredOption('--public-key-hash <hash>', 'Public key hash')
|
|
14
|
+
.option('--public-key <key>', 'Public key (hex)')
|
|
15
|
+
.option('--chains <chains>', 'Comma-separated chain IDs')
|
|
16
|
+
.option('--credits <credits>', 'Initial credits', parseInt)
|
|
17
|
+
.action(async (opts) => {
|
|
18
|
+
const client = await getClient();
|
|
19
|
+
const result = await client.identity.create({
|
|
20
|
+
name: opts.name,
|
|
21
|
+
publicKeyHash: opts.publicKeyHash,
|
|
22
|
+
publicKey: opts.publicKey,
|
|
23
|
+
chains: opts.chains ? opts.chains.split(',') : undefined,
|
|
24
|
+
credits: opts.credits,
|
|
25
|
+
});
|
|
26
|
+
printOutput(result);
|
|
27
|
+
});
|
|
28
|
+
identity
|
|
29
|
+
.command('list')
|
|
30
|
+
.description('(unavailable — the gateway has no identity list endpoint)')
|
|
31
|
+
.action(() => {
|
|
32
|
+
// This called GET /v1/identities, which 404s: the gateway serves /v1/identity (POST) and
|
|
33
|
+
// /v1/identity/{id} (GET/PATCH/DELETE) and has no collection route. Failing with an explanation
|
|
34
|
+
// beats failing with a 404 the user has to go decode. Kept as a command so it explains itself
|
|
35
|
+
// rather than printing "unknown command".
|
|
36
|
+
throw new Error('The gateway has no identity list endpoint — GET /v1/identities does not exist. '
|
|
37
|
+
+ 'Use `certen identity get <id>` for an identity you know, or `certen portfolio` for a '
|
|
38
|
+
+ 'cross-identity view of the org.');
|
|
39
|
+
});
|
|
40
|
+
identity
|
|
41
|
+
.command('get <id>')
|
|
42
|
+
.description('Get identity details')
|
|
43
|
+
.action(async (id) => {
|
|
44
|
+
const client = await getClient();
|
|
45
|
+
// No `--include`: the route takes no query parameters. It used to be sent and silently ignored.
|
|
46
|
+
const result = await client.identity.get(id);
|
|
47
|
+
printOutput(result);
|
|
48
|
+
});
|
|
49
|
+
identity
|
|
50
|
+
.command('link-chain <id>')
|
|
51
|
+
.description('Link a chain to an identity')
|
|
52
|
+
.requiredOption('--chain <chain>', 'Chain ID to link')
|
|
53
|
+
.action(async (id, opts) => {
|
|
54
|
+
const client = await getClient();
|
|
55
|
+
const result = await client.identity.update(id, {
|
|
56
|
+
linkChains: [opts.chain],
|
|
57
|
+
});
|
|
58
|
+
printOutput(result);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/commands/identity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,KAAK,UAAU,SAAS;IACtB,OAAO,IAAI,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,qBAAqB,CAAC,CAAC;IAEhF,QAAQ;SACL,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,uBAAuB,CAAC;SACpC,cAAc,CAAC,eAAe,EAAE,eAAe,CAAC;SAChD,cAAc,CAAC,0BAA0B,EAAE,iBAAiB,CAAC;SAC7D,MAAM,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;SAChD,MAAM,CAAC,mBAAmB,EAAE,2BAA2B,CAAC;SACxD,MAAM,CAAC,qBAAqB,EAAE,iBAAiB,EAAE,QAAQ,CAAC;SAC1D,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC1C,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;YACxD,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QACH,WAAW,CAAC,MAA4C,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEL,QAAQ;SACL,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,2DAA2D,CAAC;SACxE,MAAM,CAAC,GAAG,EAAE;QACX,yFAAyF;QACzF,gGAAgG;QAChG,8FAA8F;QAC9F,0CAA0C;QAC1C,MAAM,IAAI,KAAK,CACb,iFAAiF;cAC/E,uFAAuF;cACvF,iCAAiC,CACpC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,QAAQ;SACL,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,sBAAsB,CAAC;SACnC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,gGAAgG;QAChG,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7C,WAAW,CAAC,MAA4C,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEL,QAAQ;SACL,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CAAC,6BAA6B,CAAC;SAC1C,cAAc,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;SACrD,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAI,EAAE,EAAE;QACjC,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE;YAC9C,UAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;SACzB,CAAC,CAAC;QACH,WAAW,CAAC,MAA4C,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { CertenClient } from '@certen.io/sdk';
|
|
2
|
+
import { getApiKey, getApiUrl } from '../config.js';
|
|
3
|
+
import { printOutput } from '../output.js';
|
|
4
|
+
async function getClient() {
|
|
5
|
+
return new CertenClient({ apiKey: await getApiKey(), baseUrl: getApiUrl() });
|
|
6
|
+
}
|
|
7
|
+
export function registerPendingCommands(program) {
|
|
8
|
+
const pending = program.command('pending').description('Pending actions inbox');
|
|
9
|
+
pending
|
|
10
|
+
.command('list')
|
|
11
|
+
.description('List pending actions')
|
|
12
|
+
.option('--identity <id>', 'Filter by identity')
|
|
13
|
+
.option('--status <status>', 'Filter by status')
|
|
14
|
+
.option('--category <cat>', 'Filter by category')
|
|
15
|
+
.option('--limit <n>', 'Max results', parseInt)
|
|
16
|
+
.option('--offset <n>', 'Offset', parseInt)
|
|
17
|
+
.action(async (opts) => {
|
|
18
|
+
const client = await getClient();
|
|
19
|
+
const result = await client.pending.list({
|
|
20
|
+
identity: opts.identity,
|
|
21
|
+
status: opts.status,
|
|
22
|
+
category: opts.category,
|
|
23
|
+
limit: opts.limit,
|
|
24
|
+
offset: opts.offset,
|
|
25
|
+
});
|
|
26
|
+
printOutput(result);
|
|
27
|
+
});
|
|
28
|
+
pending
|
|
29
|
+
.command('sign <id>')
|
|
30
|
+
.description('Create a sign request for a pending action')
|
|
31
|
+
.option('--identity <id>', 'Identity to sign as')
|
|
32
|
+
.option('--signer-url <url>', 'Signer URL')
|
|
33
|
+
.option('--vote <vote>', 'Vote (accept/reject)')
|
|
34
|
+
.action(async (id, opts) => {
|
|
35
|
+
const client = await getClient();
|
|
36
|
+
const result = await client.sign.create({
|
|
37
|
+
type: 'pending_action',
|
|
38
|
+
targetId: id,
|
|
39
|
+
identity: opts.identity,
|
|
40
|
+
signerUrl: opts.signerUrl,
|
|
41
|
+
vote: opts.vote,
|
|
42
|
+
});
|
|
43
|
+
printOutput(result);
|
|
44
|
+
});
|
|
45
|
+
pending
|
|
46
|
+
.command('submit <id>')
|
|
47
|
+
.description('Submit a signature for a pending sign request')
|
|
48
|
+
.requiredOption('--signature <sig>', 'Signature (hex)')
|
|
49
|
+
.requiredOption('--public-key <key>', 'Public key (hex)')
|
|
50
|
+
.action(async (id, opts) => {
|
|
51
|
+
const client = await getClient();
|
|
52
|
+
const result = await client.sign.submitSignature(id, {
|
|
53
|
+
signature: opts.signature,
|
|
54
|
+
publicKey: opts.publicKey,
|
|
55
|
+
});
|
|
56
|
+
printOutput(result);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=pending.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending.js","sourceRoot":"","sources":["../../src/commands/pending.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,KAAK,UAAU,SAAS;IACtB,OAAO,IAAI,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAEhF,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,sBAAsB,CAAC;SACnC,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;SAC/C,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC;SAC/C,MAAM,CAAC,kBAAkB,EAAE,oBAAoB,CAAC;SAChD,MAAM,CAAC,aAAa,EAAE,aAAa,EAAE,QAAQ,CAAC;SAC9C,MAAM,CAAC,cAAc,EAAE,QAAQ,EAAE,QAAQ,CAAC;SAC1C,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;YACvC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,WAAW,CAAC,MAA4C,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,4CAA4C,CAAC;SACzD,MAAM,CAAC,iBAAiB,EAAE,qBAAqB,CAAC;SAChD,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC;SAC1C,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;SAC/C,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAI,EAAE,EAAE;QACjC,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;YACtC,IAAI,EAAE,gBAAgB;YACtB,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;QACH,WAAW,CAAC,MAA4C,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,aAAa,CAAC;SACtB,WAAW,CAAC,+CAA+C,CAAC;SAC5D,cAAc,CAAC,mBAAmB,EAAE,iBAAiB,CAAC;SACtD,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;SACxD,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAI,EAAE,EAAE;QACjC,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE;YACnD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,WAAW,CAAC,MAA4C,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CertenClient } from '@certen.io/sdk';
|
|
2
|
+
import { getApiKey, getApiUrl } from '../config.js';
|
|
3
|
+
import { printOutput } from '../output.js';
|
|
4
|
+
async function getClient() {
|
|
5
|
+
return new CertenClient({ apiKey: await getApiKey(), baseUrl: getApiUrl() });
|
|
6
|
+
}
|
|
7
|
+
export function registerPortfolioCommands(program) {
|
|
8
|
+
program
|
|
9
|
+
.command('portfolio')
|
|
10
|
+
.description('Get multi-chain portfolio balances')
|
|
11
|
+
.option('--identity <id>', 'Filter by identity')
|
|
12
|
+
.action(async (opts) => {
|
|
13
|
+
const client = await getClient();
|
|
14
|
+
const result = await client.portfolio.get(opts.identity);
|
|
15
|
+
printOutput(result);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=portfolio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portfolio.js","sourceRoot":"","sources":["../../src/commands/portfolio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,KAAK,UAAU,SAAS;IACtB,OAAO,IAAI,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,OAAO;SACJ,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,oCAAoC,CAAC;SACjD,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;SAC/C,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzD,WAAW,CAAC,MAA4C,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { CertenClient } from '@certen.io/sdk';
|
|
3
|
+
import { getApiKey, getApiUrl } from '../config.js';
|
|
4
|
+
import { printOutput } from '../output.js';
|
|
5
|
+
async function getClient() {
|
|
6
|
+
return new CertenClient({ apiKey: await getApiKey(), baseUrl: getApiUrl() });
|
|
7
|
+
}
|
|
8
|
+
export function registerTransactionCommands(program) {
|
|
9
|
+
const tx = program.command('tx').description('Transaction lifecycle');
|
|
10
|
+
tx
|
|
11
|
+
.command('create')
|
|
12
|
+
.description('Open a transaction intent (returns signing_data — you sign it, then `tx sign`)')
|
|
13
|
+
// The API takes an `intent` object, not flat to/amount/type fields. The flags below build the simple
|
|
14
|
+
// native-transfer shape; `--intent` takes a JSON file or literal for multi-leg and contract-call
|
|
15
|
+
// intents, which have no sensible flag representation.
|
|
16
|
+
.requiredOption('--identity <id>', 'Identity ID (uuid)')
|
|
17
|
+
.option('--intent <json>', 'Intent as JSON, or @path/to/intent.json. Overrides the flags below.')
|
|
18
|
+
.option('--from-chain <chain>', 'Source chain', 'accumulate')
|
|
19
|
+
.option('--to-chain <chain>', 'Destination chain, e.g. ethereum-sepolia')
|
|
20
|
+
.option('--from <address>', 'Source address (the identity ADI or its abstract account)')
|
|
21
|
+
.option('--to <address>', 'Destination address')
|
|
22
|
+
.option('--amount <amount>', 'Amount in base units (wei) — pass as a string')
|
|
23
|
+
.option('--token <symbol>', 'Token symbol')
|
|
24
|
+
.option('--contract-address <addr...>', 'Contract addresses this intent touches')
|
|
25
|
+
.option('--signer-key-page <url>', 'Which key page signs, e.g. acc://org.acme/book/2')
|
|
26
|
+
.option('--signer-public-key <hex>', 'Which seat on the page signs (64 hex)')
|
|
27
|
+
.option('--idempotency-key <key>', 'Idempotency key (one is generated if omitted)')
|
|
28
|
+
.action(async (opts) => {
|
|
29
|
+
const client = await getClient();
|
|
30
|
+
let intent;
|
|
31
|
+
if (opts.intent) {
|
|
32
|
+
const raw = opts.intent.startsWith('@')
|
|
33
|
+
? readFileSync(opts.intent.slice(1), 'utf8')
|
|
34
|
+
: opts.intent;
|
|
35
|
+
intent = JSON.parse(raw);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
if (!opts.to || !opts.amount) {
|
|
39
|
+
throw new Error('give --intent, or all of --to and --amount (plus --to-chain) for a simple transfer');
|
|
40
|
+
}
|
|
41
|
+
intent = {
|
|
42
|
+
fromChain: opts.fromChain,
|
|
43
|
+
toChain: opts.toChain,
|
|
44
|
+
fromAddress: opts.from,
|
|
45
|
+
toAddress: opts.to,
|
|
46
|
+
amount: String(opts.amount),
|
|
47
|
+
tokenSymbol: opts.token,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const result = await client.transaction.create({
|
|
51
|
+
identityId: opts.identity,
|
|
52
|
+
intent,
|
|
53
|
+
contractAddresses: opts.contractAddress,
|
|
54
|
+
signerKeyPage: opts.signerKeyPage,
|
|
55
|
+
signerPublicKey: opts.signerPublicKey,
|
|
56
|
+
idempotencyKey: opts.idempotencyKey,
|
|
57
|
+
});
|
|
58
|
+
printOutput(result);
|
|
59
|
+
});
|
|
60
|
+
tx
|
|
61
|
+
.command('sign <id>')
|
|
62
|
+
.description('Submit a signature for a transaction')
|
|
63
|
+
.requiredOption('--signature <sig>', 'Signature (hex)')
|
|
64
|
+
.requiredOption('--public-key <key>', 'Public key (hex)')
|
|
65
|
+
.action(async (id, opts) => {
|
|
66
|
+
const client = await getClient();
|
|
67
|
+
const result = await client.transaction.submitSignature(id, {
|
|
68
|
+
signature: opts.signature,
|
|
69
|
+
publicKey: opts.publicKey,
|
|
70
|
+
});
|
|
71
|
+
printOutput(result);
|
|
72
|
+
});
|
|
73
|
+
tx
|
|
74
|
+
.command('status <id>')
|
|
75
|
+
.description('Get transaction status')
|
|
76
|
+
.action(async (id) => {
|
|
77
|
+
const client = await getClient();
|
|
78
|
+
const result = await client.transaction.get(id);
|
|
79
|
+
printOutput(result);
|
|
80
|
+
});
|
|
81
|
+
tx
|
|
82
|
+
.command('list')
|
|
83
|
+
.description('List transactions')
|
|
84
|
+
.option('--limit <n>', 'Max results', parseInt)
|
|
85
|
+
.option('--offset <n>', 'Offset', parseInt)
|
|
86
|
+
.action(async (opts) => {
|
|
87
|
+
const client = await getClient();
|
|
88
|
+
const result = await client.transaction.list({
|
|
89
|
+
limit: opts.limit,
|
|
90
|
+
offset: opts.offset,
|
|
91
|
+
});
|
|
92
|
+
printOutput(result);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/commands/transaction.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface CliConfig {
|
|
2
|
+
api_key?: string;
|
|
3
|
+
api_url?: string;
|
|
4
|
+
output?: 'table' | 'json';
|
|
5
|
+
/** When 'keyring', api_key in this file is unused; the OS keyring is the source of truth. */
|
|
6
|
+
storage?: 'file' | 'keyring';
|
|
7
|
+
/**
|
|
8
|
+
* Round-2 #43: when storage=keyring, the actual key isn't in this file.
|
|
9
|
+
* Persist its prefix (first 12 chars) so `auth status` can still show
|
|
10
|
+
* which key is selected without round-tripping through the keyring.
|
|
11
|
+
*/
|
|
12
|
+
key_prefix?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function readConfig(): CliConfig;
|
|
15
|
+
/**
|
|
16
|
+
* Write the config file with 0600 perms (owner read/write only). On Windows,
|
|
17
|
+
* filesystem permissions are not enforced the same way; we still call
|
|
18
|
+
* chmod to flag intent.
|
|
19
|
+
*/
|
|
20
|
+
export declare function writeConfig(config: CliConfig): void;
|
|
21
|
+
/**
|
|
22
|
+
* Read the API key with the following precedence:
|
|
23
|
+
* 1. CERTEN_API_KEY env (always wins so CI never touches the keyring/file)
|
|
24
|
+
* 2. OS keyring when storage='keyring'
|
|
25
|
+
* 3. config.json (only if perms are 0600 or stricter)
|
|
26
|
+
*/
|
|
27
|
+
export declare function getApiKey(): Promise<string>;
|
|
28
|
+
export declare function setApiKey(apiKey: string, useKeyring: boolean): Promise<void>;
|
|
29
|
+
export declare function clearApiKey(): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* The gateway this CLI talks to when nothing else says.
|
|
32
|
+
*
|
|
33
|
+
* Must be a host that actually serves the API. This was `https://api.certen.io`, which resolves to the
|
|
34
|
+
* Certen marketing site, so every unconfigured invocation got HTML back and the failure looked like a
|
|
35
|
+
* broken CLI rather than a wrong address.
|
|
36
|
+
*/
|
|
37
|
+
export declare const DEFAULT_API_URL = "https://gateway.kompendium.co";
|
|
38
|
+
export declare function getApiUrl(): string;
|
|
39
|
+
export declare function getOutputFormat(): 'table' | 'json';
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync, statSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
const CONFIG_DIR = join(homedir(), '.certen');
|
|
5
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
6
|
+
export function readConfig() {
|
|
7
|
+
if (!existsSync(CONFIG_FILE)) {
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
const raw = readFileSync(CONFIG_FILE, 'utf-8');
|
|
12
|
+
return JSON.parse(raw);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Write the config file with 0600 perms (owner read/write only). On Windows,
|
|
20
|
+
* filesystem permissions are not enforced the same way; we still call
|
|
21
|
+
* chmod to flag intent.
|
|
22
|
+
*/
|
|
23
|
+
export function writeConfig(config) {
|
|
24
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
25
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { encoding: 'utf-8', mode: 0o600 });
|
|
28
|
+
try {
|
|
29
|
+
chmodSync(CONFIG_FILE, 0o600);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Windows or non-permission-aware FS: best effort.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* If the config file exists with world/group read permissions, warn the
|
|
37
|
+
* user and refuse to read the api_key. Forces explicit re-login under
|
|
38
|
+
* 0600 perms, or env-var-only operation.
|
|
39
|
+
*/
|
|
40
|
+
function configFileIsSecure() {
|
|
41
|
+
try {
|
|
42
|
+
const stat = statSync(CONFIG_FILE);
|
|
43
|
+
// Cross-platform: check that group/world have no read bits.
|
|
44
|
+
const mode = stat.mode & 0o077;
|
|
45
|
+
return mode === 0;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return true; // missing file is fine; we just have no key
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function loadKeyring() {
|
|
52
|
+
try {
|
|
53
|
+
const mod = await import('keytar');
|
|
54
|
+
return mod;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const KEYRING_SERVICE = 'certen';
|
|
61
|
+
const KEYRING_ACCOUNT = 'api_key';
|
|
62
|
+
/**
|
|
63
|
+
* Read the API key with the following precedence:
|
|
64
|
+
* 1. CERTEN_API_KEY env (always wins so CI never touches the keyring/file)
|
|
65
|
+
* 2. OS keyring when storage='keyring'
|
|
66
|
+
* 3. config.json (only if perms are 0600 or stricter)
|
|
67
|
+
*/
|
|
68
|
+
export async function getApiKey() {
|
|
69
|
+
const envKey = process.env.CERTEN_API_KEY;
|
|
70
|
+
if (envKey)
|
|
71
|
+
return envKey;
|
|
72
|
+
const cfg = readConfig();
|
|
73
|
+
if (cfg.storage === 'keyring') {
|
|
74
|
+
const kr = await loadKeyring();
|
|
75
|
+
if (kr) {
|
|
76
|
+
const v = await kr.getPassword(KEYRING_SERVICE, KEYRING_ACCOUNT);
|
|
77
|
+
if (v)
|
|
78
|
+
return v;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.error('storage=keyring requested but `keytar` is not installed; install it or set CERTEN_API_KEY.');
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (cfg.api_key) {
|
|
86
|
+
if (!configFileIsSecure()) {
|
|
87
|
+
console.error('refusing to read ~/.certen/config.json — file permissions are not 0600. Run `certen auth login` again to fix.');
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
return cfg.api_key;
|
|
91
|
+
}
|
|
92
|
+
console.error('No API key configured. Run "certen auth login --api-key <key>" or set CERTEN_API_KEY.');
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
export async function setApiKey(apiKey, useKeyring) {
|
|
96
|
+
const prefix = apiKey.substring(0, 12);
|
|
97
|
+
if (useKeyring) {
|
|
98
|
+
const kr = await loadKeyring();
|
|
99
|
+
if (!kr) {
|
|
100
|
+
throw new Error('keytar is not installed; install it with `npm i keytar -g` or pass --no-keyring');
|
|
101
|
+
}
|
|
102
|
+
await kr.setPassword(KEYRING_SERVICE, KEYRING_ACCOUNT, apiKey);
|
|
103
|
+
const cfg = readConfig();
|
|
104
|
+
cfg.storage = 'keyring';
|
|
105
|
+
cfg.key_prefix = prefix;
|
|
106
|
+
delete cfg.api_key;
|
|
107
|
+
writeConfig(cfg);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const cfg = readConfig();
|
|
111
|
+
cfg.storage = 'file';
|
|
112
|
+
cfg.api_key = apiKey;
|
|
113
|
+
cfg.key_prefix = prefix;
|
|
114
|
+
writeConfig(cfg);
|
|
115
|
+
}
|
|
116
|
+
export async function clearApiKey() {
|
|
117
|
+
const cfg = readConfig();
|
|
118
|
+
if (cfg.storage === 'keyring') {
|
|
119
|
+
const kr = await loadKeyring();
|
|
120
|
+
if (kr)
|
|
121
|
+
await kr.deletePassword(KEYRING_SERVICE, KEYRING_ACCOUNT);
|
|
122
|
+
}
|
|
123
|
+
delete cfg.api_key;
|
|
124
|
+
delete cfg.key_prefix;
|
|
125
|
+
cfg.storage = 'file';
|
|
126
|
+
writeConfig(cfg);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The gateway this CLI talks to when nothing else says.
|
|
130
|
+
*
|
|
131
|
+
* Must be a host that actually serves the API. This was `https://api.certen.io`, which resolves to the
|
|
132
|
+
* Certen marketing site, so every unconfigured invocation got HTML back and the failure looked like a
|
|
133
|
+
* broken CLI rather than a wrong address.
|
|
134
|
+
*/
|
|
135
|
+
export const DEFAULT_API_URL = 'https://gateway.kompendium.co';
|
|
136
|
+
export function getApiUrl() {
|
|
137
|
+
const envUrl = process.env.CERTEN_API_URL;
|
|
138
|
+
if (envUrl)
|
|
139
|
+
return envUrl;
|
|
140
|
+
const cfg = readConfig();
|
|
141
|
+
return cfg.api_url ?? DEFAULT_API_URL;
|
|
142
|
+
}
|
|
143
|
+
export function getOutputFormat() {
|
|
144
|
+
const cfg = readConfig();
|
|
145
|
+
return cfg.output ?? 'table';
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { CertenError } from '@certen.io/sdk';
|
|
4
|
+
import { registerAuthCommands } from './commands/auth.js';
|
|
5
|
+
import { registerIdentityCommands } from './commands/identity.js';
|
|
6
|
+
import { registerTransactionCommands } from './commands/transaction.js';
|
|
7
|
+
import { registerPendingCommands } from './commands/pending.js';
|
|
8
|
+
import { registerGovernanceCommands } from './commands/governance.js';
|
|
9
|
+
import { registerPortfolioCommands } from './commands/portfolio.js';
|
|
10
|
+
import { registerAdminCommands } from './commands/admin.js';
|
|
11
|
+
const program = new Command();
|
|
12
|
+
program
|
|
13
|
+
.name('certen')
|
|
14
|
+
.description('CERTEN Gateway CLI')
|
|
15
|
+
.version('0.1.0');
|
|
16
|
+
registerAuthCommands(program);
|
|
17
|
+
registerIdentityCommands(program);
|
|
18
|
+
registerTransactionCommands(program);
|
|
19
|
+
registerPendingCommands(program);
|
|
20
|
+
registerGovernanceCommands(program);
|
|
21
|
+
registerPortfolioCommands(program);
|
|
22
|
+
registerAdminCommands(program);
|
|
23
|
+
// Global error handler
|
|
24
|
+
program.hook('preAction', () => { });
|
|
25
|
+
program.exitOverride();
|
|
26
|
+
async function main() {
|
|
27
|
+
try {
|
|
28
|
+
await program.parseAsync(process.argv);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
if (err instanceof CertenError) {
|
|
32
|
+
console.error(`Error [${err.code}]: ${err.message}`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
if (err instanceof Error) {
|
|
36
|
+
// Commander exit override throws for --help etc
|
|
37
|
+
if (err.exitCode === 0)
|
|
38
|
+
return;
|
|
39
|
+
console.error(`Error: ${err.message}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
console.error('Unknown error:', err);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
main();
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,oBAAoB,CAAC;KACjC,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,2BAA2B,CAAC,OAAO,CAAC,CAAC;AACrC,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACpC,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACnC,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAE/B,uBAAuB;AACvB,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AACpC,OAAO,CAAC,YAAY,EAAE,CAAC;AAEvB,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;YACzB,gDAAgD;YAChD,IAAK,GAAW,CAAC,QAAQ,KAAK,CAAC;gBAAE,OAAO;YACxC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
package/dist/output.d.ts
ADDED
package/dist/output.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { getOutputFormat } from './config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Print data as an aligned table or JSON depending on user preference.
|
|
4
|
+
*/
|
|
5
|
+
export function printOutput(data, opts) {
|
|
6
|
+
const format = opts?.forceJson ? 'json' : getOutputFormat();
|
|
7
|
+
if (format === 'json') {
|
|
8
|
+
console.log(JSON.stringify(data, null, 2));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
// Single object: print key-value pairs
|
|
12
|
+
if (!Array.isArray(data)) {
|
|
13
|
+
const entries = Object.entries(data);
|
|
14
|
+
const maxKeyLen = Math.max(...entries.map(([k]) => k.length));
|
|
15
|
+
for (const [key, value] of entries) {
|
|
16
|
+
const displayValue = typeof value === 'object' ? JSON.stringify(value) : String(value ?? '');
|
|
17
|
+
console.log(`${key.padEnd(maxKeyLen + 2)}${displayValue}`);
|
|
18
|
+
}
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// Array: print table
|
|
22
|
+
if (data.length === 0) {
|
|
23
|
+
console.log('(no results)');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const columns = Object.keys(data[0]);
|
|
27
|
+
const widths = {};
|
|
28
|
+
for (const col of columns) {
|
|
29
|
+
widths[col] = col.length;
|
|
30
|
+
}
|
|
31
|
+
for (const row of data) {
|
|
32
|
+
for (const col of columns) {
|
|
33
|
+
const val = formatCell(row[col]);
|
|
34
|
+
widths[col] = Math.max(widths[col], val.length);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Header
|
|
38
|
+
const header = columns.map((c) => c.toUpperCase().padEnd(widths[c])).join(' ');
|
|
39
|
+
console.log(header);
|
|
40
|
+
console.log(columns.map((c) => '-'.repeat(widths[c])).join(' '));
|
|
41
|
+
// Rows
|
|
42
|
+
for (const row of data) {
|
|
43
|
+
const line = columns.map((c) => formatCell(row[c]).padEnd(widths[c])).join(' ');
|
|
44
|
+
console.log(line);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function formatCell(value) {
|
|
48
|
+
if (value === null || value === undefined)
|
|
49
|
+
return '-';
|
|
50
|
+
if (typeof value === 'object')
|
|
51
|
+
return JSON.stringify(value);
|
|
52
|
+
return String(value);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@certen.io/cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Command line for the CERTEN Gateway API",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"certen",
|
|
9
|
+
"accumulate",
|
|
10
|
+
"cli",
|
|
11
|
+
"blockchain"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/certenIO/certen-sdk#readme",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/certenIO/certen-sdk.git",
|
|
17
|
+
"directory": "packages/cli"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/certenIO/certen-sdk/issues"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"certen": "dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"//files": "Build output plus docs. Without this npm ships the whole directory, including src/ and test/.",
|
|
29
|
+
"files": [
|
|
30
|
+
"dist/",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"typecheck": "tsc --noEmit",
|
|
38
|
+
"//prepack": "Build before packing so the published bin can never point at a missing dist/index.js.",
|
|
39
|
+
"prepack": "npm run build",
|
|
40
|
+
"prepublishOnly": "npm run build && npm test"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"//dependencies": "@certen.io/sdk MUST be a version range, not file:../sdk. A published package carrying a file: dependency installs and then fails to resolve on the consumer's machine, because that path does not exist there. Local development uses `npm link` or a workspace instead.",
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@certen.io/sdk": "^0.2.0",
|
|
48
|
+
"commander": "^12.0.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"typescript": "^5.5.0",
|
|
52
|
+
"vitest": "^1.6.1",
|
|
53
|
+
"@types/node": "^22.0.0"
|
|
54
|
+
},
|
|
55
|
+
"//publishConfig": "Provenance is passed as --provenance by .github/workflows/release.yml. Setting it here instead would break every publish outside CI with an error that does not explain itself."
|
|
56
|
+
}
|