Skip to content

Commit 9f81b8e

Browse files
authored
Merge pull request #14 from kaloudis/loadKeysAndRunClient
lnc-web: allow Wasm binary to be downloaded w/o loading keys and running
2 parents ca6e4a0 + 6b7ed1a commit 9f81b8e

File tree

1 file changed

+102
-83
lines changed

1 file changed

+102
-83
lines changed

lib/index.ts

Lines changed: 102 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ interface LncConstructor {
6464
/** Specify a custom Lightning Node Connect proxy server. If not specified we'll default to `mailbox.terminal.lightning.today:443`. */
6565
serverHost?: string;
6666
/** Your LNC pairing phrase */
67-
pairingPhrase: string;
67+
pairingPhrase?: string;
6868
/** local private key; part of the second handshake authentication process. Only need to specify this if you handle storage of auth data yourself and set `onLocalPrivCreate`. */
6969
localKey?: string;
7070
/** remote public key; part of the second handshake authentication process. Only need to specify this if you handle storage of auth data yourself and set `onRemoteKeyReceive`. */
@@ -83,8 +83,10 @@ interface LncConstructor {
8383

8484
export default class LNC {
8585
go: any;
86-
mod?: WebAssembly.Module;
87-
inst?: WebAssembly.Instance;
86+
result?: {
87+
module: WebAssembly.Module;
88+
instance: WebAssembly.Instance;
89+
};
8890

8991
_serverHost: string;
9092
_pairingPhrase: string;
@@ -106,7 +108,7 @@ export default class LNC {
106108
constructor(config: LncConstructor) {
107109
this._serverHost =
108110
config.serverHost || 'mailbox.terminal.lightning.today:443';
109-
this._pairingPhrase = config.pairingPhrase;
111+
this._pairingPhrase = config.pairingPhrase || '';
110112
this._localKey = config.localKey;
111113
this._remoteKey = config.remoteKey;
112114
this._wasmClientCode =
@@ -185,98 +187,113 @@ export default class LNC {
185187
);
186188
}
187189

190+
setPairingPhrase(pairingPhrase: string) {
191+
this._pairingPhrase = pairingPhrase;
192+
}
193+
194+
setLocalKey(localKey: string) {
195+
this._localKey = localKey;
196+
}
197+
198+
setRemoteKey(remoteKey: string) {
199+
this._remoteKey = remoteKey;
200+
}
201+
202+
setServerHost(serverHost: string) {
203+
this._serverHost = serverHost;
204+
}
205+
188206
clearStorage = () =>
189207
Object.entries(localStorage)
190208
.map((x) => x[0])
191209
.filter((x) => x.substring(0, 8) == 'lnc-web:')
192210
.map((x) => localStorage.removeItem(x));
193211

194212
/**
195-
* Downloads the WASM client binary and run
213+
* Downloads the WASM client binary
196214
*/
197-
async load() {
198-
try {
199-
const result = await WebAssembly.instantiateStreaming(
200-
fetch(this._wasmClientCode),
201-
this.go.importObject
202-
);
203-
log.info('downloaded WASM file');
204-
205-
let localKey = '';
206-
let remoteKey = '';
215+
async preload() {
216+
this.result = await WebAssembly.instantiateStreaming(
217+
fetch(this._wasmClientCode),
218+
this.go.importObject
219+
);
220+
log.info('downloaded WASM file');
221+
}
207222

208-
if (this._localKey) {
209-
localKey = this._localKey;
210-
} else if (
211-
localStorage.getItem(`lnc-web:${this._namespace}:localKey`)
212-
) {
213-
const data = localStorage.getItem(
214-
`lnc-web:${this._namespace}:localKey`
215-
);
216-
if (
217-
!verifyTestCipher(
218-
this.testCipher,
219-
this._password,
220-
this.salt
221-
)
222-
) {
223-
throw new Error('Invalid Password');
224-
}
225-
localKey = this._password
226-
? decrypt(data, this._password, this.salt)
227-
: data;
223+
/**
224+
* Loads keys from storage and runs the Wasm client binary
225+
*/
226+
async loadKeysAndRunClient() {
227+
// make sure the WASM client binary is downloaded first
228+
if (!this.isReady) await this.preload();
229+
230+
let localKey = '';
231+
let remoteKey = '';
232+
233+
if (this._localKey) {
234+
localKey = this._localKey;
235+
} else if (
236+
localStorage.getItem(`lnc-web:${this._namespace}:localKey`)
237+
) {
238+
const data = localStorage.getItem(
239+
`lnc-web:${this._namespace}:localKey`
240+
);
241+
if (!verifyTestCipher(this.testCipher, this._password, this.salt)) {
242+
throw new Error('Invalid Password');
228243
}
244+
localKey = this._password
245+
? decrypt(data, this._password, this.salt)
246+
: data;
247+
}
229248

230-
if (this._remoteKey) {
231-
remoteKey = this._remoteKey;
232-
} else if (
233-
localStorage.getItem(`lnc-web:${this._namespace}:remoteKey`)
234-
) {
235-
const data = localStorage.getItem(
236-
`lnc-web:${this._namespace}:remoteKey`
237-
);
238-
if (
239-
!verifyTestCipher(
240-
this.testCipher,
241-
this._password,
242-
this.salt
243-
)
244-
) {
245-
throw new Error('Invalid password');
246-
}
247-
remoteKey = this._password
248-
? decrypt(data, this._password, this.salt)
249-
: data;
249+
if (this._remoteKey) {
250+
remoteKey = this._remoteKey;
251+
} else if (
252+
localStorage.getItem(`lnc-web:${this._namespace}:remoteKey`)
253+
) {
254+
const data = localStorage.getItem(
255+
`lnc-web:${this._namespace}:remoteKey`
256+
);
257+
if (!verifyTestCipher(this.testCipher, this._password, this.salt)) {
258+
throw new Error('Invalid password');
250259
}
260+
remoteKey = this._password
261+
? decrypt(data, this._password, this.salt)
262+
: data;
263+
}
251264

252-
log.debug('localKey', localKey);
253-
log.debug('remoteKey', remoteKey);
254-
255-
global.onLocalPrivCreate =
256-
this._onLocalPrivCreate || this.onLocalPrivCreate;
257-
258-
global.onRemoteKeyReceive =
259-
this._onRemoteKeyReceive || this.onRemoteKeyReceive;
260-
261-
global.onAuthData = (keyHex: string) => {
262-
log.debug('auth data received: ' + keyHex);
263-
};
264-
265-
this.go.argv = [
266-
'wasm-client',
267-
'--debuglevel=trace',
268-
'--namespace=' + this._namespace,
269-
'--localprivate=' + localKey,
270-
'--remotepublic=' + remoteKey,
271-
'--onlocalprivcreate=onLocalPrivCreate',
272-
'--onremotekeyreceive=onRemoteKeyReceive',
273-
'--onauthdata=onAuthData'
274-
];
275-
276-
this.go.run(result.instance);
277-
await WebAssembly.instantiate(result.module, this.go.importObject);
278-
} catch {
279-
throw new Error('The password provided is not valid.');
265+
log.debug('localKey', localKey);
266+
log.debug('remoteKey', remoteKey);
267+
268+
global.onLocalPrivCreate =
269+
this._onLocalPrivCreate || this.onLocalPrivCreate;
270+
271+
global.onRemoteKeyReceive =
272+
this._onRemoteKeyReceive || this.onRemoteKeyReceive;
273+
274+
global.onAuthData = (keyHex: string) => {
275+
log.debug('auth data received: ' + keyHex);
276+
};
277+
278+
this.go.argv = [
279+
'wasm-client',
280+
'--debuglevel=trace',
281+
'--namespace=' + this._namespace,
282+
'--localprivate=' + localKey,
283+
'--remotepublic=' + remoteKey,
284+
'--onlocalprivcreate=onLocalPrivCreate',
285+
'--onremotekeyreceive=onRemoteKeyReceive',
286+
'--onauthdata=onAuthData'
287+
];
288+
289+
if (this.result) {
290+
this.go.run(this.result.instance);
291+
await WebAssembly.instantiate(
292+
this.result.module,
293+
this.go.importObject
294+
);
295+
} else {
296+
throw new Error("Can't find WASM instance.");
280297
}
281298
}
282299

@@ -293,6 +310,8 @@ export default class LNC {
293310
// do not attempt to connect multiple times
294311
if (this.isConnected) return;
295312

313+
await this.loadKeysAndRunClient();
314+
296315
// ensure the WASM binary is loaded
297316
if (!this.isReady) await this.waitTilReady();
298317

0 commit comments

Comments
 (0)