sigild 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +39 -0
- package/LICENSE +202 -0
- package/README.md +70 -0
- package/THREAT_MODEL.md +84 -0
- package/dist/src/audit/index.d.ts +2 -0
- package/dist/src/audit/index.d.ts.map +1 -0
- package/dist/src/audit/index.js +2 -0
- package/dist/src/audit/index.js.map +1 -0
- package/dist/src/audit/log.d.ts +96 -0
- package/dist/src/audit/log.d.ts.map +1 -0
- package/dist/src/audit/log.js +229 -0
- package/dist/src/audit/log.js.map +1 -0
- package/dist/src/bin/sigild.d.ts +3 -0
- package/dist/src/bin/sigild.d.ts.map +1 -0
- package/dist/src/bin/sigild.js +30 -0
- package/dist/src/bin/sigild.js.map +1 -0
- package/dist/src/crypto/aead.d.ts +9 -0
- package/dist/src/crypto/aead.d.ts.map +1 -0
- package/dist/src/crypto/aead.js +38 -0
- package/dist/src/crypto/aead.js.map +1 -0
- package/dist/src/crypto/index.d.ts +5 -0
- package/dist/src/crypto/index.d.ts.map +1 -0
- package/dist/src/crypto/index.js +5 -0
- package/dist/src/crypto/index.js.map +1 -0
- package/dist/src/crypto/kdf.d.ts +10 -0
- package/dist/src/crypto/kdf.d.ts.map +1 -0
- package/dist/src/crypto/kdf.js +27 -0
- package/dist/src/crypto/kdf.js.map +1 -0
- package/dist/src/crypto/keyfile.d.ts +12 -0
- package/dist/src/crypto/keyfile.d.ts.map +1 -0
- package/dist/src/crypto/keyfile.js +114 -0
- package/dist/src/crypto/keyfile.js.map +1 -0
- package/dist/src/crypto/secret-buffer.d.ts +19 -0
- package/dist/src/crypto/secret-buffer.d.ts.map +1 -0
- package/dist/src/crypto/secret-buffer.js +48 -0
- package/dist/src/crypto/secret-buffer.js.map +1 -0
- package/dist/src/daemon/handles.d.ts +51 -0
- package/dist/src/daemon/handles.d.ts.map +1 -0
- package/dist/src/daemon/handles.js +140 -0
- package/dist/src/daemon/handles.js.map +1 -0
- package/dist/src/daemon/index.d.ts +5 -0
- package/dist/src/daemon/index.d.ts.map +1 -0
- package/dist/src/daemon/index.js +5 -0
- package/dist/src/daemon/index.js.map +1 -0
- package/dist/src/daemon/methods.d.ts +20 -0
- package/dist/src/daemon/methods.d.ts.map +1 -0
- package/dist/src/daemon/methods.js +221 -0
- package/dist/src/daemon/methods.js.map +1 -0
- package/dist/src/daemon/passphrase.d.ts +14 -0
- package/dist/src/daemon/passphrase.d.ts.map +1 -0
- package/dist/src/daemon/passphrase.js +49 -0
- package/dist/src/daemon/passphrase.js.map +1 -0
- package/dist/src/daemon/rpc.d.ts +61 -0
- package/dist/src/daemon/rpc.d.ts.map +1 -0
- package/dist/src/daemon/rpc.js +76 -0
- package/dist/src/daemon/rpc.js.map +1 -0
- package/dist/src/daemon/runtime.d.ts +40 -0
- package/dist/src/daemon/runtime.d.ts.map +1 -0
- package/dist/src/daemon/runtime.js +61 -0
- package/dist/src/daemon/runtime.js.map +1 -0
- package/dist/src/daemon/server.d.ts +53 -0
- package/dist/src/daemon/server.d.ts.map +1 -0
- package/dist/src/daemon/server.js +103 -0
- package/dist/src/daemon/server.js.map +1 -0
- package/dist/src/eth/address.d.ts +13 -0
- package/dist/src/eth/address.d.ts.map +1 -0
- package/dist/src/eth/address.js +51 -0
- package/dist/src/eth/address.js.map +1 -0
- package/dist/src/eth/index.d.ts +8 -0
- package/dist/src/eth/index.d.ts.map +1 -0
- package/dist/src/eth/index.js +8 -0
- package/dist/src/eth/index.js.map +1 -0
- package/dist/src/eth/keccak.d.ts +2 -0
- package/dist/src/eth/keccak.d.ts.map +1 -0
- package/dist/src/eth/keccak.js +5 -0
- package/dist/src/eth/keccak.js.map +1 -0
- package/dist/src/eth/rlp.d.ts +16 -0
- package/dist/src/eth/rlp.d.ts.map +1 -0
- package/dist/src/eth/rlp.js +99 -0
- package/dist/src/eth/rlp.js.map +1 -0
- package/dist/src/eth/secp.d.ts +17 -0
- package/dist/src/eth/secp.d.ts.map +1 -0
- package/dist/src/eth/secp.js +43 -0
- package/dist/src/eth/secp.js.map +1 -0
- package/dist/src/eth/sign-message.d.ts +18 -0
- package/dist/src/eth/sign-message.d.ts.map +1 -0
- package/dist/src/eth/sign-message.js +42 -0
- package/dist/src/eth/sign-message.js.map +1 -0
- package/dist/src/eth/sign-tx.d.ts +38 -0
- package/dist/src/eth/sign-tx.d.ts.map +1 -0
- package/dist/src/eth/sign-tx.js +92 -0
- package/dist/src/eth/sign-tx.js.map +1 -0
- package/dist/src/eth/sign-typed.d.ts +33 -0
- package/dist/src/eth/sign-typed.d.ts.map +1 -0
- package/dist/src/eth/sign-typed.js +142 -0
- package/dist/src/eth/sign-typed.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type SecretBuffer } from '../crypto/index.js';
|
|
2
|
+
export interface PortalInfo {
|
|
3
|
+
handle: string;
|
|
4
|
+
kind: 'eth';
|
|
5
|
+
address: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class HandleLoadError extends Error {
|
|
8
|
+
readonly cause?: unknown;
|
|
9
|
+
constructor(message: string, cause?: unknown);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* In-memory registry of handle → unlocked SecretBuffer.
|
|
13
|
+
*
|
|
14
|
+
* The expectation is that this is constructed once at daemon startup, populated
|
|
15
|
+
* via loadFromDir (or addEntry from tests), and disposed once at shutdown.
|
|
16
|
+
* After dispose() any further get/list calls throw.
|
|
17
|
+
*/
|
|
18
|
+
export declare class HandleTable {
|
|
19
|
+
#private;
|
|
20
|
+
static parseHandle(handle: string): {
|
|
21
|
+
kind: 'eth';
|
|
22
|
+
name: string;
|
|
23
|
+
};
|
|
24
|
+
static handleFromFilename(filename: string): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Load every keyfile in `dir` named `<handle>.sigil`, decrypting each with
|
|
27
|
+
* the same passphrase. Throws HandleLoadError on any failure.
|
|
28
|
+
*
|
|
29
|
+
* Order: deterministic by sorted filename, so audit logs and list_portals
|
|
30
|
+
* output are stable across restarts.
|
|
31
|
+
*/
|
|
32
|
+
loadFromDir(dir: string, passphrase: Buffer): void;
|
|
33
|
+
/**
|
|
34
|
+
* Add a handle directly (for tests or for non-file-backed key sources).
|
|
35
|
+
* Takes ownership of the SecretBuffer; dispose() will zeroize it.
|
|
36
|
+
*/
|
|
37
|
+
addEntry(handle: string, secret: SecretBuffer): void;
|
|
38
|
+
has(handle: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Returns the SecretBuffer for the handle. Caller must NOT dispose it —
|
|
41
|
+
* the table owns the lifetime.
|
|
42
|
+
*/
|
|
43
|
+
get(handle: string): SecretBuffer | undefined;
|
|
44
|
+
list(): PortalInfo[];
|
|
45
|
+
/**
|
|
46
|
+
* Zeroize every key and mark the table unusable. Idempotent.
|
|
47
|
+
*/
|
|
48
|
+
dispose(): void;
|
|
49
|
+
get isDisposed(): boolean;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=handles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../../../src/daemon/handles.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,oBAAoB,CAAC;AAQ5B,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAkB,KAAK,CAAC,EAAE,OAAO,CAAC;gBACtB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAK7C;AAED;;;;;;GAMG;AACH,qBAAa,WAAW;;IAKtB,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAMjE,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO1D;;;;;;OAMG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAgClD;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI;IAcpD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAK5B;;;OAGG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAK7C,IAAI,IAAI,UAAU,EAAE;IAKpB;;OAEG;IACH,OAAO,IAAI,IAAI;IAOf,IAAI,UAAU,IAAI,OAAO,CAExB;CACF"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { addressFromPrivateKey } from '../eth/address.js';
|
|
4
|
+
import { unsealKey, WrongPassphraseError, } from '../crypto/index.js';
|
|
5
|
+
const KEYFILE_EXT = '.sigil';
|
|
6
|
+
// Handle format: <kind>:<name> where kind is currently always "eth" and name
|
|
7
|
+
// is restricted to characters that are safe both as identifiers and as
|
|
8
|
+
// filenames. Disallow '.', '/', and whitespace.
|
|
9
|
+
const HANDLE_RE = /^(eth):([a-zA-Z0-9_-]+)$/;
|
|
10
|
+
export class HandleLoadError extends Error {
|
|
11
|
+
cause;
|
|
12
|
+
constructor(message, cause) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'HandleLoadError';
|
|
15
|
+
if (cause !== undefined)
|
|
16
|
+
this.cause = cause;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* In-memory registry of handle → unlocked SecretBuffer.
|
|
21
|
+
*
|
|
22
|
+
* The expectation is that this is constructed once at daemon startup, populated
|
|
23
|
+
* via loadFromDir (or addEntry from tests), and disposed once at shutdown.
|
|
24
|
+
* After dispose() any further get/list calls throw.
|
|
25
|
+
*/
|
|
26
|
+
export class HandleTable {
|
|
27
|
+
// Wrapped in a private map; not exposed.
|
|
28
|
+
#entries = new Map();
|
|
29
|
+
#disposed = false;
|
|
30
|
+
static parseHandle(handle) {
|
|
31
|
+
const m = HANDLE_RE.exec(handle);
|
|
32
|
+
if (!m)
|
|
33
|
+
throw new HandleLoadError(`invalid handle "${handle}": expected <kind>:<name>`);
|
|
34
|
+
return { kind: m[1], name: m[2] };
|
|
35
|
+
}
|
|
36
|
+
static handleFromFilename(filename) {
|
|
37
|
+
if (!filename.endsWith(KEYFILE_EXT))
|
|
38
|
+
return null;
|
|
39
|
+
const base = filename.slice(0, -KEYFILE_EXT.length);
|
|
40
|
+
if (!HANDLE_RE.test(base))
|
|
41
|
+
return null;
|
|
42
|
+
return base;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Load every keyfile in `dir` named `<handle>.sigil`, decrypting each with
|
|
46
|
+
* the same passphrase. Throws HandleLoadError on any failure.
|
|
47
|
+
*
|
|
48
|
+
* Order: deterministic by sorted filename, so audit logs and list_portals
|
|
49
|
+
* output are stable across restarts.
|
|
50
|
+
*/
|
|
51
|
+
loadFromDir(dir, passphrase) {
|
|
52
|
+
if (this.#disposed)
|
|
53
|
+
throw new Error('HandleTable is disposed');
|
|
54
|
+
let entries;
|
|
55
|
+
try {
|
|
56
|
+
entries = readdirSync(dir).sort();
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
if (err.code === 'ENOENT')
|
|
60
|
+
return;
|
|
61
|
+
throw new HandleLoadError(`failed to read keys directory ${dir}`, err);
|
|
62
|
+
}
|
|
63
|
+
for (const filename of entries) {
|
|
64
|
+
const handle = HandleTable.handleFromFilename(filename);
|
|
65
|
+
if (handle === null)
|
|
66
|
+
continue; // ignore non-keyfiles
|
|
67
|
+
const path = join(dir, filename);
|
|
68
|
+
let blob;
|
|
69
|
+
try {
|
|
70
|
+
blob = readFileSync(path);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
throw new HandleLoadError(`failed to read keyfile ${path}`, err);
|
|
74
|
+
}
|
|
75
|
+
let secret;
|
|
76
|
+
try {
|
|
77
|
+
secret = unsealKey(blob, passphrase);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
if (err instanceof WrongPassphraseError) {
|
|
81
|
+
throw new HandleLoadError(`wrong passphrase or tampered keyfile: ${path}`, err);
|
|
82
|
+
}
|
|
83
|
+
throw new HandleLoadError(`failed to unseal keyfile ${path}`, err);
|
|
84
|
+
}
|
|
85
|
+
this.addEntry(handle, secret);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Add a handle directly (for tests or for non-file-backed key sources).
|
|
90
|
+
* Takes ownership of the SecretBuffer; dispose() will zeroize it.
|
|
91
|
+
*/
|
|
92
|
+
addEntry(handle, secret) {
|
|
93
|
+
if (this.#disposed)
|
|
94
|
+
throw new Error('HandleTable is disposed');
|
|
95
|
+
HandleTable.parseHandle(handle); // validates format
|
|
96
|
+
if (this.#entries.has(handle)) {
|
|
97
|
+
secret.dispose();
|
|
98
|
+
throw new HandleLoadError(`duplicate handle "${handle}"`);
|
|
99
|
+
}
|
|
100
|
+
const address = addressFromPrivateKey(secret.bytes());
|
|
101
|
+
this.#entries.set(handle, {
|
|
102
|
+
secret,
|
|
103
|
+
info: { handle, kind: 'eth', address },
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
has(handle) {
|
|
107
|
+
if (this.#disposed)
|
|
108
|
+
throw new Error('HandleTable is disposed');
|
|
109
|
+
return this.#entries.has(handle);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Returns the SecretBuffer for the handle. Caller must NOT dispose it —
|
|
113
|
+
* the table owns the lifetime.
|
|
114
|
+
*/
|
|
115
|
+
get(handle) {
|
|
116
|
+
if (this.#disposed)
|
|
117
|
+
throw new Error('HandleTable is disposed');
|
|
118
|
+
return this.#entries.get(handle)?.secret;
|
|
119
|
+
}
|
|
120
|
+
list() {
|
|
121
|
+
if (this.#disposed)
|
|
122
|
+
throw new Error('HandleTable is disposed');
|
|
123
|
+
return Array.from(this.#entries.values()).map((e) => ({ ...e.info }));
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Zeroize every key and mark the table unusable. Idempotent.
|
|
127
|
+
*/
|
|
128
|
+
dispose() {
|
|
129
|
+
if (this.#disposed)
|
|
130
|
+
return;
|
|
131
|
+
for (const e of this.#entries.values())
|
|
132
|
+
e.secret.dispose();
|
|
133
|
+
this.#entries.clear();
|
|
134
|
+
this.#disposed = true;
|
|
135
|
+
}
|
|
136
|
+
get isDisposed() {
|
|
137
|
+
return this.#disposed;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=handles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handles.js","sourceRoot":"","sources":["../../../src/daemon/handles.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { type RpcId, type RpcRequest, type RpcResponse, type RpcSuccess, type RpcError, type RpcErrorObject, type ParseResult, RPC_VERSION, RPC_PARSE_ERROR, RPC_INVALID_REQUEST, RPC_METHOD_NOT_FOUND, RPC_INVALID_PARAMS, RPC_INTERNAL_ERROR, RPC_PORTAL_NOT_FOUND, RPC_POLICY_DENIED, RPC_INVALID_PAYLOAD, parseRequest, encodeResponse, encodeError, } from './rpc.js';
|
|
2
|
+
export { type PortalInfo, HandleLoadError, HandleTable, } from './handles.js';
|
|
3
|
+
export { type MethodContext, type MethodHandler, RpcMethodError, METHODS, dispatch, } from './methods.js';
|
|
4
|
+
export { type DaemonServerOpts, type DaemonServerHandle, type LogEvent, startDaemonServer, } from './server.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/daemon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,KAAK,EACV,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,KAAK,UAAU,EACf,eAAe,EACf,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,cAAc,EACd,OAAO,EACP,QAAQ,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,QAAQ,EACb,iBAAiB,GAClB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { RPC_VERSION, RPC_PARSE_ERROR, RPC_INVALID_REQUEST, RPC_METHOD_NOT_FOUND, RPC_INVALID_PARAMS, RPC_INTERNAL_ERROR, RPC_PORTAL_NOT_FOUND, RPC_POLICY_DENIED, RPC_INVALID_PAYLOAD, parseRequest, encodeResponse, encodeError, } from './rpc.js';
|
|
2
|
+
export { HandleLoadError, HandleTable, } from './handles.js';
|
|
3
|
+
export { RpcMethodError, METHODS, dispatch, } from './methods.js';
|
|
4
|
+
export { startDaemonServer, } from './server.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/daemon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EAEL,eAAe,EACf,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,cAAc,EACd,OAAO,EACP,QAAQ,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAIL,iBAAiB,GAClB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type AuditWriter } from '../audit/index.js';
|
|
2
|
+
import { type HandleTable } from './handles.js';
|
|
3
|
+
export declare class RpcMethodError extends Error {
|
|
4
|
+
readonly code: number;
|
|
5
|
+
readonly data: unknown;
|
|
6
|
+
constructor(code: number, message: string, data?: unknown);
|
|
7
|
+
}
|
|
8
|
+
export interface MethodContext {
|
|
9
|
+
handles: HandleTable;
|
|
10
|
+
audit: AuditWriter;
|
|
11
|
+
}
|
|
12
|
+
export type MethodHandler = (params: unknown, ctx: MethodContext) => unknown;
|
|
13
|
+
export declare const METHODS: Readonly<Record<string, MethodHandler>>;
|
|
14
|
+
/**
|
|
15
|
+
* Dispatch a parsed RPC request to the matching method.
|
|
16
|
+
* Throws RpcMethodError on user errors or method-not-found, or other Error
|
|
17
|
+
* for unexpected internals.
|
|
18
|
+
*/
|
|
19
|
+
export declare function dispatch(method: string, params: unknown, ctx: MethodContext): unknown;
|
|
20
|
+
//# sourceMappingURL=methods.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"methods.d.ts","sourceRoot":"","sources":["../../../src/daemon/methods.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAgB3B,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;gBACX,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;CAM1D;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC;AA8M7E,eAAO,MAAM,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAK1D,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAMrF"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { personalSign, signTransaction, signTypedData, } from '../eth/index.js';
|
|
2
|
+
import { RPC_INVALID_PARAMS, RPC_METHOD_NOT_FOUND, RPC_PORTAL_NOT_FOUND, } from './rpc.js';
|
|
3
|
+
export class RpcMethodError extends Error {
|
|
4
|
+
code;
|
|
5
|
+
data;
|
|
6
|
+
constructor(code, message, data) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'RpcMethodError';
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.data = data;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Helpers
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
function asObject(params, methodName) {
|
|
17
|
+
if (typeof params !== 'object' || params === null || Array.isArray(params)) {
|
|
18
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `${methodName}: params must be an object`);
|
|
19
|
+
}
|
|
20
|
+
return params;
|
|
21
|
+
}
|
|
22
|
+
function asString(obj, key, methodName) {
|
|
23
|
+
const v = obj[key];
|
|
24
|
+
if (typeof v !== 'string') {
|
|
25
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `${methodName}: ${key} must be a string`);
|
|
26
|
+
}
|
|
27
|
+
return v;
|
|
28
|
+
}
|
|
29
|
+
function hexToBuf(s, methodName, key) {
|
|
30
|
+
if (!/^0x[0-9a-fA-F]*$/.test(s)) {
|
|
31
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `${methodName}: ${key} must be 0x-prefixed hex`);
|
|
32
|
+
}
|
|
33
|
+
return Buffer.from(s.slice(2), 'hex');
|
|
34
|
+
}
|
|
35
|
+
function requirePortal(handles, handle) {
|
|
36
|
+
const sb = handles.get(handle);
|
|
37
|
+
if (!sb) {
|
|
38
|
+
throw new RpcMethodError(RPC_PORTAL_NOT_FOUND, `portal "${handle}" not found`);
|
|
39
|
+
}
|
|
40
|
+
return sb.bytes();
|
|
41
|
+
}
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Methods
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
const sigil_list_portals = (_params, ctx) => {
|
|
46
|
+
return { portals: ctx.handles.list() };
|
|
47
|
+
};
|
|
48
|
+
const sigil_eth_sign_message = (params, ctx) => {
|
|
49
|
+
const obj = asObject(params, 'eth_sign_message');
|
|
50
|
+
const portal = asString(obj, 'portal', 'eth_sign_message');
|
|
51
|
+
const messageHex = asString(obj, 'message', 'eth_sign_message');
|
|
52
|
+
const message = hexToBuf(messageHex, 'eth_sign_message', 'message');
|
|
53
|
+
const priv = requirePortal(ctx.handles, portal);
|
|
54
|
+
const sig = personalSign(message, priv);
|
|
55
|
+
const sigHex = ('0x' + sig.toString('hex'));
|
|
56
|
+
ctx.audit.append({
|
|
57
|
+
kind: 'eth_sign_message',
|
|
58
|
+
portal,
|
|
59
|
+
payload: { message: messageHex },
|
|
60
|
+
decision: 'allow',
|
|
61
|
+
sig: sigHex,
|
|
62
|
+
});
|
|
63
|
+
return { signature: sigHex };
|
|
64
|
+
};
|
|
65
|
+
function asTx(obj) {
|
|
66
|
+
const type = obj['type'];
|
|
67
|
+
if (type !== 'legacy' && type !== 'eip1559') {
|
|
68
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: type must be "legacy" or "eip1559"`);
|
|
69
|
+
}
|
|
70
|
+
const num = (key) => {
|
|
71
|
+
const v = obj[key];
|
|
72
|
+
if (typeof v === 'string') {
|
|
73
|
+
try {
|
|
74
|
+
return BigInt(v);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: ${key} not a valid bigint string`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (typeof v === 'number') {
|
|
81
|
+
if (!Number.isInteger(v) || v < 0) {
|
|
82
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: ${key} must be a non-negative integer`);
|
|
83
|
+
}
|
|
84
|
+
return BigInt(v);
|
|
85
|
+
}
|
|
86
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: ${key} must be number or decimal string`);
|
|
87
|
+
};
|
|
88
|
+
const to = obj['to'];
|
|
89
|
+
if (to !== null && typeof to !== 'string') {
|
|
90
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: to must be 0x address or null`);
|
|
91
|
+
}
|
|
92
|
+
if (typeof to === 'string' && !/^0x[0-9a-fA-F]{40}$/.test(to)) {
|
|
93
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: to must be 0x-prefixed 20-byte address`);
|
|
94
|
+
}
|
|
95
|
+
const data = obj['data'];
|
|
96
|
+
if (typeof data !== 'string' || !/^0x[0-9a-fA-F]*$/.test(data)) {
|
|
97
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: data must be 0x-prefixed hex`);
|
|
98
|
+
}
|
|
99
|
+
if (type === 'legacy') {
|
|
100
|
+
const tx = {
|
|
101
|
+
type: 'legacy',
|
|
102
|
+
chainId: num('chainId'),
|
|
103
|
+
nonce: num('nonce'),
|
|
104
|
+
gasPrice: num('gasPrice'),
|
|
105
|
+
gasLimit: num('gasLimit'),
|
|
106
|
+
to: to,
|
|
107
|
+
value: num('value'),
|
|
108
|
+
data: data,
|
|
109
|
+
};
|
|
110
|
+
return tx;
|
|
111
|
+
}
|
|
112
|
+
// eip1559
|
|
113
|
+
const accessListRaw = obj['accessList'];
|
|
114
|
+
let accessList;
|
|
115
|
+
if (accessListRaw === undefined) {
|
|
116
|
+
accessList = [];
|
|
117
|
+
}
|
|
118
|
+
else if (Array.isArray(accessListRaw)) {
|
|
119
|
+
accessList = accessListRaw.map((item, i) => {
|
|
120
|
+
if (typeof item !== 'object' || item === null || Array.isArray(item)) {
|
|
121
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: accessList[${i}] must be object`);
|
|
122
|
+
}
|
|
123
|
+
const it = item;
|
|
124
|
+
const addr = it['address'];
|
|
125
|
+
const keys = it['storageKeys'];
|
|
126
|
+
if (typeof addr !== 'string' || !/^0x[0-9a-fA-F]{40}$/.test(addr)) {
|
|
127
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: accessList[${i}].address`);
|
|
128
|
+
}
|
|
129
|
+
if (!Array.isArray(keys)) {
|
|
130
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: accessList[${i}].storageKeys must be array`);
|
|
131
|
+
}
|
|
132
|
+
for (const k of keys) {
|
|
133
|
+
if (typeof k !== 'string' || !/^0x[0-9a-fA-F]{64}$/.test(k)) {
|
|
134
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: accessList[${i}].storageKeys[*]`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return { address: addr, storageKeys: keys };
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `tx: accessList must be array or omitted`);
|
|
142
|
+
}
|
|
143
|
+
const tx = {
|
|
144
|
+
type: 'eip1559',
|
|
145
|
+
chainId: num('chainId'),
|
|
146
|
+
nonce: num('nonce'),
|
|
147
|
+
maxPriorityFeePerGas: num('maxPriorityFeePerGas'),
|
|
148
|
+
maxFeePerGas: num('maxFeePerGas'),
|
|
149
|
+
gasLimit: num('gasLimit'),
|
|
150
|
+
to: to,
|
|
151
|
+
value: num('value'),
|
|
152
|
+
data: data,
|
|
153
|
+
accessList,
|
|
154
|
+
};
|
|
155
|
+
return tx;
|
|
156
|
+
}
|
|
157
|
+
const sigil_eth_sign_transaction = (params, ctx) => {
|
|
158
|
+
const obj = asObject(params, 'eth_sign_transaction');
|
|
159
|
+
const portal = asString(obj, 'portal', 'eth_sign_transaction');
|
|
160
|
+
const txObj = obj['tx'];
|
|
161
|
+
if (typeof txObj !== 'object' || txObj === null || Array.isArray(txObj)) {
|
|
162
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, 'eth_sign_transaction: tx must be an object');
|
|
163
|
+
}
|
|
164
|
+
const tx = asTx(txObj);
|
|
165
|
+
const priv = requirePortal(ctx.handles, portal);
|
|
166
|
+
const signed = signTransaction(tx, priv);
|
|
167
|
+
ctx.audit.append({
|
|
168
|
+
kind: 'eth_sign_transaction',
|
|
169
|
+
portal,
|
|
170
|
+
payload: { tx: txObj },
|
|
171
|
+
decision: 'allow',
|
|
172
|
+
sig: signed,
|
|
173
|
+
});
|
|
174
|
+
return { signed };
|
|
175
|
+
};
|
|
176
|
+
const sigil_eth_sign_typed_data = (params, ctx) => {
|
|
177
|
+
const obj = asObject(params, 'eth_sign_typed_data');
|
|
178
|
+
const portal = asString(obj, 'portal', 'eth_sign_typed_data');
|
|
179
|
+
const td = obj['typedData'];
|
|
180
|
+
if (typeof td !== 'object' || td === null || Array.isArray(td)) {
|
|
181
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, 'eth_sign_typed_data: typedData must be object');
|
|
182
|
+
}
|
|
183
|
+
// We trust the typed-data shape minimally — sign-typed.ts will throw
|
|
184
|
+
// on missing fields; we wrap that as INVALID_PARAMS for the caller.
|
|
185
|
+
const priv = requirePortal(ctx.handles, portal);
|
|
186
|
+
let sig;
|
|
187
|
+
try {
|
|
188
|
+
sig = signTypedData(td, priv);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
throw new RpcMethodError(RPC_INVALID_PARAMS, `eth_sign_typed_data: ${err.message}`);
|
|
192
|
+
}
|
|
193
|
+
const sigHex = ('0x' + sig.toString('hex'));
|
|
194
|
+
ctx.audit.append({
|
|
195
|
+
kind: 'eth_sign_typed_data',
|
|
196
|
+
portal,
|
|
197
|
+
payload: { typedData: td },
|
|
198
|
+
decision: 'allow',
|
|
199
|
+
sig: sigHex,
|
|
200
|
+
});
|
|
201
|
+
return { signature: sigHex };
|
|
202
|
+
};
|
|
203
|
+
export const METHODS = Object.freeze({
|
|
204
|
+
sigil_list_portals,
|
|
205
|
+
sigil_eth_sign_message,
|
|
206
|
+
sigil_eth_sign_transaction,
|
|
207
|
+
sigil_eth_sign_typed_data,
|
|
208
|
+
});
|
|
209
|
+
/**
|
|
210
|
+
* Dispatch a parsed RPC request to the matching method.
|
|
211
|
+
* Throws RpcMethodError on user errors or method-not-found, or other Error
|
|
212
|
+
* for unexpected internals.
|
|
213
|
+
*/
|
|
214
|
+
export function dispatch(method, params, ctx) {
|
|
215
|
+
const handler = METHODS[method];
|
|
216
|
+
if (!handler) {
|
|
217
|
+
throw new RpcMethodError(RPC_METHOD_NOT_FOUND, `method not found: ${method}`);
|
|
218
|
+
}
|
|
219
|
+
return handler(params, ctx);
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=methods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"methods.js","sourceRoot":"","sources":["../../../src/daemon/methods.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReadStream } from 'node:tty';
|
|
2
|
+
/**
|
|
3
|
+
* Read a passphrase from a TTY without echoing it. Returns the passphrase as a
|
|
4
|
+
* Buffer so the caller can zeroize it after use.
|
|
5
|
+
*
|
|
6
|
+
* The implementation reads byte-by-byte in raw mode, handling Enter, backspace,
|
|
7
|
+
* and Ctrl-C. It is intentionally testable: pass a stdin/stderr override.
|
|
8
|
+
*/
|
|
9
|
+
export interface ReadPassphraseDeps {
|
|
10
|
+
stdin?: ReadStream;
|
|
11
|
+
stderr?: NodeJS.WritableStream;
|
|
12
|
+
}
|
|
13
|
+
export declare function readPassphrase(prompt: string, deps?: ReadPassphraseDeps): Promise<Buffer>;
|
|
14
|
+
//# sourceMappingURL=passphrase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passphrase.d.ts","sourceRoot":"","sources":["../../../src/daemon/passphrase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;CAChC;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoD7F"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export function readPassphrase(prompt, deps = {}) {
|
|
2
|
+
const stdin = deps.stdin ?? process.stdin;
|
|
3
|
+
const stderr = deps.stderr ?? process.stderr;
|
|
4
|
+
if (!stdin.isTTY) {
|
|
5
|
+
return Promise.reject(new Error('readPassphrase: stdin is not a TTY; pipe in via process substitution or use --passphrase-fd'));
|
|
6
|
+
}
|
|
7
|
+
stderr.write(prompt);
|
|
8
|
+
const wasRaw = stdin.isRaw;
|
|
9
|
+
stdin.setRawMode(true);
|
|
10
|
+
stdin.resume();
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
let buf = '';
|
|
13
|
+
const onData = (chunk) => {
|
|
14
|
+
const s = chunk.toString('utf8');
|
|
15
|
+
for (const c of s) {
|
|
16
|
+
const code = c.charCodeAt(0);
|
|
17
|
+
if (code === 0x03) {
|
|
18
|
+
// Ctrl-C
|
|
19
|
+
cleanup();
|
|
20
|
+
stderr.write('\n');
|
|
21
|
+
reject(new Error('passphrase entry aborted'));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (code === 0x0d || code === 0x0a) {
|
|
25
|
+
// Enter
|
|
26
|
+
cleanup();
|
|
27
|
+
stderr.write('\n');
|
|
28
|
+
resolve(Buffer.from(buf, 'utf8'));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (code === 0x7f || code === 0x08) {
|
|
32
|
+
// Backspace
|
|
33
|
+
buf = buf.slice(0, -1);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (code < 0x20)
|
|
37
|
+
continue;
|
|
38
|
+
buf += c;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const cleanup = () => {
|
|
42
|
+
stdin.removeListener('data', onData);
|
|
43
|
+
stdin.pause();
|
|
44
|
+
stdin.setRawMode(wasRaw);
|
|
45
|
+
};
|
|
46
|
+
stdin.on('data', onData);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=passphrase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passphrase.js","sourceRoot":"","sources":["../../../src/daemon/passphrase.ts"],"names":[],"mappings":"AAcA,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,OAA2B,EAAE;IAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAK,OAAO,CAAC,KAAoB,CAAC;IAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAE7C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CAAC,6FAA6F,CAAC,CACzG,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAErB,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;IAC3B,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACvB,KAAK,CAAC,MAAM,EAAE,CAAC;IAEf,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,CAAC,KAAa,EAAQ,EAAE;YACrC,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjC,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClB,MAAM,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAC7B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAClB,SAAS;oBACT,OAAO,EAAE,CAAC;oBACV,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACnB,MAAM,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;oBAC9C,OAAO;gBACT,CAAC;gBACD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBACnC,QAAQ;oBACR,OAAO,EAAE,CAAC;oBACV,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACnB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;oBAClC,OAAO;gBACT,CAAC;gBACD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBACnC,YAAY;oBACZ,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;oBACvB,SAAS;gBACX,CAAC;gBACD,IAAI,IAAI,GAAG,IAAI;oBAAE,SAAS;gBAC1B,GAAG,IAAI,CAAC,CAAC;YACX,CAAC;QACH,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACrC,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC,CAAC;QACF,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON-RPC 2.0 over newline-delimited JSON (NDJSON).
|
|
3
|
+
* Pure functions only — no IO. The server in server.ts wires this onto sockets.
|
|
4
|
+
*
|
|
5
|
+
* We use the strict JSON-RPC 2.0 envelope: every request has `jsonrpc: "2.0"`,
|
|
6
|
+
* a method, and either an id (for requests expecting a response) or no id (for
|
|
7
|
+
* notifications, which sigil currently rejects since every sign decision needs
|
|
8
|
+
* to round-trip through the audit log).
|
|
9
|
+
*/
|
|
10
|
+
export declare const RPC_VERSION = "2.0";
|
|
11
|
+
export type RpcId = string | number | null;
|
|
12
|
+
export interface RpcRequest {
|
|
13
|
+
jsonrpc: '2.0';
|
|
14
|
+
id: RpcId;
|
|
15
|
+
method: string;
|
|
16
|
+
params: unknown;
|
|
17
|
+
}
|
|
18
|
+
export interface RpcSuccess {
|
|
19
|
+
jsonrpc: '2.0';
|
|
20
|
+
id: RpcId;
|
|
21
|
+
result: unknown;
|
|
22
|
+
}
|
|
23
|
+
export interface RpcErrorObject {
|
|
24
|
+
code: number;
|
|
25
|
+
message: string;
|
|
26
|
+
data?: unknown;
|
|
27
|
+
}
|
|
28
|
+
export interface RpcError {
|
|
29
|
+
jsonrpc: '2.0';
|
|
30
|
+
id: RpcId;
|
|
31
|
+
error: RpcErrorObject;
|
|
32
|
+
}
|
|
33
|
+
export type RpcResponse = RpcSuccess | RpcError;
|
|
34
|
+
export declare const RPC_PARSE_ERROR = -32700;
|
|
35
|
+
export declare const RPC_INVALID_REQUEST = -32600;
|
|
36
|
+
export declare const RPC_METHOD_NOT_FOUND = -32601;
|
|
37
|
+
export declare const RPC_INVALID_PARAMS = -32602;
|
|
38
|
+
export declare const RPC_INTERNAL_ERROR = -32603;
|
|
39
|
+
export declare const RPC_PORTAL_NOT_FOUND = -32000;
|
|
40
|
+
export declare const RPC_POLICY_DENIED = -32001;
|
|
41
|
+
export declare const RPC_INVALID_PAYLOAD = -32002;
|
|
42
|
+
export type ParseResult = {
|
|
43
|
+
kind: 'request';
|
|
44
|
+
request: RpcRequest;
|
|
45
|
+
} | {
|
|
46
|
+
kind: 'parse_error';
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'invalid';
|
|
49
|
+
id: RpcId;
|
|
50
|
+
reason: string;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Parse a single NDJSON line into a JSON-RPC request.
|
|
54
|
+
* Returns either a valid request, a parse_error (if the line is not JSON), or
|
|
55
|
+
* an invalid envelope along with the id that should be echoed in the error
|
|
56
|
+
* response (which is null if the id couldn't be extracted).
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseRequest(line: string): ParseResult;
|
|
59
|
+
export declare function encodeResponse(id: RpcId, result: unknown): string;
|
|
60
|
+
export declare function encodeError(id: RpcId, code: number, message: string, data?: unknown): string;
|
|
61
|
+
//# sourceMappingURL=rpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.d.ts","sourceRoot":"","sources":["../../../src/daemon/rpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,WAAW,QAAQ,CAAC;AAEjC,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAE3C,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,QAAQ,CAAC;AAGhD,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAC1C,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAC3C,eAAO,MAAM,kBAAkB,SAAS,CAAC;AACzC,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAGzC,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAC3C,eAAO,MAAM,iBAAiB,SAAS,CAAC;AACxC,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAE1C,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAuCtD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAGjE;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAI5F"}
|