@leofcoin/peernet 0.11.31 → 0.12.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.
Files changed (41) hide show
  1. package/dist/browser/generate-account.js +50 -0
  2. package/dist/browser/messages.js +439 -0
  3. package/dist/browser/pako.js +6731 -0
  4. package/dist/browser/peernet-swarm.js +836 -0
  5. package/dist/browser/peernet.js +7576 -54848
  6. package/dist/browser/protons.js +3786 -0
  7. package/dist/browser/storage.js +12 -0
  8. package/dist/browser/wrtc.js +28 -0
  9. package/dist/commonjs/dht-6a1b6246.js +45 -0
  10. package/dist/commonjs/dht-response-e4a603ea.js +34 -0
  11. package/dist/commonjs/dht-response.js +3 -24
  12. package/dist/commonjs/dht.js +3 -35
  13. package/dist/commonjs/messages-bcb02ee9.js +189 -0
  14. package/dist/commonjs/{peernet-message.js → peernet-6eef77d5.js} +12 -7
  15. package/dist/commonjs/peernet.js +60 -1368
  16. package/dist/commonjs/peernet2.js +8 -0
  17. package/dist/commonjs/request-95ed03ec.js +33 -0
  18. package/dist/commonjs/request.js +3 -23
  19. package/dist/commonjs/response-bae4e2a2.js +33 -0
  20. package/dist/commonjs/response.js +3 -23
  21. package/dist/module/messages-421f88db.js +323 -0
  22. package/dist/module/peernet.js +53 -1451
  23. package/package.json +7 -12
  24. package/rollup.config.js +2 -21
  25. package/src/discovery/peer-discovery.js +4 -4
  26. package/src/handlers/data.js +2 -2
  27. package/src/handlers/message.js +4 -5
  28. package/src/messages/{chat-message.js → chat.js} +5 -2
  29. package/src/messages/data-response.js +5 -2
  30. package/src/messages/data.js +5 -2
  31. package/src/messages/dht-response.js +5 -2
  32. package/src/messages/dht.js +5 -2
  33. package/src/messages/peer-response.js +5 -2
  34. package/src/messages/peer.js +5 -2
  35. package/src/messages/{peernet-message.js → peernet.js} +5 -2
  36. package/src/messages/ps.js +5 -2
  37. package/src/messages/request.js +5 -2
  38. package/src/messages/response.js +5 -2
  39. package/src/messages.js +11 -0
  40. package/src/peernet.js +45 -32
  41. package/webpack.config.js +6 -3
@@ -1,910 +1,6 @@
1
1
  import '@vandeurenglenn/debug';
