@holochain/client 0.15.0 → 0.16.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/README.md +2 -12
- package/lib/api/admin/types.d.ts +2 -3
- package/lib/api/admin/websocket.js +1 -1
- package/lib/api/app/websocket.js +16 -3
- package/lib/api/app-agent/websocket.js +8 -0
- package/lib/api/client.d.ts +1 -2
- package/lib/api/client.js +0 -2
- package/lib/api/index.d.ts +1 -1
- package/lib/api/index.js +1 -1
- 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
|
|
@@ -157,13 +154,6 @@ setSigningCredentials(cell_id, signingCredentials);
|
|
|
157
154
|
localStorage.setItem(cellIdB64, JSON.stringify(signingCredentials));
|
|
158
155
|
```
|
|
159
156
|
|
|
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
157
|
## Running tests
|
|
168
158
|
|
|
169
159
|
You need a version (`stable` toolchain) of Rust available.
|
package/lib/api/admin/types.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { Action, DhtOp, Entry, ZomeCallCapGrant } from "../../hdk/index.js";
|
|
3
2
|
import { ActionHash, AgentPubKey, CellId, DnaHash, DnaProperties, Duration, HoloHash, HoloHashB64, InstalledAppId, KitsuneAgent, KitsuneSpace, RoleName, Signature, Timestamp, WasmHash } from "../../types.js";
|
|
4
3
|
import { Requester } from "../common.js";
|
|
@@ -127,7 +126,7 @@ export type AppInfo = {
|
|
|
127
126
|
/**
|
|
128
127
|
* @public
|
|
129
128
|
*/
|
|
130
|
-
export type MembraneProof =
|
|
129
|
+
export type MembraneProof = Uint8Array;
|
|
131
130
|
/**
|
|
132
131
|
* @public
|
|
133
132
|
*/
|
|
@@ -163,7 +162,7 @@ export type DumpStateResponse = any;
|
|
|
163
162
|
*/
|
|
164
163
|
export type DumpFullStateRequest = {
|
|
165
164
|
cell_id: CellId;
|
|
166
|
-
dht_ops_cursor
|
|
165
|
+
dht_ops_cursor?: number;
|
|
167
166
|
};
|
|
168
167
|
/**
|
|
169
168
|
* @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";
|
|
@@ -19,6 +19,15 @@ export class AppWebsocket extends Emittery {
|
|
|
19
19
|
overrideInstalledAppId;
|
|
20
20
|
constructor(client, defaultTimeout, overrideInstalledAppId) {
|
|
21
21
|
super();
|
|
22
|
+
// Ensure all super methods are bound to this instance because Emittery relies on `this` being the instance.
|
|
23
|
+
// Please retain until the upstream is fixed https://github.com/sindresorhus/emittery/issues/86.
|
|
24
|
+
Object.getOwnPropertyNames(Emittery.prototype).forEach((name) => {
|
|
25
|
+
const to_bind = this[name];
|
|
26
|
+
if (typeof to_bind === "function") {
|
|
27
|
+
this[name] =
|
|
28
|
+
to_bind.bind(this);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
22
31
|
this.client = client;
|
|
23
32
|
this.defaultTimeout =
|
|
24
33
|
defaultTimeout === undefined ? DEFAULT_TIMEOUT : defaultTimeout;
|
|
@@ -122,11 +131,15 @@ export const signZomeCall = async (request) => {
|
|
|
122
131
|
fn_name: request.fn_name,
|
|
123
132
|
provenance: signingCredentialsForCell.signingKey,
|
|
124
133
|
payload: encode(request.payload),
|
|
125
|
-
nonce: randomNonce(),
|
|
134
|
+
nonce: await randomNonce(),
|
|
126
135
|
expires_at: getNonceExpiration(),
|
|
127
136
|
};
|
|
128
137
|
const hashedZomeCall = await hashZomeCall(unsignedZomeCallPayload);
|
|
129
|
-
|
|
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);
|
|
130
143
|
const signedZomeCall = {
|
|
131
144
|
...unsignedZomeCallPayload,
|
|
132
145
|
signature,
|
|
@@ -19,6 +19,14 @@ export class AppAgentWebsocket {
|
|
|
19
19
|
constructor(appWebsocket, installedAppId, myPubKey) {
|
|
20
20
|
this.appWebsocket = appWebsocket;
|
|
21
21
|
this.emitter = new Emittery();
|
|
22
|
+
// Ensure all super methods are bound to this instance because Emittery relies on `this` being the instance.
|
|
23
|
+
// Please retain until the upstream is fixed https://github.com/sindresorhus/emittery/issues/86.
|
|
24
|
+
Object.getOwnPropertyNames(Emittery.prototype).forEach((name) => {
|
|
25
|
+
const to_bind = this.emitter[name];
|
|
26
|
+
if (typeof to_bind === 'function') {
|
|
27
|
+
this.emitter[name] = to_bind.bind(this.emitter);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
22
30
|
const env = getLauncherEnvironment();
|
|
23
31
|
this.installedAppId = env?.INSTALLED_APP_ID || installedAppId;
|
|
24
32
|
this.myPubKey = myPubKey;
|
package/lib/api/client.d.ts
CHANGED
|
@@ -13,8 +13,7 @@ export declare class WsClient extends Emittery {
|
|
|
13
13
|
socket: IsoWebSocket;
|
|
14
14
|
url: URL | undefined;
|
|
15
15
|
private pendingRequests;
|
|
16
|
-
index
|
|
17
|
-
private connectRetries;
|
|
16
|
+
private index;
|
|
18
17
|
constructor(socket: IsoWebSocket, url: URL);
|
|
19
18
|
private setupSocket;
|
|
20
19
|
/**
|
package/lib/api/client.js
CHANGED
|
@@ -15,14 +15,12 @@ export class WsClient extends Emittery {
|
|
|
15
15
|
url;
|
|
16
16
|
pendingRequests;
|
|
17
17
|
index;
|
|
18
|
-
connectRetries;
|
|
19
18
|
constructor(socket, url) {
|
|
20
19
|
super();
|
|
21
20
|
this.socket = socket;
|
|
22
21
|
this.url = url;
|
|
23
22
|
this.pendingRequests = {};
|
|
24
23
|
this.index = 0;
|
|
25
|
-
this.connectRetries = 0;
|
|
26
24
|
this.setupSocket();
|
|
27
25
|
}
|
|
28
26
|
setupSocket() {
|
package/lib/api/index.d.ts
CHANGED
|
@@ -3,5 +3,5 @@ export * from "./admin/index.js";
|
|
|
3
3
|
export * from "./app-agent/index.js";
|
|
4
4
|
export * from "./app/index.js";
|
|
5
5
|
export { IsoWebSocket, WsClient } from "./client.js";
|
|
6
|
-
export { CloneId, Requester, Transformer } from "./common.js";
|
|
6
|
+
export { CloneId, Requester, Transformer, getBaseRoleNameFromCloneId, isCloneId, } from "./common.js";
|
|
7
7
|
export * from "./zome-call-signing.js";
|
package/lib/api/index.js
CHANGED
|
@@ -3,5 +3,5 @@ export * from "./admin/index.js";
|
|
|
3
3
|
export * from "./app-agent/index.js";
|
|
4
4
|
export * from "./app/index.js";
|
|
5
5
|
export { IsoWebSocket, WsClient } from "./client.js";
|
|
6
|
-
export { CloneId } from "./common.js";
|
|
6
|
+
export { CloneId, getBaseRoleNameFromCloneId, isCloneId, } from "./common.js";
|
|
7
7
|
export * from "./zome-call-signing.js";
|
|
@@ -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.0",
|
|
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",
|