@tdxvolt/volt-client-grpc 0.1.2 → 0.11.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/lib/index.cjs +422 -356
- package/package.json +2 -2
- package/protobuf/tdx/volt_api/data/v1/sqlite.proto +13 -13
- package/protobuf/tdx/volt_api/volt/v1/volt.proto +3 -0
- package/protobuf/tdx/volt_api/volt/v1/wire_api.proto +1 -1
- package/src/grpc-call.js +269 -246
- package/src/volt-client-internal.js +93 -51
- package/src/volt-client.js +65 -64
|
@@ -82,19 +82,21 @@ export async function bindInternal() {
|
|
|
82
82
|
try {
|
|
83
83
|
// Check if we need to resolve a Relay volt.
|
|
84
84
|
if (
|
|
85
|
-
this.
|
|
86
|
-
|
|
85
|
+
typeof this._voltConfig?.relay === "string" ||
|
|
86
|
+
this._voltConfig?.relay?.http_address
|
|
87
87
|
) {
|
|
88
|
-
const relayURL =
|
|
88
|
+
const relayURL =
|
|
89
|
+
this._voltConfig.relay?.http_address || this._voltConfig.relay;
|
|
89
90
|
log("attempting to retrieve Relay information from %s", relayURL);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
this._voltConfig.relay = await fetchVoltConfig.call(
|
|
92
|
+
this,
|
|
93
|
+
`${relayURL}/discovery`,
|
|
94
|
+
);
|
|
95
|
+
if (this._voltConfig.relay.ca_pem) {
|
|
94
96
|
log(
|
|
95
97
|
"Auto-fetched Relay CA %s, remote address %s",
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
98
|
+
this._voltConfig.relay.ca_pem,
|
|
99
|
+
this._voltConfig.relay.address,
|
|
98
100
|
);
|
|
99
101
|
} else {
|
|
100
102
|
throw new Error("Unable to fetch Relay CA - cannot securely connect.");
|
|
@@ -256,8 +258,8 @@ export function getVoltAPIClientInternal() {
|
|
|
256
258
|
serviceAddress,
|
|
257
259
|
this._credential,
|
|
258
260
|
this.isRemote && !this.isVoltRelay,
|
|
259
|
-
this._config?.relay?.
|
|
260
|
-
this._config?.relay?.
|
|
261
|
+
this._config?.relay?.cloud ? this._voltConfig.id : "",
|
|
262
|
+
this._config?.relay?.cloud ? this._voltConfig.id : "",
|
|
261
263
|
);
|
|
262
264
|
}
|
|
263
265
|
|
|
@@ -265,53 +267,93 @@ export function getVoltAPIClientInternal() {
|
|
|
265
267
|
}
|
|
266
268
|
|
|
267
269
|
export function unaryCall(method, request) {
|
|
268
|
-
|
|
270
|
+
return new Promise((resolve, reject) => {
|
|
271
|
+
const grpcClient = this.getVoltAPIClient();
|
|
272
|
+
|
|
273
|
+
const call = new GRPCCall(this, method, "METHOD_TYPE_UNARY");
|
|
274
|
+
|
|
275
|
+
let response = null;
|
|
276
|
+
|
|
277
|
+
call.on("data", (payload) => {
|
|
278
|
+
// Cache the response and wait for `end`.
|
|
279
|
+
response = payload;
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
call.on("error", reject);
|
|
283
|
+
|
|
284
|
+
call.on("end", () => {
|
|
285
|
+
if (!response) {
|
|
286
|
+
return reject(new Error("no response received"));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Convert non-OK status to a JS error.
|
|
290
|
+
if (response.status?.message) {
|
|
291
|
+
reject(new Error(response.status.message));
|
|
292
|
+
} else {
|
|
293
|
+
resolve(response);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
269
296
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return call.wait();
|
|
297
|
+
call.start(grpcClient, request);
|
|
298
|
+
});
|
|
273
299
|
}
|
|
274
300
|
|
|
275
|
-
export async function fetchVoltConfig(
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
301
|
+
export async function fetchVoltConfig(discovery_url) {
|
|
302
|
+
try {
|
|
303
|
+
const getJSON = bent("json");
|
|
304
|
+
const fullVoltConfig = await getJSON(discovery_url);
|
|
305
|
+
|
|
306
|
+
if (!fullVoltConfig || typeof fullVoltConfig !== "object") {
|
|
307
|
+
throw new Error(`invalid config resolved from: ${discovery_url}`);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const voltConfig = pick(
|
|
311
|
+
fullVoltConfig,
|
|
312
|
+
"id",
|
|
313
|
+
"display_name",
|
|
314
|
+
"public_key",
|
|
315
|
+
"fingerprint",
|
|
316
|
+
"address",
|
|
317
|
+
"ca_pem",
|
|
318
|
+
"challenge_code",
|
|
319
|
+
"cloud",
|
|
320
|
+
"relay",
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
return voltConfig;
|
|
324
|
+
} catch (err) {
|
|
325
|
+
throw new Error(
|
|
326
|
+
`Failure loading config from ${discovery_url}: ${err.message}`,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
294
329
|
}
|
|
295
330
|
|
|
296
331
|
export async function fetchVoltConfigFromDID(volt_did) {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
332
|
+
try {
|
|
333
|
+
const didResolution = voltUtils.getDIDResolutionURL(volt_did);
|
|
334
|
+
if (!didResolution) {
|
|
335
|
+
throw new Error(`Invalid Volt DID: ${volt_did}`);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const getJSON = bent("json");
|
|
339
|
+
const didDocument = await getJSON(didResolution);
|
|
340
|
+
const voltConfigServices = findDIDDocumentService(
|
|
341
|
+
didDocument,
|
|
342
|
+
constants.didServiceType.voltConfig,
|
|
343
|
+
);
|
|
344
|
+
if (voltConfigServices.length !== 1) {
|
|
345
|
+
log(
|
|
346
|
+
"Unexpected number of Volt configuration endpoints found in DID document for %s, services found: %d",
|
|
347
|
+
volt_did,
|
|
348
|
+
voltConfigServices.length,
|
|
349
|
+
);
|
|
350
|
+
}
|
|
301
351
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
);
|
|
308
|
-
if (voltConfigServices.length !== 1) {
|
|
309
|
-
log(
|
|
310
|
-
"Unexpected number of Volt configuration endpoints found in DID document for %s, services found: %d",
|
|
311
|
-
volt_did,
|
|
312
|
-
voltConfigServices.length,
|
|
352
|
+
const serviceEndpoint = voltConfigServices[0].serviceEndpoint;
|
|
353
|
+
return await fetchVoltConfig.call(this, serviceEndpoint);
|
|
354
|
+
} catch (err) {
|
|
355
|
+
throw new Error(
|
|
356
|
+
`Failure fetching Volt config from DID document ${volt_did}: ${err.message}`,
|
|
313
357
|
);
|
|
314
358
|
}
|
|
315
|
-
const serviceEndpoint = voltConfigServices[0].serviceEndpoint;
|
|
316
|
-
return await fetchVoltConfig.call(this, serviceEndpoint);
|
|
317
359
|
}
|
package/src/volt-client.js
CHANGED
|
@@ -101,32 +101,38 @@ export class VoltClient extends EventEmitter {
|
|
|
101
101
|
this._config = { ...configJSON, ...extras };
|
|
102
102
|
|
|
103
103
|
let voltDID = "";
|
|
104
|
-
let
|
|
104
|
+
let voltHttpAddress = "";
|
|
105
105
|
if (typeof this._config.volt === "string") {
|
|
106
106
|
if (this._config.volt.indexOf("did:") === 0) {
|
|
107
107
|
voltDID = this._config.volt;
|
|
108
108
|
} else {
|
|
109
|
-
|
|
109
|
+
voltHttpAddress = this._config.volt;
|
|
110
110
|
}
|
|
111
111
|
} else if (typeof this._config.volt !== "object") {
|
|
112
112
|
throw new Error("configuration is missing the 'volt' object");
|
|
113
113
|
} else {
|
|
114
114
|
voltDID = this._config.volt.did;
|
|
115
|
-
|
|
115
|
+
voltHttpAddress = this._config.volt.http_address;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
if (voltDID) {
|
|
119
119
|
const didConfig = await fetchVoltConfigFromDID.call(this, voltDID);
|
|
120
|
-
this._config = { ...this._config,
|
|
120
|
+
this._config = { ...this._config, volt: didConfig };
|
|
121
121
|
log("resolved config from DID: %s", JSON.stringify(didConfig, null, 2));
|
|
122
|
-
} else if (
|
|
123
|
-
const discoConfig = await fetchVoltConfig.call(
|
|
124
|
-
|
|
122
|
+
} else if (voltHttpAddress) {
|
|
123
|
+
const discoConfig = await fetchVoltConfig.call(
|
|
124
|
+
this,
|
|
125
|
+
`${voltHttpAddress}/discovery`,
|
|
126
|
+
);
|
|
127
|
+
this._config = {
|
|
128
|
+
...this._config,
|
|
129
|
+
volt: { ...this._config.volt, ...discoConfig },
|
|
130
|
+
};
|
|
125
131
|
}
|
|
126
132
|
|
|
127
133
|
this._voltConfig = this._config.volt;
|
|
128
134
|
this._voltConfig.did = voltDID;
|
|
129
|
-
this._voltConfig.
|
|
135
|
+
this._voltConfig.http_address = voltHttpAddress;
|
|
130
136
|
|
|
131
137
|
if (!this._voltConfig.id || typeof this._voltConfig.id !== "string") {
|
|
132
138
|
throw new Error("'id' property is missing in Volt configuration");
|
|
@@ -256,7 +262,7 @@ export class VoltClient extends EventEmitter {
|
|
|
256
262
|
}
|
|
257
263
|
|
|
258
264
|
get isVoltRelay() {
|
|
259
|
-
return this.isRemote && !this._config?.relay.
|
|
265
|
+
return this.isRemote && !this._config?.relay.cloud;
|
|
260
266
|
}
|
|
261
267
|
|
|
262
268
|
connect() {
|
|
@@ -277,7 +283,7 @@ export class VoltClient extends EventEmitter {
|
|
|
277
283
|
/**
|
|
278
284
|
* Request resource access.
|
|
279
285
|
* @param {*} targetResourceId
|
|
280
|
-
* @param {*} accessType - see
|
|
286
|
+
* @param {*} accessType - see volt.proto for values.
|
|
281
287
|
*/
|
|
282
288
|
async RequestAccessBlocking(
|
|
283
289
|
targetResourceId,
|
|
@@ -452,24 +458,19 @@ export class VoltClient extends EventEmitter {
|
|
|
452
458
|
DownloadFile(request) {
|
|
453
459
|
const grpcClient = this.getVoltAPIClient();
|
|
454
460
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
resolve(grpcClient.DownloadFile(request, meta.metadata));
|
|
462
|
-
}).catch((err) => {
|
|
463
|
-
log("error during %s [%s]", method, err.message);
|
|
464
|
-
return Promise.reject(err);
|
|
465
|
-
});
|
|
461
|
+
const downloadCall = new GRPCCall(
|
|
462
|
+
this,
|
|
463
|
+
"DownloadFile",
|
|
464
|
+
"METHOD_TYPE_SERVER_STREAM",
|
|
465
|
+
);
|
|
466
|
+
return downloadCall.start(grpcClient, request);
|
|
466
467
|
}
|
|
467
468
|
|
|
468
|
-
UploadFile(request
|
|
469
|
+
UploadFile(request) {
|
|
469
470
|
const grpcClient = this.getVoltAPIClient();
|
|
470
471
|
|
|
471
472
|
const uploadCall = new GRPCCall(this, "UploadFile", "METHOD_TYPE_BIDI");
|
|
472
|
-
return uploadCall.start(grpcClient, request
|
|
473
|
+
return uploadCall.start(grpcClient, request);
|
|
473
474
|
}
|
|
474
475
|
|
|
475
476
|
/**
|
|
@@ -478,72 +479,72 @@ export class VoltClient extends EventEmitter {
|
|
|
478
479
|
* @returns file buffer, base64 encoded
|
|
479
480
|
*/
|
|
480
481
|
DownloadFileSync(request) {
|
|
481
|
-
|
|
482
|
+
return new Promise((resolve, reject) => {
|
|
483
|
+
const grpcClient = this.getVoltAPIClient();
|
|
482
484
|
|
|
483
|
-
|
|
485
|
+
const blocks = [];
|
|
484
486
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
call.start(grpcClient, request, (err, response) => {
|
|
491
|
-
if (err) {
|
|
492
|
-
return call.reject(err);
|
|
493
|
-
}
|
|
487
|
+
const call = new GRPCCall(
|
|
488
|
+
this,
|
|
489
|
+
"DownloadFile",
|
|
490
|
+
"METHOD_TYPE_SERVER_STREAM",
|
|
491
|
+
);
|
|
494
492
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
case "status": {
|
|
501
|
-
if (response.status.message) {
|
|
502
|
-
return call.reject(new Error(response.status.message));
|
|
503
|
-
} else {
|
|
504
|
-
// Non-error response status => do nothing and wait for the stream to end.
|
|
493
|
+
call.on("data", (response) => {
|
|
494
|
+
switch (response.payload) {
|
|
495
|
+
case "block": {
|
|
496
|
+
blocks.push(response.block);
|
|
497
|
+
break;
|
|
505
498
|
}
|
|
506
|
-
|
|
499
|
+
case "status": {
|
|
500
|
+
if (response.status.message) {
|
|
501
|
+
return call.reject(new Error(response.status.message));
|
|
502
|
+
} else {
|
|
503
|
+
// Non-error response status => do nothing and wait for the stream to end.
|
|
504
|
+
}
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
default:
|
|
508
|
+
log("unrecognised response payload %s", response.payload);
|
|
509
|
+
break;
|
|
507
510
|
}
|
|
508
|
-
|
|
509
|
-
log("unrecognised response payload %s", response.payload);
|
|
510
|
-
break;
|
|
511
|
-
}
|
|
512
|
-
});
|
|
511
|
+
});
|
|
513
512
|
|
|
514
|
-
|
|
515
|
-
.wait()
|
|
516
|
-
.then(() => {
|
|
517
|
-
log("Download finished");
|
|
518
|
-
return { buffer: Buffer.concat(blocks).toString("base64") };
|
|
519
|
-
})
|
|
520
|
-
.catch((err) => {
|
|
513
|
+
call.on("error", (err) => {
|
|
521
514
|
log("error during DownloadFile [%s]", err.message);
|
|
522
|
-
|
|
515
|
+
reject(err);
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
call.on("end", () => {
|
|
519
|
+
log("Download finished");
|
|
520
|
+
resolve({ buffer: Buffer.concat(blocks).toString("base64") });
|
|
523
521
|
});
|
|
522
|
+
|
|
523
|
+
call.start(grpcClient, request);
|
|
524
|
+
});
|
|
524
525
|
}
|
|
525
526
|
|
|
526
527
|
/**
|
|
527
528
|
* SqliteDatabaseAPI
|
|
528
529
|
*/
|
|
529
|
-
SqlExecute(request
|
|
530
|
+
SqlExecute(request) {
|
|
530
531
|
const grpcClient = this.getVoltAPIClient();
|
|
531
532
|
|
|
532
533
|
const subscribeCall = new GRPCCall(this, "Execute", "METHOD_TYPE_BIDI");
|
|
533
|
-
return subscribeCall.start(grpcClient, request
|
|
534
|
+
return subscribeCall.start(grpcClient, request);
|
|
534
535
|
}
|
|
535
536
|
|
|
536
537
|
/**
|
|
537
538
|
* WireAPI
|
|
538
539
|
*/
|
|
539
|
-
PublishWire(request
|
|
540
|
+
PublishWire(request) {
|
|
540
541
|
const grpcClient = this.getVoltAPIClient();
|
|
541
542
|
|
|
542
543
|
const publishCall = new GRPCCall(this, "PublishWire", "METHOD_TYPE_BIDI");
|
|
543
|
-
return publishCall.start(grpcClient, request
|
|
544
|
+
return publishCall.start(grpcClient, request);
|
|
544
545
|
}
|
|
545
546
|
|
|
546
|
-
SubscribeWire(request
|
|
547
|
+
SubscribeWire(request) {
|
|
547
548
|
const grpcClient = this.getVoltAPIClient();
|
|
548
549
|
|
|
549
550
|
const subscribeCall = new GRPCCall(
|
|
@@ -551,6 +552,6 @@ export class VoltClient extends EventEmitter {
|
|
|
551
552
|
"SubscribeWire",
|
|
552
553
|
"METHOD_TYPE_BIDI",
|
|
553
554
|
);
|
|
554
|
-
return subscribeCall.start(grpcClient, request
|
|
555
|
+
return subscribeCall.start(grpcClient, request);
|
|
555
556
|
}
|
|
556
557
|
}
|