colonies-ts 0.1.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/README.md +341 -0
- package/dist/index.d.mts +274 -0
- package/dist/index.d.ts +274 -0
- package/dist/index.js +976 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +944 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +57 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,944 @@
|
|
|
1
|
+
// src/crypto.ts
|
|
2
|
+
import { sha3_256 } from "@noble/hashes/sha3";
|
|
3
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
4
|
+
import { hmac } from "@noble/hashes/hmac";
|
|
5
|
+
import { bytesToHex, hexToBytes, randomBytes } from "@noble/hashes/utils";
|
|
6
|
+
var A = 0n;
|
|
7
|
+
var N = 115792089237316195423570985008687907852837564279074904382605163141518161494337n;
|
|
8
|
+
var Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240n;
|
|
9
|
+
var Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424n;
|
|
10
|
+
var G = [Gx, Gy];
|
|
11
|
+
var P = 2n ** 256n - 2n ** 32n - 977n;
|
|
12
|
+
function pad32(value) {
|
|
13
|
+
if (value.length >= 32) return value.slice(0, 32);
|
|
14
|
+
const padded = new Uint8Array(32);
|
|
15
|
+
padded.set(value, 32 - value.length);
|
|
16
|
+
return padded;
|
|
17
|
+
}
|
|
18
|
+
function intToBigEndian(value) {
|
|
19
|
+
if (value === 0n) return new Uint8Array([0]);
|
|
20
|
+
const hex = value.toString(16);
|
|
21
|
+
const paddedHex = hex.length % 2 ? "0" + hex : hex;
|
|
22
|
+
return hexToBytes(paddedHex);
|
|
23
|
+
}
|
|
24
|
+
function bigEndianToInt(value) {
|
|
25
|
+
if (value.length === 0) return 0n;
|
|
26
|
+
return BigInt("0x" + bytesToHex(value));
|
|
27
|
+
}
|
|
28
|
+
function inv(a, n) {
|
|
29
|
+
if (a === 0n) return 0n;
|
|
30
|
+
let lm = 1n, hm = 0n;
|
|
31
|
+
let low = (a % n + n) % n, high = n;
|
|
32
|
+
while (low > 1n) {
|
|
33
|
+
const r = high / low;
|
|
34
|
+
const nm = hm - lm * r;
|
|
35
|
+
const newVal = high - low * r;
|
|
36
|
+
hm = lm;
|
|
37
|
+
high = low;
|
|
38
|
+
lm = nm;
|
|
39
|
+
low = newVal;
|
|
40
|
+
}
|
|
41
|
+
return (lm % n + n) % n;
|
|
42
|
+
}
|
|
43
|
+
function toJacobian(p) {
|
|
44
|
+
return [p[0], p[1], 1n];
|
|
45
|
+
}
|
|
46
|
+
function fromJacobian(p) {
|
|
47
|
+
const z = inv(p[2], P);
|
|
48
|
+
const z2 = z * z % P;
|
|
49
|
+
const z3 = z2 * z % P;
|
|
50
|
+
return [(p[0] * z2 % P + P) % P, (p[1] * z3 % P + P) % P];
|
|
51
|
+
}
|
|
52
|
+
function jacobianDouble(p) {
|
|
53
|
+
if (p[1] === 0n) return [0n, 0n, 0n];
|
|
54
|
+
const ysq = p[1] ** 2n % P;
|
|
55
|
+
const S = 4n * p[0] * ysq % P;
|
|
56
|
+
const M = (3n * p[0] ** 2n + A * p[2] ** 4n) % P;
|
|
57
|
+
const nx = ((M ** 2n - 2n * S) % P + P) % P;
|
|
58
|
+
const ny = ((M * (S - nx) - 8n * ysq ** 2n) % P + P) % P;
|
|
59
|
+
const nz = 2n * p[1] * p[2] % P;
|
|
60
|
+
return [nx, ny, nz];
|
|
61
|
+
}
|
|
62
|
+
function jacobianAdd(p, q) {
|
|
63
|
+
if (p[1] === 0n) return q;
|
|
64
|
+
if (q[1] === 0n) return p;
|
|
65
|
+
const U1 = p[0] * q[2] ** 2n % P;
|
|
66
|
+
const U2 = q[0] * p[2] ** 2n % P;
|
|
67
|
+
const S1 = p[1] * q[2] ** 3n % P;
|
|
68
|
+
const S2 = q[1] * p[2] ** 3n % P;
|
|
69
|
+
if (U1 === U2) {
|
|
70
|
+
if (S1 !== S2) return [0n, 0n, 1n];
|
|
71
|
+
return jacobianDouble(p);
|
|
72
|
+
}
|
|
73
|
+
const H = ((U2 - U1) % P + P) % P;
|
|
74
|
+
const R = ((S2 - S1) % P + P) % P;
|
|
75
|
+
const H2 = H * H % P;
|
|
76
|
+
const H3 = H * H2 % P;
|
|
77
|
+
const U1H2 = U1 * H2 % P;
|
|
78
|
+
const nx = ((R ** 2n - H3 - 2n * U1H2) % P + P) % P;
|
|
79
|
+
const ny = ((R * (U1H2 - nx) - S1 * H3) % P + P) % P;
|
|
80
|
+
const nz = H * p[2] * q[2] % P;
|
|
81
|
+
return [nx, ny, nz];
|
|
82
|
+
}
|
|
83
|
+
function jacobianMultiply(a, n) {
|
|
84
|
+
if (a[1] === 0n || n === 0n) return [0n, 0n, 1n];
|
|
85
|
+
if (n === 1n) return a;
|
|
86
|
+
if (n < 0n || n >= N) return jacobianMultiply(a, (n % N + N) % N);
|
|
87
|
+
if (n % 2n === 0n) {
|
|
88
|
+
return jacobianDouble(jacobianMultiply(a, n / 2n));
|
|
89
|
+
} else {
|
|
90
|
+
return jacobianAdd(jacobianDouble(jacobianMultiply(a, n / 2n)), a);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function fastMultiply(a, n) {
|
|
94
|
+
return fromJacobian(jacobianMultiply(toJacobian(a), n));
|
|
95
|
+
}
|
|
96
|
+
function encodeRawPublicKey(rawPublicKey) {
|
|
97
|
+
const left = pad32(intToBigEndian(rawPublicKey[0]));
|
|
98
|
+
const right = pad32(intToBigEndian(rawPublicKey[1]));
|
|
99
|
+
const result = new Uint8Array(64);
|
|
100
|
+
result.set(left, 0);
|
|
101
|
+
result.set(right, 32);
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
function privateKeyToPublicKey(privateKeyBytes) {
|
|
105
|
+
const privateKeyAsNum = bigEndianToInt(privateKeyBytes);
|
|
106
|
+
if (privateKeyAsNum >= N) {
|
|
107
|
+
throw new Error("Invalid private key");
|
|
108
|
+
}
|
|
109
|
+
const rawPublicKey = fastMultiply(G, privateKeyAsNum);
|
|
110
|
+
return encodeRawPublicKey(rawPublicKey);
|
|
111
|
+
}
|
|
112
|
+
function deterministicGenerateK(msgHash, privateKeyBytes) {
|
|
113
|
+
const v0 = new Uint8Array(32).fill(1);
|
|
114
|
+
const k0 = new Uint8Array(32).fill(0);
|
|
115
|
+
const data1 = new Uint8Array(v0.length + 1 + privateKeyBytes.length + msgHash.length);
|
|
116
|
+
data1.set(v0, 0);
|
|
117
|
+
data1[v0.length] = 0;
|
|
118
|
+
data1.set(privateKeyBytes, v0.length + 1);
|
|
119
|
+
data1.set(msgHash, v0.length + 1 + privateKeyBytes.length);
|
|
120
|
+
const k1 = hmac(sha256, k0, data1);
|
|
121
|
+
const v1 = hmac(sha256, k1, v0);
|
|
122
|
+
const data2 = new Uint8Array(v1.length + 1 + privateKeyBytes.length + msgHash.length);
|
|
123
|
+
data2.set(v1, 0);
|
|
124
|
+
data2[v1.length] = 1;
|
|
125
|
+
data2.set(privateKeyBytes, v1.length + 1);
|
|
126
|
+
data2.set(msgHash, v1.length + 1 + privateKeyBytes.length);
|
|
127
|
+
const k2 = hmac(sha256, k1, data2);
|
|
128
|
+
const v2 = hmac(sha256, k2, v1);
|
|
129
|
+
const kb = hmac(sha256, k2, v2);
|
|
130
|
+
return bigEndianToInt(kb);
|
|
131
|
+
}
|
|
132
|
+
function ecdsaRawSign(msgHash, privateKeyBytes) {
|
|
133
|
+
const z = bigEndianToInt(msgHash);
|
|
134
|
+
const k = deterministicGenerateK(msgHash, privateKeyBytes);
|
|
135
|
+
const [r, y] = fastMultiply(G, k);
|
|
136
|
+
const privKeyNum = bigEndianToInt(privateKeyBytes);
|
|
137
|
+
const sRaw = inv(k, N) * (z + r * privKeyNum) % N;
|
|
138
|
+
const v = 27 + Number(y % 2n ^ (sRaw * 2n < N ? 0n : 1n));
|
|
139
|
+
const s = sRaw * 2n < N ? sRaw : N - sRaw;
|
|
140
|
+
return [v - 27, r, s];
|
|
141
|
+
}
|
|
142
|
+
function generatePrivateKey() {
|
|
143
|
+
const randomData = randomBytes(32);
|
|
144
|
+
const hash = sha3_256(randomData);
|
|
145
|
+
return bytesToHex(hash);
|
|
146
|
+
}
|
|
147
|
+
function deriveId(privateKey) {
|
|
148
|
+
const privateKeyBytes = hexToBytes(privateKey);
|
|
149
|
+
const publicKey = privateKeyToPublicKey(privateKeyBytes);
|
|
150
|
+
const publicKeyHex = "04" + bytesToHex(publicKey);
|
|
151
|
+
const encoder = new TextEncoder();
|
|
152
|
+
const hash = sha3_256(encoder.encode(publicKeyHex));
|
|
153
|
+
return bytesToHex(hash);
|
|
154
|
+
}
|
|
155
|
+
function sign(message, privateKey) {
|
|
156
|
+
const privateKeyBytes = hexToBytes(privateKey);
|
|
157
|
+
const encoder = new TextEncoder();
|
|
158
|
+
const msgHash = sha3_256(encoder.encode(message));
|
|
159
|
+
const [v, r, s] = ecdsaRawSign(msgHash, privateKeyBytes);
|
|
160
|
+
const vBytes = new Uint8Array([v]);
|
|
161
|
+
const rBytes = pad32(intToBigEndian(r));
|
|
162
|
+
const sBytes = pad32(intToBigEndian(s));
|
|
163
|
+
const signature = new Uint8Array(65);
|
|
164
|
+
signature.set(rBytes, 0);
|
|
165
|
+
signature.set(sBytes, 32);
|
|
166
|
+
signature.set(vBytes, 64);
|
|
167
|
+
return bytesToHex(signature);
|
|
168
|
+
}
|
|
169
|
+
var Crypto = class {
|
|
170
|
+
generatePrivateKey() {
|
|
171
|
+
return generatePrivateKey();
|
|
172
|
+
}
|
|
173
|
+
id(privateKey) {
|
|
174
|
+
return deriveId(privateKey);
|
|
175
|
+
}
|
|
176
|
+
sign(message, privateKey) {
|
|
177
|
+
return sign(message, privateKey);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// src/client.ts
|
|
182
|
+
function decodeBase64Utf8(base64) {
|
|
183
|
+
const binaryStr = atob(base64);
|
|
184
|
+
const bytes = new Uint8Array(binaryStr.length);
|
|
185
|
+
for (let i = 0; i < binaryStr.length; i++) {
|
|
186
|
+
bytes[i] = binaryStr.charCodeAt(i);
|
|
187
|
+
}
|
|
188
|
+
return new TextDecoder("utf-8").decode(bytes);
|
|
189
|
+
}
|
|
190
|
+
function encodeBase64Utf8(str) {
|
|
191
|
+
const utf8Bytes = new TextEncoder().encode(str);
|
|
192
|
+
const binaryStr = String.fromCharCode(...utf8Bytes);
|
|
193
|
+
return btoa(binaryStr);
|
|
194
|
+
}
|
|
195
|
+
var ProcessState = /* @__PURE__ */ ((ProcessState2) => {
|
|
196
|
+
ProcessState2[ProcessState2["WAITING"] = 0] = "WAITING";
|
|
197
|
+
ProcessState2[ProcessState2["RUNNING"] = 1] = "RUNNING";
|
|
198
|
+
ProcessState2[ProcessState2["SUCCESS"] = 2] = "SUCCESS";
|
|
199
|
+
ProcessState2[ProcessState2["FAILED"] = 3] = "FAILED";
|
|
200
|
+
return ProcessState2;
|
|
201
|
+
})(ProcessState || {});
|
|
202
|
+
var ColoniesClient = class {
|
|
203
|
+
constructor(config) {
|
|
204
|
+
this.privateKey = null;
|
|
205
|
+
this.host = config.host;
|
|
206
|
+
this.port = config.port;
|
|
207
|
+
this.tls = config.tls ?? false;
|
|
208
|
+
this.crypto = new Crypto();
|
|
209
|
+
}
|
|
210
|
+
setPrivateKey(privateKey) {
|
|
211
|
+
this.privateKey = privateKey;
|
|
212
|
+
}
|
|
213
|
+
getBaseUrl() {
|
|
214
|
+
const protocol = this.tls ? "https" : "http";
|
|
215
|
+
return `${protocol}://${this.host}:${this.port}/api`;
|
|
216
|
+
}
|
|
217
|
+
createRPCMsg(msg) {
|
|
218
|
+
if (!this.privateKey) {
|
|
219
|
+
throw new Error("Private key not set. Call setPrivateKey() first.");
|
|
220
|
+
}
|
|
221
|
+
const payload = encodeBase64Utf8(JSON.stringify(msg));
|
|
222
|
+
const signature = this.crypto.sign(payload, this.privateKey);
|
|
223
|
+
return {
|
|
224
|
+
payloadtype: msg.msgtype,
|
|
225
|
+
payload,
|
|
226
|
+
signature
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
async sendRPC(rpcMessage) {
|
|
230
|
+
const url = this.getBaseUrl();
|
|
231
|
+
const response = await fetch(url, {
|
|
232
|
+
method: "POST",
|
|
233
|
+
headers: {
|
|
234
|
+
"Content-Type": "application/json"
|
|
235
|
+
},
|
|
236
|
+
body: JSON.stringify(rpcMessage)
|
|
237
|
+
});
|
|
238
|
+
if (!response.ok) {
|
|
239
|
+
const errorText = await response.text();
|
|
240
|
+
let errorObj;
|
|
241
|
+
try {
|
|
242
|
+
errorObj = JSON.parse(errorText);
|
|
243
|
+
} catch {
|
|
244
|
+
throw new Error(`Request failed with status ${response.status}: ${response.statusText}`);
|
|
245
|
+
}
|
|
246
|
+
if (errorObj.payload) {
|
|
247
|
+
try {
|
|
248
|
+
const decodedPayload = decodeBase64Utf8(errorObj.payload);
|
|
249
|
+
const decodedError = JSON.parse(decodedPayload);
|
|
250
|
+
throw new Error(decodedError.message || JSON.stringify(decodedError));
|
|
251
|
+
} catch (e) {
|
|
252
|
+
if (e instanceof Error && e.message !== "Request failed") {
|
|
253
|
+
throw e;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
throw new Error(JSON.stringify(errorObj));
|
|
258
|
+
}
|
|
259
|
+
const responseText = await response.text();
|
|
260
|
+
if (!responseText || responseText.trim() === "") {
|
|
261
|
+
throw new Error("Server returned empty response");
|
|
262
|
+
}
|
|
263
|
+
const rpcReplyMsg = JSON.parse(responseText);
|
|
264
|
+
const msg = JSON.parse(decodeBase64Utf8(rpcReplyMsg.payload));
|
|
265
|
+
if (rpcReplyMsg.error === true) {
|
|
266
|
+
const errorMessage = typeof msg === "object" && msg.message ? msg.message : JSON.stringify(msg);
|
|
267
|
+
throw new Error(errorMessage);
|
|
268
|
+
}
|
|
269
|
+
return msg;
|
|
270
|
+
}
|
|
271
|
+
// ==================== Colony Methods ====================
|
|
272
|
+
async getColonies() {
|
|
273
|
+
const msg = { msgtype: "getcoloniesmsg" };
|
|
274
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
275
|
+
}
|
|
276
|
+
async getStatistics() {
|
|
277
|
+
const msg = { msgtype: "getstatisticsmsg" };
|
|
278
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Add a new colony (requires server private key)
|
|
282
|
+
* @param colony - Colony object with colonyid and name
|
|
283
|
+
*/
|
|
284
|
+
async addColony(colony) {
|
|
285
|
+
const msg = {
|
|
286
|
+
msgtype: "addcolonymsg",
|
|
287
|
+
colony
|
|
288
|
+
};
|
|
289
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Remove a colony (requires server private key)
|
|
293
|
+
* @param colonyName - Name of the colony to remove
|
|
294
|
+
*/
|
|
295
|
+
async removeColony(colonyName) {
|
|
296
|
+
const msg = {
|
|
297
|
+
msgtype: "removecolonymsg",
|
|
298
|
+
colonyname: colonyName
|
|
299
|
+
};
|
|
300
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
301
|
+
}
|
|
302
|
+
// ==================== Executor Methods ====================
|
|
303
|
+
async getExecutors(colonyName) {
|
|
304
|
+
const msg = {
|
|
305
|
+
msgtype: "getexecutorsmsg",
|
|
306
|
+
colonyname: colonyName
|
|
307
|
+
};
|
|
308
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
309
|
+
}
|
|
310
|
+
async getExecutor(colonyName, executorName) {
|
|
311
|
+
const msg = {
|
|
312
|
+
msgtype: "getexecutormsg",
|
|
313
|
+
colonyname: colonyName,
|
|
314
|
+
executorname: executorName
|
|
315
|
+
};
|
|
316
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
317
|
+
}
|
|
318
|
+
async addExecutor(executor) {
|
|
319
|
+
const msg = {
|
|
320
|
+
msgtype: "addexecutormsg",
|
|
321
|
+
executor
|
|
322
|
+
};
|
|
323
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
324
|
+
}
|
|
325
|
+
async approveExecutor(colonyName, executorName) {
|
|
326
|
+
const msg = {
|
|
327
|
+
msgtype: "approveexecutormsg",
|
|
328
|
+
colonyname: colonyName,
|
|
329
|
+
executorname: executorName
|
|
330
|
+
};
|
|
331
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
332
|
+
}
|
|
333
|
+
async removeExecutor(colonyName, executorName) {
|
|
334
|
+
const msg = {
|
|
335
|
+
msgtype: "removeexecutormsg",
|
|
336
|
+
colonyname: colonyName,
|
|
337
|
+
executorname: executorName
|
|
338
|
+
};
|
|
339
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
340
|
+
}
|
|
341
|
+
// ==================== Process Methods ====================
|
|
342
|
+
async submitFunctionSpec(spec) {
|
|
343
|
+
const msg = {
|
|
344
|
+
msgtype: "submitfuncspecmsg",
|
|
345
|
+
spec
|
|
346
|
+
};
|
|
347
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
348
|
+
}
|
|
349
|
+
async getProcess(processId) {
|
|
350
|
+
const msg = {
|
|
351
|
+
msgtype: "getprocessmsg",
|
|
352
|
+
processid: processId
|
|
353
|
+
};
|
|
354
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
355
|
+
}
|
|
356
|
+
async getProcesses(colonyName, count, state) {
|
|
357
|
+
const msg = {
|
|
358
|
+
msgtype: "getprocessesmsg",
|
|
359
|
+
colonyname: colonyName,
|
|
360
|
+
count,
|
|
361
|
+
state
|
|
362
|
+
};
|
|
363
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
364
|
+
}
|
|
365
|
+
async removeProcess(processId) {
|
|
366
|
+
const msg = {
|
|
367
|
+
msgtype: "removeprocessmsg",
|
|
368
|
+
processid: processId,
|
|
369
|
+
all: false
|
|
370
|
+
};
|
|
371
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
372
|
+
}
|
|
373
|
+
async removeAllProcesses(colonyName, state = -1) {
|
|
374
|
+
const msg = {
|
|
375
|
+
msgtype: "removeallprocessesmsg",
|
|
376
|
+
colonyname: colonyName,
|
|
377
|
+
state
|
|
378
|
+
};
|
|
379
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
380
|
+
}
|
|
381
|
+
async assign(colonyName, timeout, executorPrvKey) {
|
|
382
|
+
const originalKey = this.privateKey;
|
|
383
|
+
this.setPrivateKey(executorPrvKey);
|
|
384
|
+
try {
|
|
385
|
+
const msg = {
|
|
386
|
+
msgtype: "assignprocessmsg",
|
|
387
|
+
colonyname: colonyName,
|
|
388
|
+
timeout
|
|
389
|
+
};
|
|
390
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
391
|
+
} finally {
|
|
392
|
+
if (originalKey) {
|
|
393
|
+
this.setPrivateKey(originalKey);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
async closeProcess(processId, output) {
|
|
398
|
+
const msg = {
|
|
399
|
+
msgtype: "closesuccessfulmsg",
|
|
400
|
+
processid: processId,
|
|
401
|
+
out: output
|
|
402
|
+
};
|
|
403
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
404
|
+
}
|
|
405
|
+
async failProcess(processId, errors) {
|
|
406
|
+
const msg = {
|
|
407
|
+
msgtype: "closefailedmsg",
|
|
408
|
+
processid: processId,
|
|
409
|
+
errors
|
|
410
|
+
};
|
|
411
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
412
|
+
}
|
|
413
|
+
// ==================== Workflow Methods ====================
|
|
414
|
+
async submitWorkflowSpec(workflowSpec) {
|
|
415
|
+
const msg = {
|
|
416
|
+
msgtype: "submitworkflowspecmsg",
|
|
417
|
+
spec: workflowSpec
|
|
418
|
+
};
|
|
419
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
420
|
+
}
|
|
421
|
+
async getProcessGraph(processGraphId) {
|
|
422
|
+
const msg = {
|
|
423
|
+
msgtype: "getprocessgraphmsg",
|
|
424
|
+
processgraphid: processGraphId
|
|
425
|
+
};
|
|
426
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
427
|
+
}
|
|
428
|
+
async getProcessGraphs(colonyName, count, state) {
|
|
429
|
+
const msg = {
|
|
430
|
+
msgtype: "getprocessgraphsmsg",
|
|
431
|
+
colonyname: colonyName,
|
|
432
|
+
count
|
|
433
|
+
};
|
|
434
|
+
if (state !== void 0) {
|
|
435
|
+
msg.state = state;
|
|
436
|
+
}
|
|
437
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
438
|
+
}
|
|
439
|
+
async removeProcessGraph(processGraphId) {
|
|
440
|
+
const msg = {
|
|
441
|
+
msgtype: "removeprocessgraphmsg",
|
|
442
|
+
processgraphid: processGraphId
|
|
443
|
+
};
|
|
444
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
445
|
+
}
|
|
446
|
+
async removeAllProcessGraphs(colonyName, state) {
|
|
447
|
+
const msg = {
|
|
448
|
+
msgtype: "removeallprocessgraphsmsg",
|
|
449
|
+
colonyname: colonyName
|
|
450
|
+
};
|
|
451
|
+
if (state !== void 0) {
|
|
452
|
+
msg.state = state;
|
|
453
|
+
}
|
|
454
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
455
|
+
}
|
|
456
|
+
// ==================== Log Methods ====================
|
|
457
|
+
async addLog(processId, message, executorPrvKey) {
|
|
458
|
+
const originalKey = this.privateKey;
|
|
459
|
+
this.setPrivateKey(executorPrvKey);
|
|
460
|
+
try {
|
|
461
|
+
const msg = {
|
|
462
|
+
msgtype: "addlogmsg",
|
|
463
|
+
processid: processId,
|
|
464
|
+
message
|
|
465
|
+
};
|
|
466
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
467
|
+
} finally {
|
|
468
|
+
if (originalKey) {
|
|
469
|
+
this.setPrivateKey(originalKey);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
async getLogs(colonyName, processId, executorName, count = 100, since = 0) {
|
|
474
|
+
const msg = {
|
|
475
|
+
msgtype: "getlogsmsg",
|
|
476
|
+
colonyname: colonyName,
|
|
477
|
+
processid: processId,
|
|
478
|
+
executorname: executorName,
|
|
479
|
+
count,
|
|
480
|
+
since
|
|
481
|
+
};
|
|
482
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
483
|
+
}
|
|
484
|
+
// ==================== Function Methods ====================
|
|
485
|
+
async getFunctions(executorName, colonyName) {
|
|
486
|
+
const msg = {
|
|
487
|
+
msgtype: "getfunctionsmsg",
|
|
488
|
+
executorname: executorName,
|
|
489
|
+
colonyname: colonyName
|
|
490
|
+
};
|
|
491
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
492
|
+
}
|
|
493
|
+
// ==================== Cron Methods ====================
|
|
494
|
+
async getCrons(colonyName, count = 100) {
|
|
495
|
+
const msg = {
|
|
496
|
+
msgtype: "getcronsmsg",
|
|
497
|
+
colonyname: colonyName,
|
|
498
|
+
count
|
|
499
|
+
};
|
|
500
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
501
|
+
}
|
|
502
|
+
async getCron(cronId) {
|
|
503
|
+
const msg = {
|
|
504
|
+
msgtype: "getcronmsg",
|
|
505
|
+
cronid: cronId
|
|
506
|
+
};
|
|
507
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
508
|
+
}
|
|
509
|
+
async addCron(cronSpec) {
|
|
510
|
+
const msg = {
|
|
511
|
+
msgtype: "addcronmsg",
|
|
512
|
+
cron: cronSpec
|
|
513
|
+
};
|
|
514
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
515
|
+
}
|
|
516
|
+
async removeCron(cronId) {
|
|
517
|
+
const msg = {
|
|
518
|
+
msgtype: "removecronmsg",
|
|
519
|
+
cronid: cronId
|
|
520
|
+
};
|
|
521
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
522
|
+
}
|
|
523
|
+
// ==================== Generator Methods ====================
|
|
524
|
+
async getGenerators(colonyName, count = 100) {
|
|
525
|
+
const msg = {
|
|
526
|
+
msgtype: "getgeneratorsmsg",
|
|
527
|
+
colonyname: colonyName,
|
|
528
|
+
count
|
|
529
|
+
};
|
|
530
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
531
|
+
}
|
|
532
|
+
async getGenerator(generatorId) {
|
|
533
|
+
const msg = {
|
|
534
|
+
msgtype: "getgeneratormsg",
|
|
535
|
+
generatorid: generatorId
|
|
536
|
+
};
|
|
537
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
538
|
+
}
|
|
539
|
+
async addGenerator(generatorSpec) {
|
|
540
|
+
const msg = {
|
|
541
|
+
msgtype: "addgeneratormsg",
|
|
542
|
+
generator: generatorSpec
|
|
543
|
+
};
|
|
544
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
545
|
+
}
|
|
546
|
+
// ==================== User Methods ====================
|
|
547
|
+
async getUsers(colonyName) {
|
|
548
|
+
const msg = {
|
|
549
|
+
msgtype: "getusersmsg",
|
|
550
|
+
colonyname: colonyName
|
|
551
|
+
};
|
|
552
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
553
|
+
}
|
|
554
|
+
async addUser(user) {
|
|
555
|
+
const msg = {
|
|
556
|
+
msgtype: "addusermsg",
|
|
557
|
+
user
|
|
558
|
+
};
|
|
559
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
560
|
+
}
|
|
561
|
+
async removeUser(colonyName, name) {
|
|
562
|
+
const msg = {
|
|
563
|
+
msgtype: "removeusermsg",
|
|
564
|
+
colonyname: colonyName,
|
|
565
|
+
name
|
|
566
|
+
};
|
|
567
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
568
|
+
}
|
|
569
|
+
// ==================== File Methods ====================
|
|
570
|
+
async getFileLabels(colonyName, name = "", exact = false) {
|
|
571
|
+
const msg = {
|
|
572
|
+
msgtype: "getfilelabelsmsg",
|
|
573
|
+
colonyname: colonyName,
|
|
574
|
+
name,
|
|
575
|
+
exact
|
|
576
|
+
};
|
|
577
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
578
|
+
}
|
|
579
|
+
async getFiles(colonyName, label) {
|
|
580
|
+
const msg = {
|
|
581
|
+
msgtype: "getfilesmsg",
|
|
582
|
+
colonyname: colonyName,
|
|
583
|
+
label
|
|
584
|
+
};
|
|
585
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
586
|
+
}
|
|
587
|
+
// ==================== Attribute Methods ====================
|
|
588
|
+
async addAttribute(attribute) {
|
|
589
|
+
const msg = {
|
|
590
|
+
msgtype: "addattributemsg",
|
|
591
|
+
attribute
|
|
592
|
+
};
|
|
593
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
594
|
+
}
|
|
595
|
+
async getAttribute(attributeId) {
|
|
596
|
+
const msg = {
|
|
597
|
+
msgtype: "getattributemsg",
|
|
598
|
+
attributeid: attributeId
|
|
599
|
+
};
|
|
600
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
601
|
+
}
|
|
602
|
+
// ==================== Channel Methods ====================
|
|
603
|
+
/**
|
|
604
|
+
* Append a message to a process channel
|
|
605
|
+
* @param processId - ID of the process
|
|
606
|
+
* @param channelName - Name of the channel
|
|
607
|
+
* @param sequence - Client-assigned sequence number
|
|
608
|
+
* @param inReplyTo - Sequence number this message is replying to (0 if not a reply)
|
|
609
|
+
* @param payload - Message content (string or Uint8Array)
|
|
610
|
+
*/
|
|
611
|
+
async channelAppend(processId, channelName, sequence, inReplyTo, payload) {
|
|
612
|
+
let payloadBytes;
|
|
613
|
+
if (typeof payload === "string") {
|
|
614
|
+
const encoder = new TextEncoder();
|
|
615
|
+
payloadBytes = Array.from(encoder.encode(payload));
|
|
616
|
+
} else {
|
|
617
|
+
payloadBytes = Array.from(payload);
|
|
618
|
+
}
|
|
619
|
+
const msg = {
|
|
620
|
+
msgtype: "channelappendmsg",
|
|
621
|
+
processid: processId,
|
|
622
|
+
name: channelName,
|
|
623
|
+
sequence,
|
|
624
|
+
inreplyto: inReplyTo,
|
|
625
|
+
payload: payloadBytes
|
|
626
|
+
};
|
|
627
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Read messages from a process channel
|
|
631
|
+
* @param processId - ID of the process
|
|
632
|
+
* @param channelName - Name of the channel
|
|
633
|
+
* @param afterSeq - Read messages after this sequence number (use 0 for all)
|
|
634
|
+
* @param limit - Maximum number of messages to return (0 for no limit)
|
|
635
|
+
*/
|
|
636
|
+
async channelRead(processId, channelName, afterSeq, limit) {
|
|
637
|
+
const msg = {
|
|
638
|
+
msgtype: "channelreadmsg",
|
|
639
|
+
processid: processId,
|
|
640
|
+
name: channelName,
|
|
641
|
+
afterseq: afterSeq,
|
|
642
|
+
limit
|
|
643
|
+
};
|
|
644
|
+
const response = await this.sendRPC(this.createRPCMsg(msg));
|
|
645
|
+
if (Array.isArray(response)) {
|
|
646
|
+
return response.map((entry) => ({
|
|
647
|
+
...entry,
|
|
648
|
+
payload: typeof entry.payload === "string" ? (() => {
|
|
649
|
+
try {
|
|
650
|
+
const binaryStr = atob(entry.payload);
|
|
651
|
+
const bytes = new Uint8Array(binaryStr.length);
|
|
652
|
+
for (let i = 0; i < binaryStr.length; i++) {
|
|
653
|
+
bytes[i] = binaryStr.charCodeAt(i);
|
|
654
|
+
}
|
|
655
|
+
return new TextDecoder("utf-8").decode(bytes);
|
|
656
|
+
} catch {
|
|
657
|
+
return entry.payload;
|
|
658
|
+
}
|
|
659
|
+
})() : Array.isArray(entry.payload) ? new TextDecoder("utf-8").decode(new Uint8Array(entry.payload)) : entry.payload
|
|
660
|
+
}));
|
|
661
|
+
}
|
|
662
|
+
return response || [];
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Subscribe to a channel using WebSocket for real-time updates
|
|
666
|
+
* @param processId - ID of the process
|
|
667
|
+
* @param channelName - Name of the channel
|
|
668
|
+
* @param afterSeq - Start reading after this sequence number
|
|
669
|
+
* @param timeout - Timeout in seconds for the subscription
|
|
670
|
+
* @param onMessage - Callback for new messages
|
|
671
|
+
* @param onError - Callback for errors
|
|
672
|
+
* @param onClose - Callback when connection closes
|
|
673
|
+
* @returns WebSocket instance for cleanup
|
|
674
|
+
*/
|
|
675
|
+
subscribeChannel(processId, channelName, afterSeq, timeout, onMessage, onError, onClose) {
|
|
676
|
+
if (!this.privateKey) {
|
|
677
|
+
throw new Error("Private key not set. Call setPrivateKey() first.");
|
|
678
|
+
}
|
|
679
|
+
const wsProtocol = this.tls ? "wss" : "ws";
|
|
680
|
+
const wsUrl = `${wsProtocol}://${this.host}:${this.port}/pubsub`;
|
|
681
|
+
const ws = new WebSocket(wsUrl);
|
|
682
|
+
ws.onopen = () => {
|
|
683
|
+
const msg = {
|
|
684
|
+
msgtype: "subscribechannelmsg",
|
|
685
|
+
processid: processId,
|
|
686
|
+
name: channelName,
|
|
687
|
+
afterseq: afterSeq,
|
|
688
|
+
timeout
|
|
689
|
+
};
|
|
690
|
+
const rpcMsg = this.createRPCMsg(msg);
|
|
691
|
+
ws.send(JSON.stringify(rpcMsg));
|
|
692
|
+
};
|
|
693
|
+
ws.onmessage = (event) => {
|
|
694
|
+
try {
|
|
695
|
+
const rpcReply = JSON.parse(event.data);
|
|
696
|
+
if (rpcReply.error) {
|
|
697
|
+
const errorPayload = JSON.parse(decodeBase64Utf8(rpcReply.payload));
|
|
698
|
+
onError(new Error(errorPayload.message || "WebSocket error"));
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
const data = JSON.parse(decodeBase64Utf8(rpcReply.payload));
|
|
702
|
+
if (Array.isArray(data)) {
|
|
703
|
+
const entries = data.map((entry) => ({
|
|
704
|
+
...entry,
|
|
705
|
+
payload: typeof entry.payload === "string" ? (() => {
|
|
706
|
+
try {
|
|
707
|
+
const binaryStr = atob(entry.payload);
|
|
708
|
+
const bytes = new Uint8Array(binaryStr.length);
|
|
709
|
+
for (let i = 0; i < binaryStr.length; i++) {
|
|
710
|
+
bytes[i] = binaryStr.charCodeAt(i);
|
|
711
|
+
}
|
|
712
|
+
return new TextDecoder("utf-8").decode(bytes);
|
|
713
|
+
} catch {
|
|
714
|
+
return entry.payload;
|
|
715
|
+
}
|
|
716
|
+
})() : Array.isArray(entry.payload) ? new TextDecoder("utf-8").decode(new Uint8Array(entry.payload)) : entry.payload
|
|
717
|
+
}));
|
|
718
|
+
const errorEntry = entries.find((e) => e.error);
|
|
719
|
+
if (errorEntry) {
|
|
720
|
+
onError(new Error(errorEntry.error));
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
onMessage(entries);
|
|
724
|
+
}
|
|
725
|
+
} catch (err) {
|
|
726
|
+
onError(err instanceof Error ? err : new Error(String(err)));
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
ws.onerror = () => {
|
|
730
|
+
onError(new Error("WebSocket connection error"));
|
|
731
|
+
};
|
|
732
|
+
ws.onclose = () => {
|
|
733
|
+
onClose();
|
|
734
|
+
};
|
|
735
|
+
return ws;
|
|
736
|
+
}
|
|
737
|
+
// ==================== Blueprint Definition Methods ====================
|
|
738
|
+
/**
|
|
739
|
+
* Add a blueprint definition
|
|
740
|
+
* @param definition - Blueprint definition object
|
|
741
|
+
*/
|
|
742
|
+
async addBlueprintDefinition(definition) {
|
|
743
|
+
const msg = {
|
|
744
|
+
msgtype: "addblueprintdefinitionmsg",
|
|
745
|
+
blueprintdefinition: definition
|
|
746
|
+
};
|
|
747
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Get a blueprint definition by name
|
|
751
|
+
* @param colonyName - Name of the colony
|
|
752
|
+
* @param name - Name of the blueprint definition
|
|
753
|
+
*/
|
|
754
|
+
async getBlueprintDefinition(colonyName, name) {
|
|
755
|
+
const msg = {
|
|
756
|
+
msgtype: "getblueprintdefinitionmsg",
|
|
757
|
+
colonyname: colonyName,
|
|
758
|
+
name
|
|
759
|
+
};
|
|
760
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Get all blueprint definitions in a colony
|
|
764
|
+
* @param colonyName - Name of the colony
|
|
765
|
+
*/
|
|
766
|
+
async getBlueprintDefinitions(colonyName) {
|
|
767
|
+
const msg = {
|
|
768
|
+
msgtype: "getblueprintdefinitionsmsg",
|
|
769
|
+
colonyname: colonyName
|
|
770
|
+
};
|
|
771
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Remove a blueprint definition
|
|
775
|
+
* @param colonyName - Name of the colony (namespace)
|
|
776
|
+
* @param name - Name of the blueprint definition to remove
|
|
777
|
+
*/
|
|
778
|
+
async removeBlueprintDefinition(colonyName, name) {
|
|
779
|
+
const msg = {
|
|
780
|
+
msgtype: "removeblueprintdefinitionmsg",
|
|
781
|
+
namespace: colonyName,
|
|
782
|
+
name
|
|
783
|
+
};
|
|
784
|
+
await this.sendRPC(this.createRPCMsg(msg));
|
|
785
|
+
}
|
|
786
|
+
// ==================== Blueprint Methods ====================
|
|
787
|
+
/**
|
|
788
|
+
* Add a blueprint instance
|
|
789
|
+
* @param blueprint - Blueprint object
|
|
790
|
+
*/
|
|
791
|
+
async addBlueprint(blueprint) {
|
|
792
|
+
const msg = {
|
|
793
|
+
msgtype: "addblueprintmsg",
|
|
794
|
+
blueprint
|
|
795
|
+
};
|
|
796
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Get a blueprint by name
|
|
800
|
+
* @param colonyName - Name of the colony (namespace)
|
|
801
|
+
* @param name - Name of the blueprint
|
|
802
|
+
*/
|
|
803
|
+
async getBlueprint(colonyName, name) {
|
|
804
|
+
const msg = {
|
|
805
|
+
msgtype: "getblueprintmsg",
|
|
806
|
+
namespace: colonyName,
|
|
807
|
+
name
|
|
808
|
+
};
|
|
809
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Get blueprints in a colony, optionally filtered by kind and location
|
|
813
|
+
* @param colonyName - Name of the colony (namespace)
|
|
814
|
+
* @param kind - Optional kind filter
|
|
815
|
+
* @param location - Optional location filter
|
|
816
|
+
*/
|
|
817
|
+
async getBlueprints(colonyName, kind, location) {
|
|
818
|
+
const msg = {
|
|
819
|
+
msgtype: "getblueprintsmsg",
|
|
820
|
+
namespace: colonyName
|
|
821
|
+
};
|
|
822
|
+
if (kind) msg.kind = kind;
|
|
823
|
+
if (location) msg.locationname = location;
|
|
824
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Update an existing blueprint
|
|
828
|
+
* @param blueprint - Updated blueprint object
|
|
829
|
+
* @param forceGeneration - Force generation bump even if spec unchanged
|
|
830
|
+
*/
|
|
831
|
+
async updateBlueprint(blueprint, forceGeneration = false) {
|
|
832
|
+
const msg = {
|
|
833
|
+
msgtype: "updateblueprintmsg",
|
|
834
|
+
blueprint,
|
|
835
|
+
forcegeneration: forceGeneration
|
|
836
|
+
};
|
|
837
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* Remove a blueprint
|
|
841
|
+
* @param colonyName - Name of the colony (namespace)
|
|
842
|
+
* @param name - Name of the blueprint to remove
|
|
843
|
+
*/
|
|
844
|
+
async removeBlueprint(colonyName, name) {
|
|
845
|
+
const msg = {
|
|
846
|
+
msgtype: "removeblueprintmsg",
|
|
847
|
+
namespace: colonyName,
|
|
848
|
+
name
|
|
849
|
+
};
|
|
850
|
+
await this.sendRPC(this.createRPCMsg(msg));
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Update blueprint status (current state)
|
|
854
|
+
* @param colonyName - Name of the colony
|
|
855
|
+
* @param name - Name of the blueprint
|
|
856
|
+
* @param status - Status object representing current state
|
|
857
|
+
*/
|
|
858
|
+
async updateBlueprintStatus(colonyName, name, status) {
|
|
859
|
+
const msg = {
|
|
860
|
+
msgtype: "updateblueprintstatusmsg",
|
|
861
|
+
colonyname: colonyName,
|
|
862
|
+
blueprintname: name,
|
|
863
|
+
status
|
|
864
|
+
};
|
|
865
|
+
await this.sendRPC(this.createRPCMsg(msg));
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Trigger reconciliation for a blueprint
|
|
869
|
+
* @param colonyName - Name of the colony (namespace)
|
|
870
|
+
* @param name - Name of the blueprint
|
|
871
|
+
* @param force - Force reconciliation even if no changes detected
|
|
872
|
+
*/
|
|
873
|
+
async reconcileBlueprint(colonyName, name, force = false) {
|
|
874
|
+
const msg = {
|
|
875
|
+
msgtype: "reconcileblueprintmsg",
|
|
876
|
+
namespace: colonyName,
|
|
877
|
+
name,
|
|
878
|
+
force
|
|
879
|
+
};
|
|
880
|
+
return this.sendRPC(this.createRPCMsg(msg));
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Subscribe to process state changes using WebSocket
|
|
884
|
+
* Use this to wait for a process to be assigned (RUNNING state) before subscribing to channels
|
|
885
|
+
* @param colonyName - Name of the colony
|
|
886
|
+
* @param processId - ID of the process to watch
|
|
887
|
+
* @param state - Target state to wait for (0=WAITING, 1=RUNNING, 2=SUCCESS, 3=FAILED)
|
|
888
|
+
* @param timeout - Timeout in seconds for the subscription
|
|
889
|
+
* @param onProcess - Callback when process reaches the target state
|
|
890
|
+
* @param onError - Callback for errors
|
|
891
|
+
* @param onClose - Callback when connection closes
|
|
892
|
+
* @returns WebSocket instance for cleanup
|
|
893
|
+
*/
|
|
894
|
+
subscribeProcess(colonyName, processId, state, timeout, onProcess, onError, onClose) {
|
|
895
|
+
if (!this.privateKey) {
|
|
896
|
+
throw new Error("Private key not set. Call setPrivateKey() first.");
|
|
897
|
+
}
|
|
898
|
+
const wsProtocol = this.tls ? "wss" : "ws";
|
|
899
|
+
const wsUrl = `${wsProtocol}://${this.host}:${this.port}/pubsub`;
|
|
900
|
+
const ws = new WebSocket(wsUrl);
|
|
901
|
+
ws.onopen = () => {
|
|
902
|
+
const msg = {
|
|
903
|
+
msgtype: "subscribeprocessmsg",
|
|
904
|
+
colonyname: colonyName,
|
|
905
|
+
processid: processId,
|
|
906
|
+
executortype: "",
|
|
907
|
+
state,
|
|
908
|
+
timeout
|
|
909
|
+
};
|
|
910
|
+
const rpcMsg = this.createRPCMsg(msg);
|
|
911
|
+
ws.send(JSON.stringify(rpcMsg));
|
|
912
|
+
};
|
|
913
|
+
ws.onmessage = (event) => {
|
|
914
|
+
try {
|
|
915
|
+
const rpcReply = JSON.parse(event.data);
|
|
916
|
+
if (rpcReply.error) {
|
|
917
|
+
const errorPayload = JSON.parse(decodeBase64Utf8(rpcReply.payload));
|
|
918
|
+
onError(new Error(errorPayload.message || "WebSocket error"));
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
const process = JSON.parse(decodeBase64Utf8(rpcReply.payload));
|
|
922
|
+
onProcess(process);
|
|
923
|
+
} catch (err) {
|
|
924
|
+
onError(err instanceof Error ? err : new Error(String(err)));
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
ws.onerror = () => {
|
|
928
|
+
onError(new Error("WebSocket connection error"));
|
|
929
|
+
};
|
|
930
|
+
ws.onclose = () => {
|
|
931
|
+
onClose();
|
|
932
|
+
};
|
|
933
|
+
return ws;
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
export {
|
|
937
|
+
ColoniesClient,
|
|
938
|
+
Crypto,
|
|
939
|
+
ProcessState,
|
|
940
|
+
deriveId,
|
|
941
|
+
generatePrivateKey,
|
|
942
|
+
sign
|
|
943
|
+
};
|
|
944
|
+
//# sourceMappingURL=index.mjs.map
|