2
- import pako from 'pako';
3
- import LeofcoinStorage from '@leofcoin/storage';
4
- import protons from 'protons';
5
- import { FormatInterface, Codec, CodecHash, codecs } from '@leofcoin/codec-format-interface';
6
- import MultiWallet$1 from '@leofcoin/multi-wallet';
7
- import * as bs58check from 'bs58check';
8
- import bs58check__default from 'bs58check';
9
- import * as bip32 from 'bip32';
10
- import createKeccakHash from 'keccak';
11
- import ecc from 'tiny-secp256k1';
12
- import Mnemonic from '@leofcoin/mnemonic';
13
- import MultiSignature from 'multi-signature';
14
- import varint from 'varint';
15
- import randombytes from 'randombytes';
16
-
17
- /* socket-request-client version 1.6.3 */
18
-
19
- class LittlePubSub {
20
- constructor(verbose = true) {
21
- this.subscribers = {};
22
- this.verbose = verbose;
23
- }
24
- subscribe(event, handler, context) {
25
- if (typeof context === 'undefined') {
26
- context = handler;
27
- }
28
- this.subscribers[event] = this.subscribers[event] || { handlers: [], value: null};
29
- this.subscribers[event].handlers.push(handler.bind(context));
30
- }
31
- unsubscribe(event, handler, context) {
32
- if (typeof context === 'undefined') {
33
- context = handler;
34
- }
35
- if (this.subscribers[event]) {
36
- const index = this.subscribers[event].handlers.indexOf(handler.bind(context));
37
- this.subscribers[event].handlers.splice(index);
38
- if (this.subscribers[event].handlers.length === 0) delete this.subscribers[event];
39
- }
40
- }
41
- publish(event, change) {
42
- if (this.subscribers[event]) {
43
- if (this.verbose || this.subscribers[event].value !== change) {
44
- this.subscribers[event].value = change;
45
- this.subscribers[event].handlers.forEach(handler => {
46
- handler(change, this.subscribers[event].value);
47
- });
48
- }
49
- }
50
- }
51
- }
52
-
53
- var clientApi = _pubsub => {
54
- const subscribe = (topic, cb) => {
55
- _pubsub.subscribe(topic, cb);
56
- };
57
- const unsubscribe = (topic, cb) => {
58
- _pubsub.unsubscribe(topic, cb);
59
- };
60
- const publish = (topic, value) => {
61
- _pubsub.publish(topic, value);
62
- };
63
- const _connectionState = (state) => {
64
- switch (state) {
65
- case 0:
66
- return 'connecting'
67
- case 1:
68
- return 'open'
69
- case 2:
70
- return 'closing'
71
- case 3:
72
- return 'closed'
73
- }
74
- };
75
- const request = (client, request) => {
76
- return new Promise((resolve, reject) => {
77
- const state = _connectionState(client.readyState);
78
- if (state !== 'open') return reject(`coudn't send request to ${client.id}, no open connection found.`)
79
- request.id = Math.random().toString(36).slice(-12);
80
- const handler = result => {
81
- if (result && result.error) return reject(result.error)
82
- resolve({result, id: request.id, handler});
83
- unsubscribe(request.id, handler);
84
- };
85
- subscribe(request.id, handler);
86
- send(client, request);
87
- });
88
- };
89
- const send = async (client, request) => {
90
- return client.send(JSON.stringify(request))
91
- };
92
- const pubsub = client => {
93
- return {
94
- publish: (topic = 'pubsub', value) => {
95
- return send(client, {url: 'pubsub', params: { topic, value }})
96
- },
97
- subscribe: (topic = 'pubsub', cb) => {
98
- subscribe(topic, cb);
99
- return send(client, {url: 'pubsub', params: { topic, subscribe: true }})
100
- },
101
- unsubscribe: (topic = 'pubsub', cb) => {
102
- unsubscribe(topic, cb);
103
- return send(client, {url: 'pubsub', params: { topic, unsubscribe: true }})
104
- },
105
- subscribers: _pubsub.subscribers
106
- }
107
- };
108
- const server = (client) => {
109
- return {
110
- uptime: async () => {
111
- try {
112
- const { result, id, handler } = await request(client, {url: 'uptime'});
113
- unsubscribe(id, handler);
114
- return result
115
- } catch (e) {
116
- throw e
117
- }
118
- },
119
- ping: async () => {
120
- try {
121
- const now = new Date().getTime();
122
- const { result, id, handler } = await request(client, {url: 'ping'});
123
- unsubscribe(id, handler);
124
- return (Number(result) - now)
125
- } catch (e) {
126
- throw e
127
- }
128
- }
129
- }
130
- };
131
- const peernet = (client) => {
132
- return {
133
- join: async (params) => {
134
- try {
135
- params.join = true;
136
- const requested = { url: 'peernet', params };
137
- const { result, id, handler } = await request(client, requested);
138
- unsubscribe(id, handler);
139
- return result
140
- } catch (e) {
141
- throw e
142
- }
143
- },
144
- leave: async (params) => {
145
- try {
146
- params.join = false;
147
- const requested = { url: 'peernet', params };
148
- const { result, id, handler } = await request(client, requested);
149
- unsubscribe(id, handler);
150
- return result
151
- } catch (e) {
152
- throw e
153
- }
154
- }
155
- }
156
- };
157
- return { send, request, pubsub, server, subscribe, unsubscribe, publish, peernet }
158
- };
159
-
160
- if (!globalThis.PubSub) globalThis.PubSub = LittlePubSub;
161
- if (!globalThis.pubsub) globalThis.pubsub = new LittlePubSub({verbose: false});
162
- const socketRequestClient = (url, protocols = 'echo-protocol', options = { retry: false }) => {
163
- const { retry } = options;
164
- const api = clientApi(pubsub);
165
- let tries = 0;
166
- const onerror = error => {
167
- if (pubsub.subscribers['error']) {
168
- pubsub.publish('error', error);
169
- } else {
170
- console.error(error);
171
- }
172
- };
173
- const onmessage = message => {
174
- const {value, url, status, id} = JSON.parse(message.data.toString());
175
- const publisher = id ? id : url;
176
- if (status === 200) {
177
- pubsub.publish(publisher, value);
178
- } else {
179
- pubsub.publish(publisher, {error: value});
180
- }
181
- };
182
- const clientConnection = client => {
183
- const startTime = new Date().getTime();
184
- return {
185
- client,
186
- request: async req => {
187
- const { result, id, handler } = await api.request(client, req);
188
- pubsub.unsubscribe(id, handler);
189
- return result
190
- },
191
- send: req => api.send(client, req),
192
- subscribe: api.subscribe,
193
- unsubscribe: api.unsubscribe,
194
- subscribers: api.subscribers,
195
- publish: api.publish,
196
- pubsub: api.pubsub(client),
197
- uptime: () => {
198
- const now = new Date().getTime();
199
- return (now - startTime)
200
- },
201
- peernet: api.peernet(client),
202
- server: api.server(client),
203
- close: exit => {
204
- client.close();
205
- }
206
- }
207
- };
208
- return new Promise((resolve, reject) => {
209
- const init = () => {
210
- let ws;
211
- if (typeof process === 'object' && !globalThis.WebSocket) {
212
- ws = require('websocket').w3cwebsocket;
213
- } else {
214
- ws = WebSocket;
215
- }
216
- const client = new ws(url, protocols);
217
- client.onmessage = onmessage;
218
- client.onerror = onerror;
219
- client.onopen = () => {
220
- tries = 0;
221
- resolve(clientConnection(client));
222
- };
223
- client.onclose = message => {
224
- tries++;
225
- if (!retry) return reject(options)
226
- if (tries > 5) {
227
- console.log(`${protocols} Client Closed`);
228
- console.error(`could not connect to - ${url}/`);
229
- return resolve(clientConnection(client))
230
- }
231
- if (message.code === 1006) {
232
- console.log('Retrying in 10 seconds');
233
- setTimeout(() => {
234
- return init();
235
- }, retry);
236
- }
237
- };
238
- };
239
- return init();
240
- });
241
- };
242
-
243
- class Peer {
244
- #connection
245
- #connecting = false
246
- #connected = false
247
- #channelReady = false
248
- #destroying = false
249
- #destroyed = false
250
- #isNegotiating = false
251
- #firstNegotiation = true
252
- #iceComplete = false
253
- #remoteTracks = []
254
- #remoteStreams = []
255
- #pendingCandidates = []
256
- #senderMap = new Map()
257
- #messageQue = []
258
- #chunksQue = {}
259
- #iceCompleteTimer
260
- #channel
261
- #peerId
262
- #chunkSize = 16 * 1024 // 16384
263
- #queRunning = false
264
- #MAX_BUFFERED_AMOUNT = 16 * 1024 * 1024
265
-
266
- get connection() {
267
- return this.#connection
268
- }
269
-
270
- get connected() {
271
- return this.#connected
272
- }
273
-
274
- get readyState() {
275
- return this.channel?.readyState
276
- }
277
-
278
- /**
279
- * @params {Object} options
280
- * @params {string} options.channelName - this peerid : otherpeer id
281
- */
282
- constructor(options = {}) {
283
- this._in = this._in.bind(this);
284
- this.offerOptions = options.offerOptions;
285
- this.initiator = options.initiator;
286
- this.streams = options.streams;
287
- this.socketClient = options.socketClient;
288
- this.id = options.id;
289
- this.to = options.to;
290
- this.bw = {
291
- up: 0,
292
- down: 0
293
- };
294
-
295
- this.channelName = options.channelName;
296
-
297
- this.#peerId = options.peerId;
298
- this.options = options;
299
- this.#init();
300
- }
301
-
302
- get peerId() {
303
- return this.#peerId
304
- }
305
-
306
- set socketClient(value) {
307
- // this.socketClient?.pubsub.unsubscribe('signal', this._in)
308
- this._socketClient = value;
309
- this._socketClient.pubsub.subscribe('signal', this._in);
310
- }
311
-
312
- get socketClient() {
313
- return this._socketClient
314
- }
315
-
316
- splitMessage(message) {
317
- const chunks = [];
318
- message = pako.deflate(message);
319
- const size = message.byteLength || message.length;
320
- let offset = 0;
321
- return new Promise((resolve, reject) => {
322
- const splitMessage = () => {
323
- const chunk = message.slice(offset, offset + this.#chunkSize > size ? size : offset + this.#chunkSize);
324
- offset += this.#chunkSize;
325
- chunks.push(chunk);
326
- if (offset < size) return splitMessage()
327
- else resolve({chunks, size});
328
- };
329
-
330
- splitMessage();
331
- })
332
- }
333
-
334
- async #runQue() {
335
- this.#queRunning = true;
336
- if (this.#messageQue.length > 0 && this.channel.bufferedAmount + this.#messageQue[0]?.length < this.#MAX_BUFFERED_AMOUNT) {
337
- const message = this.#messageQue.shift();
338
-
339
- switch (this.channel?.readyState) {
340
- case 'open':
341
- await this.channel.send(message);
342
- if (this.#messageQue.length > 0) return this.#runQue()
343
- else this.#queRunning = false;
344
- break;
345
- case 'closed':
346
- case 'closing':
347
- this.#messageQue = [];
348
- this.#queRunning = false;
349
- debug('channel already closed, this usually means a bad implementation, try checking the readyState or check if the peer is connected before sending');
350
- break;
351
- case undefined:
352
- this.#messageQue = [];
353
- this.#queRunning = false;
354
- debug(`trying to send before a channel is created`);
355
- break;
356
- }
357
-
358
-
359
- } else {
360
- return setTimeout(() => this.#runQue(), 50)
361
- }
362
- }
363
-
364
- #trySend({ size, id, chunks }) {
365
- let offset = 0;
366
-
367
- for (const chunk of chunks) {
368
- const start = offset;
369
- const end = offset + chunk.length;
370
-
371
- const message = new TextEncoder().encode(JSON.stringify({ size, id, chunk, start, end }));
372
- this.#messageQue.push(message);
373
- }
374
-
375
- if (!this.queRunning) return this.#runQue()
376
- }
377
-
378
- async send(message, id) {
379
- const { chunks, size } = await this.splitMessage(message);
380
- return this.#trySend({ size, id, chunks })
381
- }
382
-
383
- request(data) {
384
- return new Promise((resolve, reject) => {
385
- const id = Math.random().toString(36).slice(-12);
386
-
387
- const _onData = message => {
388
- if (message.id === id) {
389
- resolve(message.data);
390
- pubsub.unsubscribe(`peer:data`, _onData);
391
- }
392
- };
393
-
394
- pubsub.subscribe(`peer:data`, _onData);
395
-
396
- // cleanup subscriptions
397
- // setTimeout(() => {
398
- // pubsub.unsubscribe(`peer:data-request-${id}`, _onData)
399
- // }, 5000);
400
-
401
- this.send(data, id);
402
- })
403
- }
404
-
405
- async #init() {
406
- try {
407
- const iceServers = [{
408
- urls: 'stun:stun.l.google.com:19302' // Google's public STUN server
409
- }, {
410
- urls: "stun:openrelay.metered.ca:80",
411
- }, {
412
- urls: "turn:openrelay.metered.ca:443",
413
- username: "openrelayproject",
414
- credential: "openrelayproject",
415
- }, {
416
- urls: "turn:openrelay.metered.ca:443?transport=tcp",
417
- username: "openrelayproject",
418
- credential: "openrelayproject",
419
- }];
420
-
421
- this.#connection = new wrtc.RTCPeerConnection({iceServers});
422
-
423
- this.#connection.onicecandidate = ({ candidate }) => {
424
- if (candidate) {
425
- this.address = candidate.address;
426
- this.port = candidate.port;
427
- this.protocol = candidate.protocol;
428
- this.ipFamily = this.address.includes('::') ? 'ipv6': 'ipv4';
429
- this._sendMessage({candidate});
430
- }
431
- };
432
- // if (this.initiator) this.#connection.onnegotiationneeded = () => {
433
- // console.log('create offer');
434
- this.#connection.ondatachannel = (message) => {
435
- message.channel.onopen = () => {
436
- this.#connected = true;
437
- pubsub.publish('peer:connected', this);
438
- };
439
- message.channel.onclose = () => this.close.bind(this);
440
-
441
- message.channel.onmessage = (message) => {
442
- this._handleMessage(this.id, message);
443
- };
444
- this.channel = message.channel;
445
- };
446
- if (this.initiator) {
447
-
448
- this.channel = this.#connection.createDataChannel('messageChannel');
449
- this.channel.onopen = () => {
450
- this.#connected = true;
451
- pubsub.publish('peer:connected', this);
452
- // this.channel.send('hi')
453
- };
454
- this.channel.onclose = () => this.close.bind(this);
455
-
456
- this.channel.onmessage = (message) => {
457
- this._handleMessage(this.peerId, message);
458
- };
459
-
460
- const offer = await this.#connection.createOffer();
461
- await this.#connection.setLocalDescription(offer);
462
-
463
- this._sendMessage({'sdp': this.#connection.localDescription});
464
- }
465
- } catch (e) {
466
- console.log(e);
467
- }
468
- }
469
-
470
- _handleMessage(peerId, message) {
471
- debug(`incoming message from ${peerId}`);
472
-
473
- message = JSON.parse(new TextDecoder().decode(message.data));
474
- // allow sharding (multiple peers share data)
475
- pubsub.publish('peernet:shard', message);
476
- const { id } = message;
477
-
478
- if (!this.#chunksQue[id]) this.#chunksQue[id] = [];
479
-
480
- if (message.size > this.#chunksQue[id].length || message.size === this.#chunksQue[id].length) {
481
- for (const value of Object.values(message.chunk)) {
482
- this.#chunksQue[id].push(value);
483
- }
484
- }
485
-
486
- if (message.size === this.#chunksQue[id].length) {
487
- let data = new Uint8Array(Object.values(this.#chunksQue[id]));
488
- delete this.#chunksQue[id];
489
- data = pako.inflate(data);
490
- pubsub.publish('peer:data', { id, data });
491
- }
492
- this.bw.down += message.byteLength || message.length;
493
- }
494
-
495
- _sendMessage(message) {
496
- this.socketClient.send({url: 'signal', params: {
497
- to: this.to,
498
- from: this.id,
499
- channelName: this.options.channelName,
500
- ...message
501
- }});
502
- }
503
-
504
- async _in(message, data) {
505
- // message = JSON.parse(message);
506
- if (message.to !== this.id) return
507
- // if (data.videocall) return this._startStream(true, false); // start video and audio stream
508
- // if (data.call) return this._startStream(true, true); // start audio stream
509
- if (message.candidate) {
510
- debug(`incoming candidate ${this.channelName}`);
511
- debug(message.candidate.candidate);
512
- this.remoteAddress = message.candidate.address;
513
- this.remotePort = message.candidate.port;
514
- this.remoteProtocol = message.candidate.protocol;
515
- this.remoteIpFamily = this.remoteAddress?.includes('::') ? 'ipv6': 'ipv4';
516
- return this.#connection.addIceCandidate(new wrtc.RTCIceCandidate(message.candidate));
517
- }
518
- try {
519
- if (message.sdp) {
520
- if (message.sdp.type === 'offer') {
521
- debug(`incoming offer ${this.channelName}`);
522
- await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
523
- const answer = await this.#connection.createAnswer();
524
- await this.#connection.setLocalDescription(answer);
525
- this._sendMessage({'sdp': this.#connection.localDescription});
526
- }
527
- if (message.sdp.type === 'answer') {
528
- debug(`incoming answer ${this.channelName}`);
529
- await this.#connection.setRemoteDescription(new wrtc.RTCSessionDescription(message.sdp));
530
- }
531
- }
532
- } catch (e) {
533
- console.log(e);
534
- }
535
- }
536
-
537
- close() {
538
- debug(`closing ${this.peerId}`);
539
- this.#connected = false;
540
- this.channel?.close();
541
- this.#connection?.close();
542
-
543
- this.socketClient.pubsub.unsubscribe('signal', this._in);
544
- }
545
- }
546
-
547
- class Client {
548
- #peerConnection
549
- #connections = {}
550
- #stars = {}
551
-
552
- get connections() {
553
- return { ...this.#connections }
554
- }
555
-
556
- get peers() {
557
- return Object.entries(this.#connections)
558
- }
559
-
560
- constructor(id, identifiers = ['peernet-v0.1.0'], stars = []) {
561
- this.id = id || Math.random().toString(36).slice(-12);
562
- if (!Array.isArray(identifiers)) identifiers = [identifiers];
563
- this.peerJoined = this.peerJoined.bind(this);
564
- this.peerLeft = this.peerLeft.bind(this);
565
- this.starLeft = this.starLeft.bind(this);
566
- this.starJoined = this.starJoined.bind(this);
567
-
568
- this._init(identifiers, stars);
569
- }
570
-
571
- async _init(identifiers, stars = []) {
572
- if (stars.length === 0) {
573
- stars.push('wss://star.leofcoin.org');
574
- }
575
- this.identifiers = identifiers;
576
- this.starsConfig = stars;
577
- // reconnectJob()
578
-
579
- globalThis.wrtc = await import('wrtc');
580
- for (const star of stars) {
581
- try {
582
- this.socketClient = await socketRequestClient(star, identifiers[0]);
583
- const id = await this.socketClient.request({url: 'id', params: {from: this.id}});
584
- this.socketClient.peerId = id;
585
- this.#stars[id] = this.socketClient;
586
- } catch (e) {
587
- if (stars.indexOf(star) === stars.length -1 && !this.socketClient) throw new Error(`No star available to connect`);
588
- }
589
- }
590
- const peers = await this.socketClient.peernet.join({id: this.id});
591
- for (const id of peers) {
592
- if (id !== this.id && !this.#connections[id]) this.#connections[id] = new Peer({channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id});
593
- }
594
- this.setupListeners();
595
- }
596
-
597
- setupListeners() {
598
- this.socketClient.subscribe('peer:joined', this.peerJoined);
599
- this.socketClient.subscribe('peer:left', this.peerLeft);
600
- this.socketClient.subscribe('star:left', this.starLeft);
601
- }
602
-
603
- starJoined(id) {
604
- if (this.#stars[id]) {
605
- this.#stars[id].close();
606
- delete this.#stars[id];
607
- }
608
- console.log(`star ${id} joined`);
609
- }
610
-
611
- async starLeft(id) {
612
- if (this.#stars[id]) {
613
- this.#stars[id].close();
614
- delete this.#stars[id];
615
- }
616
- if (this.socketClient?.peerId === id) {
617
-
618
- this.socketClient.unsubscribe('peer:joined', this.peerJoined);
619
- this.socketClient.unsubscribe('peer:left', this.peerLeft);
620
- this.socketClient.unsubscribe('star:left', this.starLeft);
621
- this.socketClient.close();
622
- this.socketClient = undefined;
623
-
624
- for (const star of this.starsConfig) {
625
- try {
626
- this.socketClient = await socketRequestClient(star, this.identifiers[0]);
627
- if (!this.socketClient?.client?._connection.connected) return
628
- const id = await this.socketClient.request({url: 'id', params: {from: this.id}});
629
- this.#stars[id] = this.socketClient;
630
-
631
- this.socketClient.peerId = id;
632
-
633
- const peers = await this.socketClient.peernet.join({id: this.id});
634
- this.setupListeners();
635
- for (const id of peers) {
636
- if (id !== this.id) {
637
- // close connection
638
- if (this.#connections[id]) {
639
- if (this.#connections[id].connected) await this.#connections[id].close();
640
- delete this.#connections[id];
641
- }
642
- // reconnect
643
- if (id !== this.id) this.#connections[id] = new Peer({channelName: `${id}:${this.id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id});
644
- }
645
-
646
- }
647
- } catch (e) {
648
- console.log(e);
649
- if (this.starsConfig.indexOf(star) === this.starsConfig.length -1 && !this.socketClient) throw new Error(`No star available to connect`);
650
- }
651
- }
652
- }
653
- debug(`star ${id} left`);
654
- }
655
-
656
- peerLeft(peer) {
657
- const id = peer.peerId || peer;
658
- if (this.#connections[id]) {
659
- this.#connections[id].close();
660
- delete this.#connections[id];
661
- }
662
- debug(`peer ${id} left`);
663
- }
664
-
665
- peerJoined(peer, signal) {
666
- const id = peer.peerId || peer;
667
- if (this.#connections[id]) {
668
- if (this.#connections[id].connected) this.#connections[id].close();
669
- delete this.#connections[id];
670
- }
671
- // RTCPeerConnection
672
- this.#connections[id] = new Peer({initiator: true, channelName: `${this.id}:${id}`, socketClient: this.socketClient, id: this.id, to: id, peerId: id});
673
- debug(`peer ${id} joined`);
674
- }
675
-
676
- removePeer(peer) {
677
- const id = peer.peerId || peer;
678
- if (this.#connections[id]) {
679
- this.#connections[id].connected && this.#connections[id].close();
680
- delete this.#connections[id];
681
- }
682
- debug(`peer ${id} removed`);
683
- }
684
-
685
-
686
- }
687
-
688
- var proto$a = `
689
- // PeernetMessage
690
- message PeernetMessage {
691
- required bytes data = 1;
692
- required bytes signature = 2;
693
- optional string from = 3;
694
- optional string to = 4;
695
- optional string id = 5;
696
- }`;
697
-
698
- class PeernetMessage extends FormatInterface {
699
- get keys() {
700
- return ['data', 'signature', 'from', 'to', 'id']
701
- }
702
-
703
- constructor(buffer) {
704
- const name = 'peernet-message';
705
- super(buffer, protons(proto$a).PeernetMessage, {name});
706
- }
707
- }
708
-
709
- var proto$9 = `
710
- // PeernetDHTMessage
711
- message PeernetDHTMessage {
712
- required string hash = 1;
713
- optional string store = 2;
714
- }
715
- `;
716
-
717
- /**
718
- * @example `
719
- new DHTMessage(hash, store)
720
- // store = optional if not set, peernet checks every store
721
- let message = new DHTMessage('hashmvbs124xcfd...', 'transaction')
722
- message = new DHTMessage('hashmvbs124xcfd...', 'block')
723
- `
724
- */
725
- class DHTMessage extends FormatInterface {
726
- /**
727
- *
728
- */
729
- get keys() {
730
- return ['hash', 'store']
731
- }
732
-
733
- constructor(data) {
734
- const name = 'peernet-dht';
735
- super(data, protons(proto$9).PeernetDHTMessage, {name});
736
- }
737
- }
738
-
739
- var proto$8 = `
740
- // PeernetDHTMessageResponse
741
- message PeernetDHTMessageResponse {
742
- required string hash = 1;
743
- required bool has = 2;
744
- }
745
- `;
746
-
747
- class DHTMessageResponse extends FormatInterface {
748
- get keys() {
749
- return ['hash', 'has']
750
- }
751
-
752
- constructor(data) {
753
- const name = 'peernet-dht-response';
754
- super(data, protons(proto$8).PeernetDHTMessageResponse, {name});
755
- }
756
- }
757
-
758
- var proto$7 = `
759
- // PeernetDataMessage
760
- message PeernetDataMessage {
761
- required string hash = 1;
762
- optional string store = 2;
763
- }
764
- `;
765
-
766
- /**
767
- * @extends {CodecFormat}
768
- */
769
- class DataMessage extends FormatInterface {
770
- get keys() {
771
- return ['hash', 'store']
772
- }
773
- /**
774
- * @param {Buffer|String|Object|DataMessage} data - The data needed to create the DataMessage
775
- */
776
- constructor(data) {
777
- super(data, protons(proto$7).PeernetDataMessage, {name: 'peernet-data'});
778
- }
779
- }
780
-
781
- var proto$6 = `
782
- // PsMessage
783
- message PsMessage {
784
- required bytes data = 1;
785
- required bytes topic = 2;
786
- }`;
787
-
788
- class PsMessage extends FormatInterface {
789
- get keys() {
790
- return ['data', 'topic']
791
- }
792
-
793
- constructor(buffer) {
794
- const name = 'peernet-ps';
795
- super(buffer, protons(proto$6).PsMessage, {name});
796
- }
797
- }
798
-
799
- var proto$5 = `
800
- // PeernetPeerMessage
801
- message PeernetPeerMessage {
802
- required string id = 1;
803
- }
804
- `;
805
-
806
- class PeerMessage extends FormatInterface {
807
- get keys() {
808
- return ['id']
809
- }
810
-
811
- constructor(data) {
812
- const name = 'peernet-peer';
813
- super(data, protons(proto$5).PeernetPeerMessage, {name});
814
- }
815
- }
816
-
817
- var proto$4 = `
818
- // PeernetRequestMessage
819
- message PeernetRequestMessage {
820
- required string request = 1;
821
- }
822
- `;
823
-
824
- class RequestMessage extends FormatInterface {
825
- get keys() {
826
- return ['request']
827
- }
828
-
829
- constructor(data) {
830
- const name = 'peernet-request';
831
- super(data, protons(proto$4).PeernetRequestMessage, {name});
832
- }
833
- }
834
-
835
- var proto$3 = `
836
- // PeernetResponseMessage
837
- message PeernetResponseMessage {
838
- required bytes response = 1;
839
- }
840
- `;
841
-
842
- class ResponseMessage extends FormatInterface {
843
- get keys() {
844
- return ['response']
845
- }
846
-
847
- constructor(data) {
848
- const name = 'peernet-response';
849
- super(data, protons(proto$3).PeernetResponseMessage, {name});
850
- }
851
- }
852
-
853
- var proto$2 = `
854
- // PeernetPeerMessageResponse
855
- message PeernetPeerMessageResponse {
856
- required string id = 1;
857
- }
858
- `;
859
-
860
- class PeerMessageResponse extends FormatInterface {
861
- get keys() {
862
- return ['id']
863
- }
864
-
865
- constructor(data) {
866
- const name = 'peernet-peer-response';
867
- super(data, protons(proto$2).PeernetPeerMessageResponse, {name});
868
- }
869
- }
870
-
871
- var proto$1 = `
872
- // PeernetDataMessageResponse
873
- message PeernetDataMessageResponse {
874
- required string hash = 1;
875
- required bytes data = 2;
876
- }
877
- `;
878
-
879
- class DataMessageResponse extends FormatInterface {
880
- get keys() {
881
- return ['hash', 'data']
882
- }
883
-
884
- constructor(data) {
885
- const name = 'peernet-data-response';
886
- super(data, protons(proto$1).PeernetDataMessageResponse, {name});
887
- }
888
- }
889
-
890
- var proto = `
891
- message ChatMessage {
892
- required string value = 1;
893
- required string author = 2;
894
- required uint64 timestamp = 3;
895
- repeated string files = 4;
896
- }`;
897
-
898
- class ChatMessage extends FormatInterface {
899
- get keys() {
900
- return ['author', 'value', 'timestamp', 'files']
901
- }
902
-
903
- constructor(buffer) {
904
- const name = 'chat-message';
905
- super(buffer, protons(proto).ChatMessage, {name});
906
- }
907
- }
2
+ import { Codec, CodecHash, codecs } from '@leofcoin/codec-format-interface';
3
+ import MultiWallet from '@leofcoin/multi-wallet';
908
4
 
909
5
  const protoFor = (data) => {
910
6
  if (!Buffer.isBuffer(data)) data = Buffer.from(data);
@@ -981,12 +77,12 @@ class PeerDiscovery {
981
77
  async discover(peer) {
982
78
  let id = this._getPeerId(peer.id);
983
79
  if (id) return id
984
- const data = new peernet.protos['peernet-peer']({id: this.id});
80
+ const data = await new peernet.protos['peernet-peer']({id: this.id});
985
81
  const node = await peernet.prepareMessage(peer.id, data.encoded);
986
82
 
987
83
  let response = await peer.request(node.encoded);
988
- response = protoFor(response);
989
- response = new peernet.protos['peernet-peer-response'](response.decoded.data);
84
+ response = await protoFor(response);
85
+ response = await new peernet.protos['peernet-peer-response'](response.decoded.data);
990
86
 
991
87
  id = response.decoded.id;
992
88
  if (id === this.id) return;
@@ -1017,7 +113,7 @@ class PeerDiscovery {
1017
113
  peernet.peerMap.set(from, connections);
1018
114
  }
1019
115
  }
1020
- const data = new peernet.protos['peernet-peer-response']({id: this.id});
116
+ const data = await new peernet.protos['peernet-peer-response']({id: this.id});
1021
117
  const node = await peernet.prepareMessage(from, data.encoded);
1022
118
 
1023
119
  peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
@@ -1157,527 +253,6 @@ class DhtEarth {
1157
253
  }
1158
254
  }
1159
255
 
1160
- /**
1161
- * @params {String} network
1162
- * @return {object} { identity, accounts, config }
1163
- */
1164
- var generateAccount = async network => {
1165
- let wallet = new MultiWallet$1(network);
1166
- /**
1167
- * @type {string}
1168
- */
1169
- const mnemonic = await wallet.generate();
1170
-
1171
- wallet = new MultiWallet$1(network);
1172
- await wallet.recover(mnemonic, network);
1173
- /**
1174
- * @type {object}
1175
- */
1176
- const account = wallet.account(0);
1177
- /**
1178
- * @type {object}
1179
- */
1180
- const external = account.external(0);
1181
- const internal = account.internal(0);
1182
-
1183
- return {
1184
- identity: {
1185
- mnemonic,
1186
- // multiWIF: wallet.export(),
1187
- publicKey: external.publicKey,
1188
- privateKey: external.privateKey,
1189
- walletId: external.id
1190
- },
1191
- accounts: [['main account', external.address, internal.address]]
1192
- // config: {
1193
- // }
1194
- }
1195
- };
1196
-
1197
- var testnets = {
1198
- 'leofcoin:olivia': {
1199
- messagePrefix: '\u0019Leofcoin Signed Message:',
1200
- pubKeyHash: 0x73, // o
1201
- scriptHash: 0x76, // p
1202
- multiTxHash: 0x8b4125, // omtx
1203
- payments: {
1204
- version: 0,
1205
- unspent: 0x1fa443d7 // ounsp
1206
- },
1207
- wif: 0x7D, // s
1208
- multiCodec: 0x7c4,
1209
- bip32: { public: 0x13BBF2D5, private: 0x13BBCBC5 }
1210
- },
1211
- 'bitcoin:testnet': {
1212
- messagePrefix: '\x18Bitcoin Signed Message:\n',
1213
- bech32: 'tb',
1214
- pubKeyHash: 0x6f,
1215
- scriptHash: 0xc4,
1216
- wif: 0xef,
1217
- bip32: {
1218
- public: 0x043587cf,
1219
- private: 0x04358394
1220
- }
1221
- }
1222
-
1223
- };
1224
-
1225
- // https://en.bitcoin.it/wiki/List_of_address_prefixes
1226
- /**
1227
- * Main network
1228
- * @return {messagePrefix, pubKeyHash, scriptHash, wif, bip32}
1229
- */
1230
- const leofcoin = {
1231
- messagePrefix: '\u0019Leofcoin Signed Message:',
1232
- pubKeyHash: 0x30, // L
1233
- scriptHash: 0x37, // P
1234
- multiTxHash: 0x3adeed, // Lmtx
1235
- payments: {
1236
- version: 0,
1237
- unspent: 0x0d6e0327 // Lunsp
1238
- },
1239
- coin_type: 640,
1240
- wif: 0x3F, // S
1241
- multiCodec: 0x3c4,
1242
- bip32: { public: 0x13BBF2D4, private: 0x13BBCBC4 },
1243
- testnet: testnets['leofcoin:olivia']
1244
- };
1245
-
1246
- const bitcoin = {
1247
- messagePrefix: '\x18Bitcoin Signed Message:\n',
1248
- bech32: 'bc',
1249
- pubKeyHash: 0x00,
1250
- multiCodec: 0x00,
1251
- scriptHash: 0x05,
1252
- wif: 0x80,
1253
- coin_type: 0,
1254
- bip32: {
1255
- public: 0x0488b21e, private: 0x0488ade4
1256
- },
1257
- testnet: testnets['bitcoin:testnet']
1258
- };
1259
-
1260
- const litecoin = {
1261
- messagePrefix: '\x19Litecoin Signed Message:\n',
1262
- pubKeyHash: 0x30,
1263
- scriptHash: 0x32,
1264
- wif: 0xb0,
1265
- bip32: {
1266
- public: 0x019da462,
1267
- private: 0x019d9cfe
1268
- }
1269
- };
1270
-
1271
- const ethereum = {
1272
- messagePrefix: '\x19Ethereum Signed Message:\n',
1273
- pubKeyHash: 0x30,
1274
- scriptHash: 0x32,
1275
- bip32: {
1276
- private: 0x0488ADE4, public: 0x0488B21E
1277
- },
1278
- coin_type: 60,
1279
- wif: 0x45,//E
1280
- multiCodec: 0x3c5
1281
- };
1282
-
1283
- /**
1284
- * Our & supported networks
1285
- * @return {leofcoin, olivia}
1286
- */
1287
- var networks = {
1288
- leofcoin,
1289
- bitcoin,
1290
- litecoin,
1291
- ethereum
1292
- };
1293
-
1294
- const fromNetworkString = network => {
1295
- const parts = network.split(':');
1296
- network = networks[parts[0]];
1297
- if (parts[1]) {
1298
- if (network[parts[1]]) network = network[parts[1]];
1299
-
1300
- network.coin_type = 1;
1301
- }
1302
- return network;
1303
- };
1304
-
1305
- // import { createHash } from 'crypto'
1306
- // import { createHash as _createHash } from './hash'
1307
-
1308
- const { encode: encode$1, decode: decode$1 } = bs58check__default;
1309
- class HDWallet {
1310
-
1311
- get chainCodeBuffer() {
1312
- return this.ifNotLocked(() => this.hdnode.chainCode)
1313
- }
1314
-
1315
- get chainCode() {
1316
- return this.ifNotLocked(() => this.chainCodeBuffer.toString('hex'))
1317
- }
1318
-
1319
- get privateKeyBuffer() {
1320
- return this.ifNotLocked(() => this.hdnode.privateKey)
1321
- }
1322
-
1323
- get privateKey() {
1324
- return this.ifNotLocked(() => this.privateKeyBuffer.toString('hex'))
1325
- }
1326
-
1327
- get publicKeyBuffer() {
1328
- return this.ifNotLocked(() => this.hdnode.publicKey)
1329
- }
1330
-
1331
- get publicKey() {
1332
- return this.ifNotLocked(() => this.publicKeyBuffer.toString('hex'))
1333
- }
1334
-
1335
- get ethereumAddress() {
1336
- const buffer = ecc.pointFromScalar(this.hdnode.__D, false);
1337
- let hash = createKeccakHash('keccak256').update(buffer.slice(1)).digest();
1338
- return `0x${hash.slice(-20).toString('hex')}`
1339
- }
1340
-
1341
- // async bitcoinAddress() {
1342
- // const chainCode = this.privateKeyBuffer
1343
- //
1344
- // const node = bip32.fromPrivateKey(this.privateKeyBuffer, chainCode, networks['bitcoin'])
1345
- // let buffer = await _createHash(node.publicKey, 'SHA-256')
1346
- // buffer = createHash('ripemd160').update(buffer).digest()
1347
- // // buffer = Buffer.from(`0x00${buffer.toString('hex')}`, 'hex')
1348
- // // buffer = createHash('sha256').update(buffer).digest()
1349
- // // const mainHash = buffer
1350
- // // buffer = createHash('sha256').update(buffer).digest()
1351
- // // const checksum = buffer.toString('hex').substring(0, 8)
1352
- // // return base58.encode(Buffer.concat([mainHash, Buffer.from(checksum, 'hex')]))
1353
- // const payload = Buffer.allocUnsafe(21)
1354
- // payload.writeUInt8(networks['bitcoin'].pubKeyHash, 0)
1355
- // buffer.copy(payload, 1)
1356
- //
1357
- // return encode(payload)
1358
- // }
1359
-
1360
- get leofcoinAddress() {
1361
- return encode$1(this.neutered.publicKeyBuffer)
1362
- }
1363
-
1364
- get address() {
1365
- return this.getAddressForCoin()
1366
- }
1367
-
1368
- getAddressForCoin(coin_type) {
1369
- if (!coin_type) coin_type = this.hdnode.network.coin_type;
1370
- if (coin_type === 1) {
1371
- if (this.networkName?.split(':')[0] === 'ethereum') coin_type = 60;
1372
- if (this.networkName?.split(':')[0] === 'leofcoin') coin_type = 640;
1373
- }
1374
- // if (coin_type === 0) return this.bitcoinAddress
1375
- if (coin_type === 60) return this.ethereumAddress
1376
- if (coin_type === 640) return this.leofcoinAddress
1377
- }
1378
-
1379
- get accountAddress() {
1380
- return this.ifNotLocked(() => encode$1(this.hdnode.publicKeyBuffer))
1381
- }
1382
-
1383
- get isTestnet() {
1384
- if (typeof network === 'string')
1385
- this.hdnode.network = fromNetworkString(network);
1386
-
1387
- return Boolean(this.hdnode.network.coin_type === 1)
1388
- }
1389
-
1390
- constructor(network, hdnode) {
1391
- if (typeof network === 'string') {
1392
- this.networkName = network;
1393
- this.network = fromNetworkString(network);
1394
- } else if (typeof network === 'object')
1395
- this.network = network;
1396
-
1397
- if (hdnode) this.defineHDNode(hdnode);
1398
- }
1399
-
1400
- ifNotLocked(fn, params) {
1401
- if (!this.locked) return fn(params);
1402
- return null
1403
- }
1404
-
1405
- defineHDNode(value) {
1406
- Object.defineProperty(this, 'hdnode', {
1407
- configurable: false,
1408
- writable: false,
1409
- value: value
1410
- });
1411
- }
1412
-
1413
- validateNetwork(network) {
1414
- if (!network && !this.network) return console.error(`expected network to be defined`);
1415
- if (!network && this.network) network = this.network;
1416
- if (typeof network === 'string') network = fromNetworkString(network);
1417
- if (typeof network !== 'object') return console.error('network not found');
1418
- return network;
1419
- }
1420
-
1421
- async generate(password, network) {
1422
- network = this.validateNetwork(network);
1423
- const mnemonic = new Mnemonic().generate();
1424
- const seed = new Mnemonic().seedFromMnemonic(mnemonic, password);
1425
- this.defineHDNode(bip32.fromSeed(seed, network));
1426
- return mnemonic;
1427
- }
1428
-
1429
- /**
1430
- * recover using mnemonic (recovery word list)
1431
- */
1432
- async recover(mnemonic, password, network) {
1433
- network = this.validateNetwork(network, password);
1434
- const seed = new Mnemonic().seedFromMnemonic(mnemonic, password);
1435
- this.defineHDNode(bip32.fromSeed(seed, network));
1436
- }
1437
-
1438
- load(base58, network) {
1439
- network = this.validateNetwork(network);
1440
- this.defineHDNode(bip32.fromBase58(base58, network));
1441
- }
1442
-
1443
- save() {
1444
- return this.hdnode.toBase58();
1445
- }
1446
-
1447
- fromAddress(address, chainCode, network) {
1448
- network = this.validateNetwork(network);
1449
- // if (network.coin_type === 60) {
1450
- // address = Buffer.from(address, 'hex')
1451
- // } else {
1452
- address = decode$1(address);
1453
- // }
1454
-
1455
- if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = address.slice(1);
1456
- this.defineHDNode(bip32.fromPublicKey(address, chainCode, network));
1457
- }
1458
-
1459
- fromPublicKey(hex, chainCode, network) {
1460
- network = this.validateNetwork(network);
1461
- if (!Buffer.isBuffer(hex)) hex = Buffer.from(hex, 'hex');
1462
- if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = hex.slice(1);
1463
- this.defineHDNode(bip32.fromPublicKey(hex, chainCode, network));
1464
- }
1465
- }
1466
-
1467
- const { subtle } = crypto;
1468
-
1469
- const generateAesKey = async (length = 256) => {
1470
- const key = await subtle.generateKey({
1471
- name: 'AES-CBC',
1472
- length
1473
- }, true, ['encrypt', 'decrypt']);
1474
-
1475
- return key;
1476
- };
1477
-
1478
- const importAesKey = async (exported, format = 'raw', length = 256) => {
1479
- return await subtle.importKey(format, exported, {
1480
- name: 'AES-CBC',
1481
- length
1482
- }, true, ['encrypt', 'decrypt'])
1483
- };
1484
-
1485
- const exportAesKey = async (key, format = 'raw') => {
1486
- return await subtle.exportKey(format, key)
1487
- };
1488
-
1489
- const encryptAes = async (uint8Array, key, iv) => subtle.encrypt({
1490
- name: 'AES-CBC',
1491
- iv,
1492
- }, key, uint8Array);
1493
-
1494
- const uint8ArrayToHex = uint8Array =>
1495
- [...uint8Array].map(x => x.toString(16).padStart(2, '0')).join('');
1496
-
1497
- const arrayBufferToHex = arrayBuffer =>
1498
- uint8ArrayToHex(new Uint8Array(arrayBuffer));
1499
-
1500
- const hexToUint8Array = hex =>
1501
- new Uint8Array(hex.match(/[\da-f]{2}/gi).map(x => parseInt(x, 16)));
1502
-
1503
- const encrypt = async string => {
1504
- const ec = new TextEncoder();
1505
- const key = await generateAesKey();
1506
- const iv = await randombytes(16);
1507
-
1508
- const ciphertext = await encryptAes(ec.encode(string), key, iv);
1509
- const exported = await exportAesKey(key);
1510
-
1511
- return {
1512
- key: arrayBufferToHex(exported),
1513
- iv: iv.toString('hex'),
1514
- cipher: arrayBufferToHex(ciphertext)
1515
- }
1516
- };
1517
-
1518
- const decrypt = async (cipher, key, iv) => {
1519
- if (!key.type) key = await importAesKey(hexToUint8Array(key));
1520
- cipher = new Uint8Array(hexToUint8Array(cipher));
1521
- iv = new Uint8Array(hexToUint8Array(iv));
1522
-
1523
- const dec = new TextDecoder();
1524
- const plaintext = await subtle.decrypt({
1525
- name: 'AES-CBC',
1526
- iv,
1527
- }, key, cipher);
1528
-
1529
- return dec.decode(plaintext);
1530
- };
1531
-
1532
- const { encode, decode } = bs58check;
1533
-
1534
- // TODO: multihash addresses
1535
- class HDAccount {
1536
- /**
1537
- * @param {number} depth - acount depth
1538
- */
1539
- constructor(node, depth = 0) {
1540
- this.node = node;
1541
- this.depth = depth;
1542
- this._prefix = `m/44'/${node.network.coin_type}'/${depth}'/`;
1543
- }
1544
-
1545
- /**
1546
- * @param {number} index - address index
1547
- */
1548
- internal(index = 0) {
1549
- return this.node.derivePath(`${this._prefix}1/${index}`)
1550
- }
1551
-
1552
- /**
1553
- * @param {number} index - address index
1554
- */
1555
- external(index = 0) {
1556
- return this.node.derivePath(`${this._prefix}0/${index}`)
1557
- }
1558
- }
1559
-
1560
- class MultiWallet extends HDWallet {
1561
- constructor(network, hdnode) {
1562
- super(network, hdnode);
1563
- this.multiCodec = this.network.multiCodec;
1564
- this.version = 0x00;
1565
- }
1566
-
1567
- get id() {
1568
- const buffer = Buffer.concat([
1569
- Buffer.from(varint.encode(this.multiCodec)),
1570
- Buffer.from(this.account(0).node.neutered.publicKey, 'hex')
1571
- ]);
1572
- return encode(buffer)
1573
- }
1574
-
1575
- get multiWIF() {
1576
- return this.ifNotLocked(() => this.encode())
1577
- }
1578
-
1579
- get neutered() {
1580
- const neutered = this.ifNotLocked(() => new MultiWallet(this.networkName, this.hdnode.neutered()));
1581
- if (neutered) this._neutered = neutered;
1582
- return this._neutered
1583
- }
1584
-
1585
- fromId(id) {
1586
- let buffer = decode(id);
1587
- varint.decode(buffer);
1588
- buffer = buffer.slice(varint.decode.bytes);
1589
- this.fromPublicKey(buffer, null, this.networkName);
1590
- }
1591
-
1592
- async lock(multiWIF) {
1593
- if (!multiWIF) multiWIF = this.multiWIF;
1594
- this.encrypted = await encrypt(multiWIF.toString('hex'));
1595
- this.locked = true;
1596
- return this.encrypted
1597
- }
1598
-
1599
- async unlock({key, iv, cipher}) {
1600
- const decrypted = await decrypt(cipher, key, iv);
1601
- this.import(decrypted);
1602
- this.locked = false;
1603
- }
1604
-
1605
- export() {
1606
- return this.encode();
1607
- }
1608
-
1609
- /**
1610
- * encodes the multiWIF and loads wallet from bs58
1611
- *
1612
- * @param {multiWIF} multiWIF - note a multiWIF is not the same as a wif
1613
- */
1614
- import(multiWIF) {
1615
- const { bs58, version, multiCodec } = this.decode(multiWIF);
1616
- this.network = Object.values(networks).reduce((p, c) => {
1617
- if (c.multiCodec===multiCodec) return c
1618
- else if (c.testnet && c.testnet.multiCodec === multiCodec) return c.testnet
1619
- else return p
1620
- }, networks['leofcoin']);
1621
- this.load(bs58, this.networkName);
1622
- }
1623
-
1624
- /**
1625
- * @return base58Check encoded string
1626
- */
1627
- encode() {
1628
- const buffer = Buffer.concat([
1629
- Buffer.from(varint.encode(this.version)),
1630
- Buffer.from(varint.encode(this.multiCodec)),
1631
- decode(this.save())
1632
- ]);
1633
- return encode(buffer);
1634
- }
1635
-
1636
- decode(bs58) {
1637
- let buffer = decode(bs58);
1638
- const version = varint.decode(buffer);
1639
- buffer = buffer.slice(varint.decode.bytes);
1640
- const multiCodec = varint.decode(buffer);
1641
- buffer = buffer.slice(varint.decode.bytes);
1642
- bs58 = encode(buffer);
1643
- if (version !== this.version) throw TypeError('Invalid version');
1644
- if (this.multiCodec !== multiCodec) throw TypeError('Invalid multiCodec');
1645
- return { version, multiCodec, bs58 };
1646
- }
1647
-
1648
- sign(hash) {
1649
- return new MultiSignature(this.version, this.network.multiCodec)
1650
- .sign(hash, this.privateKeyBuffer);
1651
-
1652
- }
1653
-
1654
- verify(multiSignature, hash) {
1655
- return new MultiSignature(this.version, this.network.multiCodec)
1656
- .verify(multiSignature, hash, this.publicKeyBuffer)
1657
- }
1658
-
1659
- /**
1660
- * @param {number} account - account to return chain for
1661
- * @return { internal(addressIndex), external(addressIndex) }
1662
- */
1663
- account(index) {
1664
- return new HDAccount(new MultiWallet(this.networkName, this.hdnode), index);
1665
- }
1666
-
1667
- /**
1668
- * m / purpose' / coin_type' / account' / change / aadress_index
1669
- *
1670
- * see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
1671
- */
1672
- derivePath(path) {
1673
- return new MultiWallet(this.networkName, this.hdnode.derivePath(path))
1674
- }
1675
-
1676
- derive(index) {
1677
- return new MultiWallet(this.networkName, this.hdnode.derive(index));
1678
- }
1679
- }
1680
-
1681
256
  class MessageHandler {
1682
257
  constructor(network) {
1683
258
  this.network = network;
@@ -1716,7 +291,7 @@ class MessageHandler {
1716
291
  data,
1717
292
  };
1718
293
  const signature = await this.hashAndSignMessage(message);
1719
- const node = new PeernetMessage({
294
+ const node = await new globalThis.peernet.protos['peernet-message']({
1720
295
  ...message,
1721
296
  signature,
1722
297
  });
@@ -1730,8 +305,8 @@ const dataHandler = async message => {
1730
305
 
1731
306
  const {data, id} = message;
1732
307
 
1733
- message = protoFor(data);
1734
- const proto = protoFor(message.decoded.data);
308
+ message = await protoFor(data);
309
+ const proto = await protoFor(message.decoded.data);
1735
310
  const from = message.decoded.from;
1736
311
 
1737
312
  peernet._protoHandler({id, proto}, peernet.client.connections[from], from);
@@ -1797,6 +372,14 @@ class Peernet {
1797
372
  return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
1798
373
  }
1799
374
 
375
+ get protos() {
376
+ return globalThis.peernet.protos
377
+ }
378
+
379
+ get codecs() {
380
+ return codecs
381
+ }
382
+
1800
383
  addProto(name, proto) {
1801
384
  if (!this.protos[name]) this.protos[name] = proto;
1802
385
  }
@@ -1806,6 +389,10 @@ class Peernet {
1806
389
  }
1807
390
 
1808
391
  async addStore(name, prefix, root, isPrivate = true) {
392
+ if (!globalThis.LeofcoinStorage) {
393
+ const importee = await import(/* webpackChunkName: "storage" */ '@leofcoin/storage');
394
+ globalThis.LeofcoinStorage = importee.default;
395
+ }
1809
396
  if (name === 'block' || name === 'transaction' || name === 'chain' ||
1810
397
  name === 'data' || name === 'message') isPrivate = false;
1811
398
 
@@ -1813,7 +400,7 @@ class Peernet {
1813
400
  if (this.hasDaemon) {
1814
401
  Storage = LeofcoinStorageClient;
1815
402
  } else {
1816
- Storage = globalThis.LeofcoinStorage?.default ? globalThis.LeofcoinStorage.default : LeofcoinStorage;
403
+ Storage = LeofcoinStorage;
1817
404
  }
1818
405
  globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
1819
406
  await new Storage(name, root);
@@ -1878,6 +465,20 @@ class Peernet {
1878
465
  this.storePrefix = options.storePrefix;
1879
466
  this.root = options.root;
1880
467
 
468
+ const {
469
+ RequestMessage,
470
+ ResponseMessage,
471
+ PeerMessage,
472
+ PeerMessageResponse,
473
+ PeernetMessage,
474
+ DHTMessage,
475
+ DHTMessageResponse,
476
+ DataMessage,
477
+ DataMessageResponse,
478
+ PsMessage,
479
+ ChatMessage
480
+ } = await import(/* webpackChunkName: "messages" */ './messages-421f88db.js');
481
+
1881
482
  /**
1882
483
  * proto Object containing protos
1883
484
  * @type {Object}
@@ -1887,6 +488,7 @@ class Peernet {
1887
488
  * @property {DataMessage} protos[peernet-data] messageNode
1888
489
  * @property {DataMessageResponse} protos[peernet-data-response] messageNode
1889
490
  */
491
+
1890
492
  globalThis.peernet.protos = {
1891
493
  'peernet-request': RequestMessage,
1892
494
  'peernet-response': ResponseMessage,
@@ -1901,16 +503,11 @@ class Peernet {
1901
503
  'chat-message': ChatMessage,
1902
504
  };
1903
505
 
1904
- this.protos = globalThis.peernet.protos;
1905
- this.codecs = codecs;
1906
-
1907
506
  this._messageHandler = new MessageHandler(this.network);
1908
507
 
1909
508
  const {daemon, environment} = await target();
1910
509
  this.hasDaemon = daemon;
1911
510
 
1912
-
1913
-
1914
511
  for (const store of this.defaultStores) {
1915
512
  await this.addStore(store, options.storePrefix, options.root);
1916
513
  }
@@ -1930,6 +527,9 @@ class Peernet {
1930
527
  }
1931
528
  } catch (e) {
1932
529
  if (e.code === 'ERR_NOT_FOUND') {
530
+
531
+ const importee = await import(/* webpackChunkName: "generate-account" */ '@leofcoin/generate-account');
532
+ const generateAccount = importee.default;
1933
533
  const {identity, accounts, config} = await generateAccount(this.network);
1934
534
  walletStore.put('version', new TextEncoder().encode(1));
1935
535
  walletStore.put('accounts', new TextEncoder().encode(JSON.stringify(accounts)));
@@ -1962,11 +562,13 @@ class Peernet {
1962
562
  */
1963
563
  pubsub.subscribe('peer:data', dataHandler);
1964
564
 
565
+
566
+ const importee = await import(/* webpackChunkName: "peernet-swarm" */ '@leofcoin/peernet-swarm');
1965
567
  /**
1966
568
  * @access public
1967
569
  * @type {PeernetClient}
1968
570
  */
1969
- this.client = new Client(this.id);
571
+ this.client = new importee.default(this.id);
1970
572
  if (globalThis.onbeforeunload) {
1971
573
  globalThis.addEventListener('beforeunload', async () => this.client.close());
1972
574
  }
@@ -2006,7 +608,7 @@ class Peernet {
2006
608
  if (store.private) has = false;
2007
609
  else has = await store.has(hash);
2008
610
  }
2009
- const data = new DHTMessageResponse({hash, has});
611
+ const data = await new this.protos['peernet-dht-response']({hash, has});
2010
612
  const node = await this.prepareMessage(from, data.encoded);
2011
613
 
2012
614
  this.sendMessage(peer, id, node.encoded);
@@ -2022,7 +624,7 @@ class Peernet {
2022
624
  data = await store.get(hash);
2023
625
 
2024
626
  if (data) {
2025
- data = new DataMessageResponse({hash, data});
627
+ data = await new this.protos['peernet-data-response']({hash, data});
2026
628
 
2027
629
  const node = await this.prepareMessage(from, data.encoded);
2028
630
  this.sendMessage(peer, id, node.encoded);
@@ -2049,16 +651,16 @@ class Peernet {
2049
651
  */
2050
652
  async walk(hash) {
2051
653
  if (!hash) throw new Error('hash expected, received undefined')
2052
- const data = new DHTMessage({hash});
654
+ const data = await new this.protos['peernet-dht']({hash});
2053
655
  this.client.id;
2054
656
  const walk = async peer => {
2055
657
  const node = await this.prepareMessage(peer.peerId, data.encoded);
2056
658
  let result = await peer.request(node.encoded);
2057
659
  result = new Uint8Array(Object.values(result));
2058
- let proto = protoFor(result);
660
+ let proto = await protoFor(result);
2059
661
  if (proto.name !== 'peernet-message') throw encapsulatedError()
2060
662
  const from = proto.decoded.from;
2061
- proto = protoFor(proto.decoded.data);
663
+ proto = await protoFor(proto.decoded.data);
2062
664
  if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
2063
665
 
2064
666
  // TODO: give ip and port (just used for location)
@@ -2157,7 +759,7 @@ class Peernet {
2157
759
  if (peer.peerId === id) return peer
2158
760
  });
2159
761
 
2160
- let data = new DataMessage({hash, store: store?.name ? store?.name : store});
762
+ let data = await new this.protos['peernet-data']({hash, store: store?.name ? store?.name : store});
2161
763
 
2162
764
  const node = await this.prepareMessage(id, data.encoded);
2163
765
  if (closest[0]) data = await closest[0].request(node.encoded);
@@ -2168,8 +770,8 @@ class Peernet {
2168
770
  if (closest[0]) data = await closest[0].request(node.encoded);
2169
771
  }
2170
772
  data = new Uint8Array(Object.values(data));
2171
- let proto = protoFor(data);
2172
- proto = protoFor(proto.decoded.data);
773
+ let proto = await protoFor(data);
774
+ proto = await protoFor(proto.decoded.data);
2173
775
  // TODO: store data automaticly or not
2174
776
  return proto.decoded.data
2175
777
 
@@ -2302,7 +904,7 @@ class Peernet {
2302
904
  if (topic instanceof Uint8Array === false) topic = new TextEncoder().encode(topic);
2303
905
  if (data instanceof Uint8Array === false) data = new TextEncoder().encode(JSON.stringify(data));
2304
906
  const id = Math.random().toString(36).slice(-12);
2305
- data = new PsMessage({data, topic});
907
+ data = await new this.protos['peernet-ps']({data, topic});
2306
908
  for (const peer of this.connections) {
2307
909
  if (peer.peerId !== this.peerId) {
2308
910
  const node = await this.prepareMessage(peer.peerId, data.encoded);
@@ -2313,7 +915,7 @@ class Peernet {
2313
915
  }
2314
916
 
2315
917
  createHash(data, name) {
2316
- return new CodecHash(data, {name})
918
+ return new CodeHash(data, {name})
2317
919
  }
2318
920
 
2319
921
  /**