@ledgerhq/ledger-key-ring-protocol 0.5.3-next.0 → 0.5.4-next.2

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/sdk.js CHANGED
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -21,14 +12,18 @@ const errors_1 = require("@ledgerhq/errors");
21
12
  const errors_2 = require("./errors");
22
13
  const auth_1 = require("./auth");
23
14
  class SDK {
15
+ context;
16
+ hwDeviceProvider;
17
+ lifecycle;
18
+ api;
24
19
  constructor(context, hwDeviceProvider, lifecyle) {
25
- this.jwt = undefined;
26
- this.jwtHash = "";
27
20
  this.context = context;
28
21
  this.hwDeviceProvider = hwDeviceProvider;
29
22
  this.lifecycle = lifecyle;
30
23
  this.api = (0, api_1.default)(context.apiBaseUrl);
31
24
  }
25
+ jwt = undefined;
26
+ jwtHash = "";
32
27
  withAuth(trustchain, memberCredentials, job, policy, ignorePermissionsChecks) {
33
28
  const hash = trustchain.rootId + " " + memberCredentials.pubkey;
34
29
  if (this.jwtHash !== hash) {
@@ -50,267 +45,237 @@ class SDK {
50
45
  return job(jwt);
51
46
  }, this.jwt, () => this.auth(trustchain, memberCredentials), jwt => this.api.refreshAuth(jwt), policy);
52
47
  }
53
- initMemberCredentials() {
54
- return __awaiter(this, void 0, void 0, function* () {
55
- const kp = hw_ledger_key_ring_protocol_1.crypto.randomKeypair();
56
- return convertKeyPairToLiveCredentials(kp);
57
- });
48
+ async initMemberCredentials() {
49
+ const kp = hw_ledger_key_ring_protocol_1.crypto.randomKeypair();
50
+ return convertKeyPairToLiveCredentials(kp);
58
51
  }
59
- getOrCreateTrustchain(deviceId, memberCredentials, callbacks, topic, currentTrustchain) {
60
- return __awaiter(this, void 0, void 0, function* () {
61
- var _a;
62
- this.invalidateJwt();
63
- let type = types_1.TrustchainResultType.restored;
64
- const withJwt = job => this.hwDeviceProvider.withJwt(deviceId, job, "cache", callbacks);
65
- const withHw = job => this.hwDeviceProvider.withHw(deviceId, job, callbacks);
66
- let trustchains = yield withJwt(this.api.getTrustchains);
67
- (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onInitialResponse) === null || _a === void 0 ? void 0 : _a.call(callbacks, trustchains);
68
- if (currentTrustchain) {
69
- yield this.restoreTrustchain(currentTrustchain, memberCredentials).then(() => {
70
- throw Object.keys(trustchains).includes(currentTrustchain.rootId)
71
- ? new errors_2.TrustchainAlreadyInitialized()
72
- : new errors_2.TrustchainAlreadyInitializedWithOtherSeed();
73
- }, () => {
74
- // The user was ejected from the trustchain therefore we can continue
75
- });
76
- }
77
- if (Object.keys(trustchains).length === 0) {
78
- (0, logs_1.log)("trustchain", "getOrCreateTrustchain: no trustchain yet, let's create one");
79
- type = types_1.TrustchainResultType.created;
80
- const streamTree = yield this.hwDeviceProvider.withHw(deviceId, hw => hw_ledger_key_ring_protocol_1.StreamTree.createNewTree(hw, { topic }));
81
- yield streamTree.getRoot().resolve(); // double checks the signatures are correct before sending to the backend
82
- const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode(streamTree.getRoot().blocks);
83
- yield withJwt(jwt => this.api.postSeed(jwt, hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)));
84
- // deviceJwt have changed, proactively refresh it
85
- yield this.hwDeviceProvider.refreshJwt(deviceId, callbacks);
86
- trustchains = yield withJwt(this.api.getTrustchains);
87
- }
88
- // we find our trustchain root id
89
- let trustchainRootId;
90
- const trustchainRootPath = "m/";
91
- for (const [trustchainId, info] of Object.entries(trustchains)) {
92
- for (const path in info) {
93
- if (path === trustchainRootPath) {
94
- trustchainRootId = trustchainId;
95
- }
52
+ async getOrCreateTrustchain(deviceId, memberCredentials, callbacks, topic, currentTrustchain) {
53
+ this.invalidateJwt();
54
+ let type = types_1.TrustchainResultType.restored;
55
+ const withJwt = job => this.hwDeviceProvider.withJwt(deviceId, job, "cache", callbacks);
56
+ const withHw = job => this.hwDeviceProvider.withHw(deviceId, job, callbacks);
57
+ let trustchains = await withJwt(this.api.getTrustchains);
58
+ callbacks?.onInitialResponse?.(trustchains);
59
+ if (currentTrustchain) {
60
+ await this.restoreTrustchain(currentTrustchain, memberCredentials).then(() => {
61
+ throw Object.keys(trustchains).includes(currentTrustchain.rootId)
62
+ ? new errors_2.TrustchainAlreadyInitialized()
63
+ : new errors_2.TrustchainAlreadyInitializedWithOtherSeed();
64
+ }, () => {
65
+ // The user was ejected from the trustchain therefore we can continue
66
+ });
67
+ }
68
+ if (Object.keys(trustchains).length === 0) {
69
+ (0, logs_1.log)("trustchain", "getOrCreateTrustchain: no trustchain yet, let's create one");
70
+ type = types_1.TrustchainResultType.created;
71
+ const streamTree = await this.hwDeviceProvider.withHw(deviceId, hw => hw_ledger_key_ring_protocol_1.StreamTree.createNewTree(hw, { topic }));
72
+ await streamTree.getRoot().resolve(); // double checks the signatures are correct before sending to the backend
73
+ const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode(streamTree.getRoot().blocks);
74
+ await withJwt(jwt => this.api.postSeed(jwt, hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)));
75
+ // deviceJwt have changed, proactively refresh it
76
+ await this.hwDeviceProvider.refreshJwt(deviceId, callbacks);
77
+ trustchains = await withJwt(this.api.getTrustchains);
78
+ }
79
+ // we find our trustchain root id
80
+ let trustchainRootId;
81
+ const trustchainRootPath = "m/";
82
+ for (const [trustchainId, info] of Object.entries(trustchains)) {
83
+ for (const path in info) {
84
+ if (path === trustchainRootPath) {
85
+ trustchainRootId = trustchainId;
96
86
  }
97
87
  }
98
- invariant(trustchainRootId, "trustchainRootId should be defined");
99
- (0, logs_1.log)("trustchain", "getOrCreateTrustchain rootId=" + trustchainRootId);
100
- // make a stream tree from all the trustchains associated to this root id
101
- let { streamTree } = yield withJwt(jwt => this.fetchTrustchain(jwt, trustchainRootId));
102
- const path = streamTree.getApplicationRootPath(this.context.applicationId);
103
- const child = streamTree.getChild(path);
104
- let shouldShare = true;
105
- if (child) {
106
- const resolved = yield child.resolve();
107
- const members = resolved.getMembers();
108
- shouldShare = !members.some(m => hw_ledger_key_ring_protocol_1.crypto.to_hex(m) === memberCredentials.pubkey); // not already a member
109
- }
110
- if (shouldShare) {
111
- if (type === types_1.TrustchainResultType.restored)
112
- type = types_1.TrustchainResultType.updated;
113
- streamTree = yield this.pushMember(streamTree, path, trustchainRootId, withJwt, withHw, {
114
- id: memberCredentials.pubkey,
115
- name: this.context.name,
116
- permissions: hw_ledger_key_ring_protocol_1.Permissions.OWNER,
117
- });
118
- }
119
- const walletSyncEncryptionKey = yield extractEncryptionKey(streamTree, path, memberCredentials);
120
- const trustchain = {
121
- rootId: trustchainRootId,
122
- walletSyncEncryptionKey,
123
- applicationPath: path,
124
- };
125
- return { type, trustchain };
126
- });
127
- }
128
- restoreTrustchain(trustchain, memberCredentials) {
129
- return __awaiter(this, void 0, void 0, function* () {
130
- const { streamTree, applicationRootPath } = yield this.withAuth(trustchain, memberCredentials, jwt => this.fetchTrustchainAndResolve(jwt, trustchain.rootId, this.context.applicationId), "refresh", true);
131
- const walletSyncEncryptionKey = yield extractEncryptionKey(streamTree, applicationRootPath, memberCredentials);
132
- return {
133
- rootId: trustchain.rootId,
134
- walletSyncEncryptionKey,
135
- applicationPath: applicationRootPath,
136
- };
137
- });
138
- }
139
- getMembers(trustchain, memberCredentials) {
140
- return __awaiter(this, void 0, void 0, function* () {
141
- const { resolved } = yield this.withAuth(trustchain, memberCredentials, jwt => this.fetchTrustchainAndResolve(jwt, trustchain.rootId, this.context.applicationId));
142
- const members = resolved.getMembersData();
143
- if (!members.some(m => m.id === memberCredentials.pubkey)) {
144
- throw new errors_2.TrustchainEjected("Not a member of trustchain");
145
- }
146
- return members;
147
- });
148
- }
149
- removeMember(deviceId, trustchain, memberCredentials, member, callbacks) {
150
- return __awaiter(this, void 0, void 0, function* () {
151
- var _a;
152
- this.invalidateJwt();
153
- const withJwt = job => this.hwDeviceProvider.withJwt(deviceId, job, "cache", callbacks);
154
- const withHw = job => this.hwDeviceProvider.withHw(deviceId, job, callbacks);
155
- // invariant because the sdk does not support this case, and the UI should not allows it.
156
- invariant(memberCredentials.pubkey !== member.id, "removeMember must not be used to remove the current member.");
157
- const afterRotation = yield ((_a = this.lifecycle) === null || _a === void 0 ? void 0 : _a.onTrustchainRotation(this, trustchain, memberCredentials));
158
- const applicationId = this.context.applicationId;
159
- const trustchainId = trustchain.rootId;
160
- // eslint-disable-next-line prefer-const
161
- let { resolved, streamTree, applicationRootPath } = yield withJwt(jwt => this.fetchTrustchainAndResolve(jwt, trustchainId, applicationId));
162
- const members = resolved.getMembersData();
163
- const withoutMember = members.filter(m => m.id !== member.id);
164
- invariant(withoutMember.length < members.length, "member not found"); // invariant because the UI should not allow this case.
165
- const withoutMemberOrMe = withoutMember.filter(m => m.id !== memberCredentials.pubkey);
166
- const softwareDevice = getSoftwareDevice(memberCredentials);
167
- const newPath = streamTree.getApplicationRootPath(applicationId, 1);
168
- // We close the current trustchain with the hardware wallet in order to get a user confirmation of the action
169
- const sendCloseStreamToAPI = yield this.closeStream(streamTree, applicationRootPath, trustchainId, withJwt, withHw);
170
- // derive a new branch of the tree on the new path
171
- streamTree = yield this.pushMember(streamTree, newPath, trustchainId, withJwt, withHw, {
88
+ }
89
+ invariant(trustchainRootId, "trustchainRootId should be defined");
90
+ (0, logs_1.log)("trustchain", "getOrCreateTrustchain rootId=" + trustchainRootId);
91
+ // make a stream tree from all the trustchains associated to this root id
92
+ let { streamTree } = await withJwt(jwt => this.fetchTrustchain(jwt, trustchainRootId));
93
+ const path = streamTree.getApplicationRootPath(this.context.applicationId);
94
+ const child = streamTree.getChild(path);
95
+ let shouldShare = true;
96
+ if (child) {
97
+ const resolved = await child.resolve();
98
+ const members = resolved.getMembers();
99
+ shouldShare = !members.some(m => hw_ledger_key_ring_protocol_1.crypto.to_hex(m) === memberCredentials.pubkey); // not already a member
100
+ }
101
+ if (shouldShare) {
102
+ if (type === types_1.TrustchainResultType.restored)
103
+ type = types_1.TrustchainResultType.updated;
104
+ streamTree = await this.pushMember(streamTree, path, trustchainRootId, withJwt, withHw, {
172
105
  id: memberCredentials.pubkey,
173
106
  name: this.context.name,
174
107
  permissions: hw_ledger_key_ring_protocol_1.Permissions.OWNER,
175
108
  });
176
- // add the remaining members
177
- const withSw = (job) => job(softwareDevice);
178
- for (const m of withoutMemberOrMe) {
179
- streamTree = yield this.pushMember(streamTree, newPath, trustchainId, withJwt, withSw, m);
180
- }
181
- const walletSyncEncryptionKey = yield extractEncryptionKey(streamTree, newPath, memberCredentials);
182
- // we send the close stream to the API only after the new stream is created in case user cancelled the process in the middle.
183
- yield sendCloseStreamToAPI();
184
- // deviceJwt have changed, proactively refresh it
185
- yield this.hwDeviceProvider.refreshJwt(deviceId, callbacks);
186
- const newTrustchain = {
187
- rootId: trustchainId,
188
- walletSyncEncryptionKey,
189
- applicationPath: newPath,
190
- };
191
- if (afterRotation)
192
- yield afterRotation(newTrustchain);
193
- // refresh the jwt with the new trustchain
194
- this.jwt = yield this.withAuth(newTrustchain, memberCredentials, jwt => Promise.resolve(jwt), "refresh");
195
- return newTrustchain;
196
- });
109
+ }
110
+ const walletSyncEncryptionKey = await extractEncryptionKey(streamTree, path, memberCredentials);
111
+ const trustchain = {
112
+ rootId: trustchainRootId,
113
+ walletSyncEncryptionKey,
114
+ applicationPath: path,
115
+ };
116
+ return { type, trustchain };
117
+ }
118
+ async restoreTrustchain(trustchain, memberCredentials) {
119
+ const { streamTree, applicationRootPath } = await this.withAuth(trustchain, memberCredentials, jwt => this.fetchTrustchainAndResolve(jwt, trustchain.rootId, this.context.applicationId), "refresh", true);
120
+ const walletSyncEncryptionKey = await extractEncryptionKey(streamTree, applicationRootPath, memberCredentials);
121
+ return {
122
+ rootId: trustchain.rootId,
123
+ walletSyncEncryptionKey,
124
+ applicationPath: applicationRootPath,
125
+ };
126
+ }
127
+ async getMembers(trustchain, memberCredentials) {
128
+ const { resolved } = await this.withAuth(trustchain, memberCredentials, jwt => this.fetchTrustchainAndResolve(jwt, trustchain.rootId, this.context.applicationId));
129
+ const members = resolved.getMembersData();
130
+ if (!members.some(m => m.id === memberCredentials.pubkey)) {
131
+ throw new errors_2.TrustchainEjected("Not a member of trustchain");
132
+ }
133
+ return members;
197
134
  }
198
- addMember(trustchain, memberCredentials, member) {
199
- return __awaiter(this, void 0, void 0, function* () {
200
- const withJwt = f => this.withAuth(trustchain, memberCredentials, f);
201
- const { streamTree, applicationRootPath } = yield withJwt(jwt => this.fetchTrustchainAndResolve(jwt, trustchain.rootId, this.context.applicationId));
202
- const softwareDevice = getSoftwareDevice(memberCredentials);
203
- const withSw = (job) => job(softwareDevice);
204
- yield this.pushMember(streamTree, applicationRootPath, trustchain.rootId, withJwt, withSw, member);
135
+ async removeMember(deviceId, trustchain, memberCredentials, member, callbacks) {
136
+ this.invalidateJwt();
137
+ const withJwt = job => this.hwDeviceProvider.withJwt(deviceId, job, "cache", callbacks);
138
+ const withHw = job => this.hwDeviceProvider.withHw(deviceId, job, callbacks);
139
+ // invariant because the sdk does not support this case, and the UI should not allows it.
140
+ invariant(memberCredentials.pubkey !== member.id, "removeMember must not be used to remove the current member.");
141
+ const afterRotation = await this.lifecycle?.onTrustchainRotation(this, trustchain, memberCredentials);
142
+ const applicationId = this.context.applicationId;
143
+ const trustchainId = trustchain.rootId;
144
+ // eslint-disable-next-line prefer-const
145
+ let { resolved, streamTree, applicationRootPath } = await withJwt(jwt => this.fetchTrustchainAndResolve(jwt, trustchainId, applicationId));
146
+ const members = resolved.getMembersData();
147
+ const withoutMember = members.filter(m => m.id !== member.id);
148
+ invariant(withoutMember.length < members.length, "member not found"); // invariant because the UI should not allow this case.
149
+ const withoutMemberOrMe = withoutMember.filter(m => m.id !== memberCredentials.pubkey);
150
+ const softwareDevice = getSoftwareDevice(memberCredentials);
151
+ const newPath = streamTree.getApplicationRootPath(applicationId, 1);
152
+ // We close the current trustchain with the hardware wallet in order to get a user confirmation of the action
153
+ const sendCloseStreamToAPI = await this.closeStream(streamTree, applicationRootPath, trustchainId, withJwt, withHw);
154
+ // derive a new branch of the tree on the new path
155
+ streamTree = await this.pushMember(streamTree, newPath, trustchainId, withJwt, withHw, {
156
+ id: memberCredentials.pubkey,
157
+ name: this.context.name,
158
+ permissions: hw_ledger_key_ring_protocol_1.Permissions.OWNER,
205
159
  });
160
+ // add the remaining members
161
+ const withSw = (job) => job(softwareDevice);
162
+ for (const m of withoutMemberOrMe) {
163
+ streamTree = await this.pushMember(streamTree, newPath, trustchainId, withJwt, withSw, m);
164
+ }
165
+ const walletSyncEncryptionKey = await extractEncryptionKey(streamTree, newPath, memberCredentials);
166
+ // we send the close stream to the API only after the new stream is created in case user cancelled the process in the middle.
167
+ await sendCloseStreamToAPI();
168
+ // deviceJwt have changed, proactively refresh it
169
+ await this.hwDeviceProvider.refreshJwt(deviceId, callbacks);
170
+ const newTrustchain = {
171
+ rootId: trustchainId,
172
+ walletSyncEncryptionKey,
173
+ applicationPath: newPath,
174
+ };
175
+ if (afterRotation)
176
+ await afterRotation(newTrustchain);
177
+ // refresh the jwt with the new trustchain
178
+ this.jwt = await this.withAuth(newTrustchain, memberCredentials, jwt => Promise.resolve(jwt), "refresh");
179
+ return newTrustchain;
180
+ }
181
+ async addMember(trustchain, memberCredentials, member) {
182
+ const withJwt = f => this.withAuth(trustchain, memberCredentials, f);
183
+ const { streamTree, applicationRootPath } = await withJwt(jwt => this.fetchTrustchainAndResolve(jwt, trustchain.rootId, this.context.applicationId));
184
+ const softwareDevice = getSoftwareDevice(memberCredentials);
185
+ const withSw = (job) => job(softwareDevice);
186
+ await this.pushMember(streamTree, applicationRootPath, trustchain.rootId, withJwt, withSw, member);
206
187
  }
207
188
  invalidateJwt() {
208
189
  this.jwt = undefined;
209
190
  this.hwDeviceProvider.clearJwt();
210
191
  }
211
- destroyTrustchain(trustchain, memberCredentials) {
212
- return __awaiter(this, void 0, void 0, function* () {
213
- yield this.withAuth(trustchain, memberCredentials, jwt => this.api.deleteTrustchain(jwt, trustchain.rootId));
214
- this.invalidateJwt();
215
- });
192
+ async destroyTrustchain(trustchain, memberCredentials) {
193
+ await this.withAuth(trustchain, memberCredentials, jwt => this.api.deleteTrustchain(jwt, trustchain.rootId));
194
+ this.invalidateJwt();
216
195
  }
217
- encryptUserData(trustchain, input) {
218
- return __awaiter(this, void 0, void 0, function* () {
219
- const key = hw_ledger_key_ring_protocol_1.crypto.from_hex(trustchain.walletSyncEncryptionKey);
220
- const encrypted = yield hw_ledger_key_ring_protocol_1.crypto.encryptUserData(key, input);
221
- return encrypted;
222
- });
196
+ async encryptUserData(trustchain, input) {
197
+ const key = hw_ledger_key_ring_protocol_1.crypto.from_hex(trustchain.walletSyncEncryptionKey);
198
+ const encrypted = await hw_ledger_key_ring_protocol_1.crypto.encryptUserData(key, input);
199
+ return encrypted;
223
200
  }
224
- decryptUserData(trustchain, data) {
225
- return __awaiter(this, void 0, void 0, function* () {
226
- const key = hw_ledger_key_ring_protocol_1.crypto.from_hex(trustchain.walletSyncEncryptionKey);
227
- const decrypted = yield hw_ledger_key_ring_protocol_1.crypto.decryptUserData(key, data);
228
- return decrypted;
229
- });
201
+ async decryptUserData(trustchain, data) {
202
+ const key = hw_ledger_key_ring_protocol_1.crypto.from_hex(trustchain.walletSyncEncryptionKey);
203
+ const decrypted = await hw_ledger_key_ring_protocol_1.crypto.decryptUserData(key, data);
204
+ return decrypted;
230
205
  }
231
- fetchTrustchain(jwt, trustchainId) {
232
- return __awaiter(this, void 0, void 0, function* () {
233
- const trustchainData = yield this.api.getTrustchain(jwt, trustchainId);
234
- const streamTree = hw_ledger_key_ring_protocol_1.StreamTree.deserialize(trustchainData);
235
- return { streamTree };
236
- });
237
- }
238
- fetchTrustchainAndResolve(jwt, trustchainId, applicationId) {
239
- return __awaiter(this, void 0, void 0, function* () {
240
- const { streamTree } = yield this.fetchTrustchain(jwt, trustchainId);
241
- const applicationRootPath = streamTree.getApplicationRootPath(applicationId);
242
- const applicationNode = streamTree.getChild(applicationRootPath);
243
- invariant(applicationNode, "could not find the application stream.");
244
- const resolved = yield applicationNode.resolve();
245
- return { resolved, streamTree, applicationRootPath, applicationNode };
246
- });
206
+ async fetchTrustchain(jwt, trustchainId) {
207
+ const trustchainData = await this.api.getTrustchain(jwt, trustchainId);
208
+ const streamTree = hw_ledger_key_ring_protocol_1.StreamTree.deserialize(trustchainData);
209
+ return { streamTree };
247
210
  }
248
- auth(trustchain, memberCredentials) {
249
- return __awaiter(this, void 0, void 0, function* () {
250
- const challenge = yield this.api.getAuthenticationChallenge();
251
- const data = hw_ledger_key_ring_protocol_1.crypto.from_hex(challenge.tlv);
252
- const [parsed, _] = hw_ledger_key_ring_protocol_1.Challenge.fromBytes(data);
253
- const hash = yield hw_ledger_key_ring_protocol_1.crypto.hash(parsed.getUnsignedTLV());
254
- const keypair = convertLiveCredentialsToKeyPair(memberCredentials);
255
- const response = yield this.api
256
- .postChallengeResponse({
257
- challenge: challenge.json,
258
- signature: {
259
- credential: credentialForPubKey(memberCredentials.pubkey),
260
- signature: hw_ledger_key_ring_protocol_1.crypto.to_hex(yield hw_ledger_key_ring_protocol_1.crypto.sign(hash, keypair)),
261
- attestation: hw_ledger_key_ring_protocol_1.crypto.to_hex(liveAuthentication(trustchain.rootId)),
262
- },
263
- })
264
- .catch(e => {
265
- if (e instanceof errors_1.LedgerAPI4xx &&
266
- (e.message.includes("Not a member of trustchain") ||
267
- e.message.includes("You are not member"))) {
268
- throw new errors_2.TrustchainEjected(e.message);
269
- }
270
- throw e;
271
- });
272
- return response;
273
- });
211
+ async fetchTrustchainAndResolve(jwt, trustchainId, applicationId) {
212
+ const { streamTree } = await this.fetchTrustchain(jwt, trustchainId);
213
+ const applicationRootPath = streamTree.getApplicationRootPath(applicationId);
214
+ const applicationNode = streamTree.getChild(applicationRootPath);
215
+ invariant(applicationNode, "could not find the application stream.");
216
+ const resolved = await applicationNode.resolve();
217
+ return { resolved, streamTree, applicationRootPath, applicationNode };
274
218
  }
275
- pushMember(streamTree, path, trustchainId, withJwt, withDevice, member) {
276
- return __awaiter(this, void 0, void 0, function* () {
277
- const isMemberAlreadyInStreamTree = yield isMemberInStreamTree(streamTree, path, member);
278
- if (isMemberAlreadyInStreamTree) {
279
- return streamTree;
280
- }
281
- const isNewDerivation = !streamTree.getChild(path);
282
- streamTree = yield withDevice(device => streamTree.share(path, device, hw_ledger_key_ring_protocol_1.crypto.from_hex(member.id), member.name, member.permissions));
283
- const child = streamTree.getChild(path);
284
- invariant(child, "StreamTree.share failed to create the child stream.");
285
- yield child.resolve(); // double checks the signatures are correct before sending to the backend
286
- if (isNewDerivation) {
287
- const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode(child.blocks);
288
- yield withJwt(jwt => this.api.postDerivation(jwt, trustchainId, hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)));
289
- }
290
- else {
291
- const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode([child.blocks[child.blocks.length - 1]]);
292
- const request = {
293
- path,
294
- blocks: [hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)],
295
- };
296
- yield withJwt(jwt => this.api.putCommands(jwt, trustchainId, request));
219
+ async auth(trustchain, memberCredentials) {
220
+ const challenge = await this.api.getAuthenticationChallenge();
221
+ const data = hw_ledger_key_ring_protocol_1.crypto.from_hex(challenge.tlv);
222
+ const [parsed, _] = hw_ledger_key_ring_protocol_1.Challenge.fromBytes(data);
223
+ const hash = await hw_ledger_key_ring_protocol_1.crypto.hash(parsed.getUnsignedTLV());
224
+ const keypair = convertLiveCredentialsToKeyPair(memberCredentials);
225
+ const response = await this.api
226
+ .postChallengeResponse({
227
+ challenge: challenge.json,
228
+ signature: {
229
+ credential: credentialForPubKey(memberCredentials.pubkey),
230
+ signature: hw_ledger_key_ring_protocol_1.crypto.to_hex(await hw_ledger_key_ring_protocol_1.crypto.sign(hash, keypair)),
231
+ attestation: hw_ledger_key_ring_protocol_1.crypto.to_hex(liveAuthentication(trustchain.rootId)),
232
+ },
233
+ })
234
+ .catch(e => {
235
+ if (e instanceof errors_1.LedgerAPI4xx &&
236
+ (e.message.includes("Not a member of trustchain") ||
237
+ e.message.includes("You are not member"))) {
238
+ throw new errors_2.TrustchainEjected(e.message);
297
239
  }
298
- return streamTree;
240
+ throw e;
299
241
  });
242
+ return response;
300
243
  }
301
- closeStream(streamTree, path, trustchainId, withJwt, withDevice) {
302
- return __awaiter(this, void 0, void 0, function* () {
303
- streamTree = yield withDevice(device => streamTree.close(path, device));
304
- const child = streamTree.getChild(path);
305
- invariant(child, "StreamTree.close failed to create the child stream.");
306
- yield child.resolve(); // double checks the signatures are correct before sending to the backend
244
+ async pushMember(streamTree, path, trustchainId, withJwt, withDevice, member) {
245
+ const isMemberAlreadyInStreamTree = await isMemberInStreamTree(streamTree, path, member);
246
+ if (isMemberAlreadyInStreamTree) {
247
+ return streamTree;
248
+ }
249
+ const isNewDerivation = !streamTree.getChild(path);
250
+ streamTree = await withDevice(device => streamTree.share(path, device, hw_ledger_key_ring_protocol_1.crypto.from_hex(member.id), member.name, member.permissions));
251
+ const child = streamTree.getChild(path);
252
+ invariant(child, "StreamTree.share failed to create the child stream.");
253
+ await child.resolve(); // double checks the signatures are correct before sending to the backend
254
+ if (isNewDerivation) {
255
+ const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode(child.blocks);
256
+ await withJwt(jwt => this.api.postDerivation(jwt, trustchainId, hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)));
257
+ }
258
+ else {
307
259
  const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode([child.blocks[child.blocks.length - 1]]);
308
260
  const request = {
309
261
  path,
310
262
  blocks: [hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)],
311
263
  };
312
- return () => withJwt(jwt => this.api.putCommands(jwt, trustchainId, request));
313
- });
264
+ await withJwt(jwt => this.api.putCommands(jwt, trustchainId, request));
265
+ }
266
+ return streamTree;
267
+ }
268
+ async closeStream(streamTree, path, trustchainId, withJwt, withDevice) {
269
+ streamTree = await withDevice(device => streamTree.close(path, device));
270
+ const child = streamTree.getChild(path);
271
+ invariant(child, "StreamTree.close failed to create the child stream.");
272
+ await child.resolve(); // double checks the signatures are correct before sending to the backend
273
+ const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode([child.blocks[child.blocks.length - 1]]);
274
+ const request = {
275
+ path,
276
+ blocks: [hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)],
277
+ };
278
+ return () => withJwt(jwt => this.api.putCommands(jwt, trustchainId, request));
314
279
  }
315
280
  }
316
281
  exports.SDK = SDK;
@@ -332,22 +297,20 @@ function getSoftwareDevice(memberCredentials) {
332
297
  const kp = convertLiveCredentialsToKeyPair(memberCredentials);
333
298
  return new hw_ledger_key_ring_protocol_1.SoftwareDevice(kp);
334
299
  }
335
- function extractEncryptionKey(streamTree, path, memberCredentials) {
336
- return __awaiter(this, void 0, void 0, function* () {
337
- const softwareDevice = getSoftwareDevice(memberCredentials);
338
- const pathNumbers = hw_ledger_key_ring_protocol_1.DerivationPath.toIndexArray(path);
339
- try {
340
- const key = yield softwareDevice.readKey(streamTree, pathNumbers);
341
- // private key is in the first 32 bytes
342
- return hw_ledger_key_ring_protocol_1.crypto.to_hex(key.slice(0, 32));
343
- }
344
- catch (e) {
345
- if (e instanceof Error) {
346
- throw new errors_2.TrustchainEjected(e.message);
347
- }
348
- throw e;
300
+ async function extractEncryptionKey(streamTree, path, memberCredentials) {
301
+ const softwareDevice = getSoftwareDevice(memberCredentials);
302
+ const pathNumbers = hw_ledger_key_ring_protocol_1.DerivationPath.toIndexArray(path);
303
+ try {
304
+ const key = await softwareDevice.readKey(streamTree, pathNumbers);
305
+ // private key is in the first 32 bytes
306
+ return hw_ledger_key_ring_protocol_1.crypto.to_hex(key.slice(0, 32));
307
+ }
308
+ catch (e) {
309
+ if (e instanceof Error) {
310
+ throw new errors_2.TrustchainEjected(e.message);
349
311
  }
350
- });
312
+ throw e;
313
+ }
351
314
  }
352
315
  // spec https://ledgerhq.atlassian.net/wiki/spaces/TA/pages/4335960138/ARCH+LedgerLive+Auth+specifications
353
316
  function liveAuthentication(rootId) {
@@ -366,15 +329,13 @@ function invariant(condition, message) {
366
329
  throw new Error(message);
367
330
  }
368
331
  }
369
- function isMemberInStreamTree(streamTree, path, member) {
370
- return __awaiter(this, void 0, void 0, function* () {
371
- const child = streamTree.getChild(path);
372
- if (!child) {
373
- return false;
374
- }
375
- const resolved = yield child.resolve();
376
- const members = resolved.getMembersData();
377
- return members.some(m => m.id === member.id);
378
- });
332
+ async function isMemberInStreamTree(streamTree, path, member) {
333
+ const child = streamTree.getChild(path);
334
+ if (!child) {
335
+ return false;
336
+ }
337
+ const resolved = await child.resolve();
338
+ const members = resolved.getMembersData();
339
+ return members.some(m => m.id === member.id);
379
340
  }
380
341
  //# sourceMappingURL=sdk.js.map