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