@holochain/client 0.15.1 → 0.16.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/README.md +11 -31
- package/lib/api/admin/types.d.ts +21 -0
- package/lib/api/admin/websocket.js +1 -1
- package/lib/api/app/websocket.js +10 -5
- package/lib/api/app-agent/websocket.js +3 -2
- package/lib/api/zome-call-signing.d.ts +9 -16
- package/lib/api/zome-call-signing.js +19 -12
- package/lib/environments/launcher.js +1 -1
- package/package.json +10 -8
package/README.md
CHANGED
|
@@ -13,14 +13,11 @@ A JavaScript client for the Holochain Conductor API (works with browsers as well
|
|
|
13
13
|
|
|
14
14
|
[Complete API reference](./docs/client.md)
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## Installation
|
|
17
17
|
|
|
18
18
|
**JS client v0.12.x** is compatible with **Holochain v0.1.x**.
|
|
19
19
|
|
|
20
|
-
**JS client v0.
|
|
21
|
-
*As target, ES2020 or higher is required when bundling for production*.
|
|
22
|
-
|
|
23
|
-
## Installation
|
|
20
|
+
**JS client v0.16.x** are compatible with **Holochain v0.2.x**.
|
|
24
21
|
|
|
25
22
|
To install from NPM, run
|
|
26
23
|
```bash
|
|
@@ -33,7 +30,7 @@ npm install --save-exact @holochain/client
|
|
|
33
30
|
|
|
34
31
|
### Use AppAgentWebsocket with implicit zome call signing
|
|
35
32
|
```typescript
|
|
36
|
-
import { AdminWebsocket, AppAgentWebsocket, CellType } from "@holochain/client";
|
|
33
|
+
import { ActionHash, AdminWebsocket, AppAgentWebsocket, CellType } from "@holochain/client";
|
|
37
34
|
|
|
38
35
|
const adminWs = await AdminWebsocket.connect("ws://127.0.0.1:65000");
|
|
39
36
|
const agent_key = await adminWs.generateAgentPubKey();
|
|
@@ -57,25 +54,15 @@ const appAgentWs = await AppAgentWebsocket.connect(
|
|
|
57
54
|
installed_app_id
|
|
58
55
|
);
|
|
59
56
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
appAgentWs.on("signal", signalCb);
|
|
57
|
+
const zomeCallPayload: CallZomeRequest = {
|
|
58
|
+
cell_id,
|
|
59
|
+
zome_name: "zome_name",
|
|
60
|
+
fn_name: "create_entry",
|
|
61
|
+
provenance: agent_key,
|
|
62
|
+
payload: "some_content",
|
|
63
|
+
};
|
|
70
64
|
|
|
71
|
-
|
|
72
|
-
await appAgentWs.callZome({
|
|
73
|
-
role_name,
|
|
74
|
-
zome_name: "zome",
|
|
75
|
-
fn_name: "emitter",
|
|
76
|
-
payload: null,
|
|
77
|
-
});
|
|
78
|
-
await signalReceived;
|
|
65
|
+
const response: ActionHash = await appAgentWs.callZome(zomeCallPayload, 30000);
|
|
79
66
|
|
|
80
67
|
await appAgentWs.appWebsocket.client.close();
|
|
81
68
|
await adminWs.client.close();
|
|
@@ -157,13 +144,6 @@ setSigningCredentials(cell_id, signingCredentials);
|
|
|
157
144
|
localStorage.setItem(cellIdB64, JSON.stringify(signingCredentials));
|
|
158
145
|
```
|
|
159
146
|
|
|
160
|
-
# Holochain Compatibility
|
|
161
|
-
|
|
162
|
-
See [default.nix](./default.nix) for the Holochain version this package is compatible with.
|
|
163
|
-
|
|
164
|
-
If updating the Holochain version included in holonix, please use `niv update` as explained in the
|
|
165
|
-
[Holochain Installation Guide](https://developer.holochain.org/install-advanced/#upgrading-the-holochain-version).
|
|
166
|
-
|
|
167
147
|
## Running tests
|
|
168
148
|
|
|
169
149
|
You need a version (`stable` toolchain) of Rust available.
|
package/lib/api/admin/types.d.ts
CHANGED
|
@@ -382,12 +382,33 @@ export type NetworkSeed = string;
|
|
|
382
382
|
* @public
|
|
383
383
|
*/
|
|
384
384
|
export type InstallAppRequest = {
|
|
385
|
+
/**
|
|
386
|
+
* The agent to use when creating Cells for this App.
|
|
387
|
+
*/
|
|
385
388
|
agent_key: AgentPubKey;
|
|
389
|
+
/**
|
|
390
|
+
* The unique identifier for an installed app in this conductor.
|
|
391
|
+
* If not specified, it will be derived from the app name in the bundle manifest.
|
|
392
|
+
*/
|
|
386
393
|
installed_app_id?: InstalledAppId;
|
|
394
|
+
/**
|
|
395
|
+
* Include proof-of-membrane-membership data for cells that require it,
|
|
396
|
+
* keyed by the CellNick specified in the app bundle manifest.
|
|
397
|
+
*/
|
|
387
398
|
membrane_proofs: {
|
|
388
399
|
[key: string]: MembraneProof;
|
|
389
400
|
};
|
|
401
|
+
/**
|
|
402
|
+
* Optional global network seed override. If set will override the network seed value for all
|
|
403
|
+
* DNAs in the bundle.
|
|
404
|
+
*/
|
|
390
405
|
network_seed?: NetworkSeed;
|
|
406
|
+
/**
|
|
407
|
+
* Optional: If app installation fails due to genesis failure, normally the app will be immediately uninstalled.
|
|
408
|
+
* When this flag is set, the app is left installed with empty cells intact. This can be useful for
|
|
409
|
+
* using graft_records_onto_source_chain, or for diagnostics.
|
|
410
|
+
*/
|
|
411
|
+
ignore_genesis_failure?: boolean;
|
|
391
412
|
} & AppBundleSource;
|
|
392
413
|
/**
|
|
393
414
|
* @public
|
|
@@ -134,7 +134,7 @@ export class AdminWebsocket {
|
|
|
134
134
|
* @returns The cap secret of the created capability.
|
|
135
135
|
*/
|
|
136
136
|
grantSigningKey = async (cellId, functions, signingKey) => {
|
|
137
|
-
const capSecret = randomCapSecret();
|
|
137
|
+
const capSecret = await randomCapSecret();
|
|
138
138
|
await this.grantZomeCallCapability({
|
|
139
139
|
cell_id: cellId,
|
|
140
140
|
cap_grant: {
|
package/lib/api/app/websocket.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { hashZomeCall } from "@holochain/serialization";
|
|
2
2
|
import { decode, encode } from "@msgpack/msgpack";
|
|
3
|
-
import
|
|
3
|
+
import _sodium from "libsodium-wrappers";
|
|
4
4
|
import Emittery from "emittery";
|
|
5
5
|
import { getLauncherEnvironment, isLauncher, signZomeCallTauri, } from "../../environments/launcher.js";
|
|
6
6
|
import { encodeHashToBase64 } from "../../utils/base64.js";
|
|
@@ -23,8 +23,9 @@ export class AppWebsocket extends Emittery {
|
|
|
23
23
|
// Please retain until the upstream is fixed https://github.com/sindresorhus/emittery/issues/86.
|
|
24
24
|
Object.getOwnPropertyNames(Emittery.prototype).forEach((name) => {
|
|
25
25
|
const to_bind = this[name];
|
|
26
|
-
if (typeof to_bind ===
|
|
27
|
-
this[name] =
|
|
26
|
+
if (typeof to_bind === "function") {
|
|
27
|
+
this[name] =
|
|
28
|
+
to_bind.bind(this);
|
|
28
29
|
}
|
|
29
30
|
});
|
|
30
31
|
this.client = client;
|
|
@@ -130,11 +131,15 @@ export const signZomeCall = async (request) => {
|
|
|
130
131
|
fn_name: request.fn_name,
|
|
131
132
|
provenance: signingCredentialsForCell.signingKey,
|
|
132
133
|
payload: encode(request.payload),
|
|
133
|
-
nonce: randomNonce(),
|
|
134
|
+
nonce: await randomNonce(),
|
|
134
135
|
expires_at: getNonceExpiration(),
|
|
135
136
|
};
|
|
136
137
|
const hashedZomeCall = await hashZomeCall(unsignedZomeCallPayload);
|
|
137
|
-
|
|
138
|
+
await _sodium.ready;
|
|
139
|
+
const sodium = _sodium;
|
|
140
|
+
const signature = sodium
|
|
141
|
+
.crypto_sign(hashedZomeCall, signingCredentialsForCell.keyPair.privateKey)
|
|
142
|
+
.subarray(0, sodium.crypto_sign_BYTES);
|
|
138
143
|
const signedZomeCall = {
|
|
139
144
|
...unsignedZomeCallPayload,
|
|
140
145
|
signature,
|
|
@@ -23,8 +23,9 @@ export class AppAgentWebsocket {
|
|
|
23
23
|
// Please retain until the upstream is fixed https://github.com/sindresorhus/emittery/issues/86.
|
|
24
24
|
Object.getOwnPropertyNames(Emittery.prototype).forEach((name) => {
|
|
25
25
|
const to_bind = this.emitter[name];
|
|
26
|
-
if (typeof to_bind ===
|
|
27
|
-
this.emitter[name] =
|
|
26
|
+
if (typeof to_bind === "function") {
|
|
27
|
+
this.emitter[name] =
|
|
28
|
+
to_bind.bind(this.emitter);
|
|
28
29
|
}
|
|
29
30
|
});
|
|
30
31
|
const env = getLauncherEnvironment();
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { type KeyPair } from "libsodium-wrappers";
|
|
2
|
+
import type { CapSecret } from "../hdk/capabilities.js";
|
|
3
|
+
import type { AgentPubKey, CellId } from "../types.js";
|
|
3
4
|
/**
|
|
4
5
|
* @public
|
|
5
6
|
*/
|
|
6
7
|
export type Nonce256Bit = Uint8Array;
|
|
7
|
-
/**
|
|
8
|
-
* @public
|
|
9
|
-
*/
|
|
10
|
-
export interface KeyPair {
|
|
11
|
-
privateKey: Uint8Array;
|
|
12
|
-
publicKey: Uint8Array;
|
|
13
|
-
}
|
|
14
8
|
/**
|
|
15
9
|
* @public
|
|
16
10
|
*/
|
|
@@ -39,26 +33,25 @@ export declare const setSigningCredentials: (cellId: CellId, credentials: Signin
|
|
|
39
33
|
/**
|
|
40
34
|
* Generates a key pair for signing zome calls.
|
|
41
35
|
*
|
|
36
|
+
* @param agentPubKey - The agent pub key to take 4 last bytes (= DHT location)
|
|
37
|
+
* from (optional).
|
|
42
38
|
* @returns The signing key pair and an agent pub key based on the public key.
|
|
43
39
|
*
|
|
44
40
|
* @public
|
|
45
41
|
*/
|
|
46
|
-
export declare const generateSigningKeyPair: () => Promise<[
|
|
47
|
-
KeyPair,
|
|
48
|
-
AgentPubKey
|
|
49
|
-
]>;
|
|
42
|
+
export declare const generateSigningKeyPair: (agentPubKey?: AgentPubKey) => Promise<[KeyPair, AgentPubKey]>;
|
|
50
43
|
/**
|
|
51
44
|
* @public
|
|
52
45
|
*/
|
|
53
|
-
export declare const randomCapSecret: () => CapSecret
|
|
46
|
+
export declare const randomCapSecret: () => Promise<CapSecret>;
|
|
54
47
|
/**
|
|
55
48
|
* @public
|
|
56
49
|
*/
|
|
57
|
-
export declare const randomNonce: () => Nonce256Bit
|
|
50
|
+
export declare const randomNonce: () => Promise<Nonce256Bit>;
|
|
58
51
|
/**
|
|
59
52
|
* @public
|
|
60
53
|
*/
|
|
61
|
-
export declare const randomByteArray: (length: number) => Uint8Array
|
|
54
|
+
export declare const randomByteArray: (length: number) => Promise<Uint8Array>;
|
|
62
55
|
/**
|
|
63
56
|
* @public
|
|
64
57
|
*/
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import _sodium from "libsodium-wrappers";
|
|
2
2
|
import { encodeHashToBase64 } from "../utils/base64.js";
|
|
3
|
-
if (!globalThis.crypto) {
|
|
4
|
-
import("node:crypto").then((webcrypto) => (globalThis.crypto = webcrypto));
|
|
5
|
-
}
|
|
6
3
|
const signingCredentials = new Map();
|
|
7
4
|
/**
|
|
8
5
|
* Get credentials for signing zome calls.
|
|
@@ -30,29 +27,39 @@ export const setSigningCredentials = (cellId, credentials) => {
|
|
|
30
27
|
/**
|
|
31
28
|
* Generates a key pair for signing zome calls.
|
|
32
29
|
*
|
|
30
|
+
* @param agentPubKey - The agent pub key to take 4 last bytes (= DHT location)
|
|
31
|
+
* from (optional).
|
|
33
32
|
* @returns The signing key pair and an agent pub key based on the public key.
|
|
34
33
|
*
|
|
35
34
|
* @public
|
|
36
35
|
*/
|
|
37
|
-
export const generateSigningKeyPair = async () => {
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const keyPair =
|
|
41
|
-
const
|
|
36
|
+
export const generateSigningKeyPair = async (agentPubKey) => {
|
|
37
|
+
await _sodium.ready;
|
|
38
|
+
const sodium = _sodium;
|
|
39
|
+
const keyPair = sodium.crypto_sign_keypair();
|
|
40
|
+
const locationBytes = agentPubKey ? agentPubKey.subarray(35) : [0, 0, 0, 0];
|
|
41
|
+
const signingKey = new Uint8Array([132, 32, 36].concat(...keyPair.publicKey).concat(...locationBytes));
|
|
42
42
|
return [keyPair, signingKey];
|
|
43
43
|
};
|
|
44
44
|
/**
|
|
45
45
|
* @public
|
|
46
46
|
*/
|
|
47
|
-
export const randomCapSecret = () => randomByteArray(64);
|
|
47
|
+
export const randomCapSecret = async () => randomByteArray(64);
|
|
48
48
|
/**
|
|
49
49
|
* @public
|
|
50
50
|
*/
|
|
51
|
-
export const randomNonce = () => randomByteArray(32);
|
|
51
|
+
export const randomNonce = async () => randomByteArray(32);
|
|
52
52
|
/**
|
|
53
53
|
* @public
|
|
54
54
|
*/
|
|
55
|
-
export const randomByteArray = (length) =>
|
|
55
|
+
export const randomByteArray = async (length) => {
|
|
56
|
+
if (globalThis.crypto && "getRandomValues" in globalThis.crypto) {
|
|
57
|
+
return globalThis.crypto.getRandomValues(new Uint8Array(length));
|
|
58
|
+
}
|
|
59
|
+
await _sodium.ready;
|
|
60
|
+
const sodium = _sodium;
|
|
61
|
+
return sodium.randombytes_buf(length);
|
|
62
|
+
};
|
|
56
63
|
/**
|
|
57
64
|
* @public
|
|
58
65
|
*/
|
|
@@ -11,7 +11,7 @@ export const signZomeCallTauri = async (request) => {
|
|
|
11
11
|
zome_name: request.zome_name,
|
|
12
12
|
fn_name: request.fn_name,
|
|
13
13
|
payload: Array.from(encode(request.payload)),
|
|
14
|
-
nonce: Array.from(randomNonce()),
|
|
14
|
+
nonce: Array.from(await randomNonce()),
|
|
15
15
|
expires_at: getNonceExpiration(),
|
|
16
16
|
};
|
|
17
17
|
const signedZomeCallTauri = await invoke("sign_zome_call", { zomeCallUnsigned });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holochain/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "A JavaScript client for the Holochain Conductor API",
|
|
5
5
|
"author": "Holochain Foundation <info@holochain.org> (http://holochain.org)",
|
|
6
6
|
"license": "CAL-1.0",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"emittery": "^1.0.1",
|
|
47
47
|
"isomorphic-ws": "^5.0.0",
|
|
48
48
|
"js-base64": "^3.7.3",
|
|
49
|
+
"libsodium-wrappers": "^0.7.11",
|
|
49
50
|
"lodash-es": "^4.17.21",
|
|
50
51
|
"ws": "^8.13.0"
|
|
51
52
|
},
|
|
@@ -53,17 +54,18 @@
|
|
|
53
54
|
"@microsoft/api-documenter": "^7.21.7",
|
|
54
55
|
"@microsoft/api-extractor": "^7.34.4",
|
|
55
56
|
"@types/js-yaml": "^3.12.7",
|
|
57
|
+
"@types/libsodium-wrappers": "^0.7.10",
|
|
56
58
|
"@types/lodash-es": "^4.17.6",
|
|
57
59
|
"@types/tape": "^4.13.2",
|
|
58
60
|
"@types/ws": "^8.5.3",
|
|
59
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
60
|
-
"@typescript-eslint/parser": "^5.
|
|
61
|
-
"eslint": "^8.
|
|
62
|
-
"eslint-config-prettier": "^8.
|
|
63
|
-
"eslint-plugin-prettier": "^4.
|
|
64
|
-
"eslint-plugin-tsdoc": "^0.2.
|
|
61
|
+
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
|
62
|
+
"@typescript-eslint/parser": "^5.62.0",
|
|
63
|
+
"eslint": "^8.46.0",
|
|
64
|
+
"eslint-config-prettier": "^8.10.0",
|
|
65
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
66
|
+
"eslint-plugin-tsdoc": "^0.2.17",
|
|
65
67
|
"js-yaml": "^3.14.1",
|
|
66
|
-
"prettier": "^2.
|
|
68
|
+
"prettier": "^2.8.8",
|
|
67
69
|
"rimraf": "^3.0.2",
|
|
68
70
|
"tape": "^5.5.3",
|
|
69
71
|
"ts-node": "^10.9.1",
|