@leofcoin/chain 1.7.65 → 1.7.67

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.
@@ -0,0 +1,638 @@
1
+ import { L as LittlePubSub } from './node-browser-DewO13hB.js';
2
+ import './index-CM4QYC3g.js';
3
+
4
+ class Api {
5
+ _pubsub;
6
+ constructor(_pubsub) {
7
+ this._pubsub = _pubsub;
8
+ }
9
+ subscribe(topic, cb) {
10
+ this._pubsub.subscribe(topic, cb);
11
+ }
12
+ unsubscribe(topic, cb) {
13
+ this._pubsub.unsubscribe(topic, cb);
14
+ }
15
+ publish(topic, value) {
16
+ this._pubsub.publish(topic, value);
17
+ }
18
+ subscribers() {
19
+ this._pubsub.subscribers;
20
+ }
21
+ connectionState(state) {
22
+ switch (state) {
23
+ case 0:
24
+ return 'connecting';
25
+ case 1:
26
+ return 'open';
27
+ case 2:
28
+ return 'closing';
29
+ case 3:
30
+ return 'closed';
31
+ }
32
+ }
33
+ /**
34
+ * @param {string} type
35
+ * @param {string} name
36
+ * @param {object} params
37
+ */
38
+ request(client, request) {
39
+ return new Promise((resolve, reject) => {
40
+ const state = this.connectionState(client.readyState);
41
+ if (state !== 'open')
42
+ return reject(`coudn't send request to ${client.id}, no open connection found.`);
43
+ request.id = Math.random().toString(36).slice(-12);
44
+ const handler = result => {
45
+ if (result && result.error)
46
+ return reject(result.error);
47
+ resolve({ result, id: request.id, handler });
48
+ this.unsubscribe(request.id, handler);
49
+ };
50
+ this.subscribe(request.id, handler);
51
+ this.send(client, request);
52
+ });
53
+ }
54
+ async send(client, request) {
55
+ return client.send(JSON.stringify(request));
56
+ }
57
+ pubsub(client) {
58
+ return {
59
+ publish: (topic = 'pubsub', value) => {
60
+ return this.send(client, { url: 'pubsub', params: { topic, value } });
61
+ },
62
+ subscribe: (topic = 'pubsub', cb) => {
63
+ this.subscribe(topic, cb);
64
+ return this.send(client, { url: 'pubsub', params: { topic, subscribe: true } });
65
+ },
66
+ unsubscribe: (topic = 'pubsub', cb) => {
67
+ this.unsubscribe(topic, cb);
68
+ return this.send(client, { url: 'pubsub', params: { topic, unsubscribe: true } });
69
+ },
70
+ subscribers: this._pubsub.subscribers
71
+ };
72
+ }
73
+ server(client) {
74
+ return {
75
+ uptime: async () => {
76
+ try {
77
+ const { result, id, handler } = await this.request(client, { url: 'uptime' });
78
+ this.unsubscribe(id, handler);
79
+ return result;
80
+ }
81
+ catch (e) {
82
+ throw e;
83
+ }
84
+ },
85
+ ping: async () => {
86
+ try {
87
+ const now = new Date().getTime();
88
+ const { result, id, handler } = await this.request(client, { url: 'ping' });
89
+ this.unsubscribe(id, handler);
90
+ return (Number(result) - now);
91
+ }
92
+ catch (e) {
93
+ throw e;
94
+ }
95
+ }
96
+ };
97
+ }
98
+ peernet(client) {
99
+ return {
100
+ join: async (params) => {
101
+ try {
102
+ params.join = true;
103
+ const requested = { url: 'peernet', params };
104
+ const { result, id, handler } = await this.request(client, requested);
105
+ this.unsubscribe(id, handler);
106
+ return result;
107
+ }
108
+ catch (e) {
109
+ throw e;
110
+ }
111
+ },
112
+ leave: async (params) => {
113
+ try {
114
+ params.join = false;
115
+ const requested = { url: 'peernet', params };
116
+ const { result, id, handler } = await this.request(client, requested);
117
+ this.unsubscribe(id, handler);
118
+ return result;
119
+ }
120
+ catch (e) {
121
+ throw e;
122
+ }
123
+ }
124
+ };
125
+ }
126
+ }
127
+
128
+ class ClientConnection {
129
+ client;
130
+ api;
131
+ #startTime;
132
+ constructor(client, api) {
133
+ this.#startTime = new Date().getTime();
134
+ this.client = client;
135
+ this.api = api;
136
+ }
137
+ request = async (req) => {
138
+ const { result, id, handler } = await this.api.request(this.client, req);
139
+ globalThis.pubsub.unsubscribe(id, handler);
140
+ return result;
141
+ };
142
+ send = (req) => this.api.send(this.client, req);
143
+ get subscribe() {
144
+ return this.api.subscribe;
145
+ }
146
+ get unsubscribe() {
147
+ return this.api.unsubscribe;
148
+ }
149
+ get subscribers() {
150
+ return this.api.subscribers;
151
+ }
152
+ get publish() {
153
+ return this.api.publish;
154
+ }
155
+ get pubsub() {
156
+ return this.api.pubsub(this.client);
157
+ }
158
+ uptime = () => {
159
+ const now = new Date().getTime();
160
+ return (now - this.#startTime);
161
+ };
162
+ get peernet() {
163
+ return this.api.peernet(this.client);
164
+ }
165
+ get server() {
166
+ return this.api.server(this.client);
167
+ }
168
+ connectionState = () => this.api.connectionState(this.client.readyState);
169
+ close = exit => {
170
+ // client.onclose = message => {
171
+ // if (exit) process.exit()
172
+ // }
173
+ this.client.close();
174
+ };
175
+ }
176
+
177
+ if (!globalThis.PubSub)
178
+ globalThis.PubSub = LittlePubSub;
179
+ if (!globalThis.pubsub)
180
+ globalThis.pubsub = new LittlePubSub(false);
181
+ class SocketRequestClient {
182
+ api;
183
+ clientConnection;
184
+ #tries = 0;
185
+ #retry = false;
186
+ #timeout = 10000;
187
+ #times = 10;
188
+ #options;
189
+ #protocol;
190
+ #url;
191
+ #experimentalWebsocket = false;
192
+ constructor(url, protocol, options) {
193
+ let { retry, timeout, times, experimentalWebsocket } = options || {};
194
+ if (retry !== undefined)
195
+ this.#retry = retry;
196
+ if (timeout !== undefined)
197
+ this.#timeout = timeout;
198
+ if (times !== undefined)
199
+ this.#times = times;
200
+ if (experimentalWebsocket !== undefined)
201
+ this.#experimentalWebsocket;
202
+ this.#url = url;
203
+ this.#protocol = protocol;
204
+ this.#options = options;
205
+ this.api = new Api(globalThis.pubsub);
206
+ }
207
+ init() {
208
+ return new Promise(async (resolve, reject) => {
209
+ const init = async () => {
210
+ // @ts-ignore
211
+ if (!globalThis.WebSocket && !this.#experimentalWebsocket)
212
+ globalThis.WebSocket = (await import('./browser-DQJ6xf_F-D0onvbt2.js').then(function (n) { return n.b; })).default.w3cwebsocket;
213
+ const client = new WebSocket(this.#url, this.#protocol);
214
+ if (this.#experimentalWebsocket) {
215
+ client.addEventListener('error', this.onerror);
216
+ client.addEventListener('message', this.onmessage);
217
+ client.addEventListener('open', () => {
218
+ this.#tries = 0;
219
+ resolve(new ClientConnection(client, this.api));
220
+ });
221
+ client.addEventListener('close', (client.onclose = (message) => {
222
+ this.#tries++;
223
+ if (!this.#retry)
224
+ return reject(this.#options);
225
+ if (this.#tries > this.#times) {
226
+ console.log(`${this.#options.protocol} Client Closed`);
227
+ console.error(`could not connect to - ${this.#url}/`);
228
+ return resolve(new ClientConnection(client, this.api));
229
+ }
230
+ if (message.code === 1006) {
231
+ console.log(`Retrying in ${this.#timeout} ms`);
232
+ setTimeout(() => {
233
+ return init();
234
+ }, this.#timeout);
235
+ }
236
+ }));
237
+ }
238
+ else {
239
+ client.onmessage = this.onmessage;
240
+ client.onerror = this.onerror;
241
+ client.onopen = () => {
242
+ this.#tries = 0;
243
+ resolve(new ClientConnection(client, this.api));
244
+ };
245
+ client.onclose = (message) => {
246
+ this.#tries++;
247
+ if (!this.#retry)
248
+ return reject(this.#options);
249
+ if (this.#tries > this.#times) {
250
+ console.log(`${this.#options.protocol} Client Closed`);
251
+ console.error(`could not connect to - ${this.#url}/`);
252
+ return resolve(new ClientConnection(client, this.api));
253
+ }
254
+ if (message.code === 1006) {
255
+ console.log(`Retrying in ${this.#timeout} ms`);
256
+ setTimeout(() => {
257
+ return init();
258
+ }, this.#timeout);
259
+ }
260
+ };
261
+ }
262
+ };
263
+ return init();
264
+ });
265
+ }
266
+ onerror = (error) => {
267
+ if (globalThis.pubsub.subscribers['error']) {
268
+ globalThis.pubsub.publish('error', error);
269
+ }
270
+ else {
271
+ console.error(error);
272
+ }
273
+ };
274
+ onmessage(message) {
275
+ if (!message.data) {
276
+ console.warn(`message ignored because it contained no data`);
277
+ return;
278
+ }
279
+ const { value, url, status, id } = JSON.parse(message.data.toString());
280
+ const publisher = id ? id : url;
281
+ if (status === 200) {
282
+ globalThis.pubsub.publish(publisher, value);
283
+ }
284
+ else {
285
+ globalThis.pubsub.publish(publisher, { error: value });
286
+ }
287
+ }
288
+ }
289
+
290
+ const MAX_MESSAGE_SIZE = 16000;
291
+ const defaultOptions = {
292
+ networkVersion: 'peach',
293
+ version: 'v1',
294
+ stars: ['wss://star.leofcoin.org'],
295
+ connectEvent: 'peer:connected'
296
+ };
297
+
298
+ const iceServers = [
299
+ {
300
+ urls: 'stun:stun.l.google.com:19302' // Google's public STUN server
301
+ },
302
+ {
303
+ urls: 'stun:openrelay.metered.ca:80'
304
+ },
305
+ {
306
+ urls: 'turn:openrelay.metered.ca:443',
307
+ username: 'openrelayproject',
308
+ credential: 'openrelayproject'
309
+ },
310
+ {
311
+ urls: 'turn:openrelay.metered.ca:443?transport=tcp',
312
+ username: 'openrelayproject',
313
+ credential: 'openrelayproject'
314
+ }
315
+ ];
316
+ const SimplePeer = (await import('./index-DqPlTtAJ-Bczd-x6k.js').then(function (n) { return n.i; })).default;
317
+ class Peer extends SimplePeer {
318
+ peerId;
319
+ channelName;
320
+ version;
321
+ bw = { up: 0, down: 0 };
322
+ get connected() {
323
+ return super.connected;
324
+ }
325
+ constructor(options) {
326
+ const { from, to, initiator, trickle, config, version } = options;
327
+ const channelName = initiator ? `${from}:${to}` : `${to}:${from}`;
328
+ super({
329
+ channelName,
330
+ initiator,
331
+ trickle: trickle || true,
332
+ config: { iceServers, ...config },
333
+ wrtc: globalThis.wrtc
334
+ });
335
+ this.version = String(version);
336
+ this.peerId = to;
337
+ this.channelName = channelName;
338
+ }
339
+ async #chunkit(data, id) {
340
+ this.bw.up = data.length;
341
+ const size = data.length;
342
+ // no needles chunking, keep it simple, if data is smaller then max size just send it
343
+ if (data.length <= MAX_MESSAGE_SIZE) {
344
+ return super.send(JSON.stringify({ chunk: data, id, size: data.length }));
345
+ }
346
+ async function* chunks(data) {
347
+ while (data.length !== 0) {
348
+ const amountToSlice = data.length >= MAX_MESSAGE_SIZE ? MAX_MESSAGE_SIZE : data.length;
349
+ const subArray = data.subarray(0, amountToSlice);
350
+ data = data.subarray(amountToSlice, data.length);
351
+ yield subArray;
352
+ // super.send(JSON.stringify({ chunk: subArray, id, size }))
353
+ }
354
+ }
355
+ // while (data.length !== 0) {
356
+ // const amountToSlice =
357
+ // data.length >= MAX_MESSAGE_SIZE ? MAX_MESSAGE_SIZE : data.length
358
+ // const subArray = data.subarray(0, amountToSlice)
359
+ // data = data.subarray(amountToSlice, data.length)
360
+ // super.send(JSON.stringify({ chunk: subArray, id, size }))
361
+ // }
362
+ for await (const chunk of chunks(data)) {
363
+ super.send(JSON.stringify({ chunk, id, size }));
364
+ }
365
+ }
366
+ /**
367
+ * send to peer
368
+ * @param data ArrayLike
369
+ * @param id custom id to listen to
370
+ */
371
+ send(data, id = crypto.randomUUID()) {
372
+ // send chuncks till ndata support for SCTP is added
373
+ // wraps data
374
+ this.#chunkit(data, id);
375
+ }
376
+ /**
377
+ * send to peer & wait for response
378
+ * @param data ArrayLike
379
+ * @param id custom id to listen to
380
+ */
381
+ request(data, id = crypto.randomUUID()) {
382
+ return new Promise((resolve, reject) => {
383
+ const timeout = setTimeout(() => reject(`request for ${id} timed out`), 30_000);
384
+ const onrequest = ({ data }) => {
385
+ clearTimeout(timeout);
386
+ resolve(data);
387
+ globalThis.pubsub.unsubscribe(id, onrequest);
388
+ };
389
+ globalThis.pubsub.subscribe(id, onrequest);
390
+ this.send(data, id);
391
+ });
392
+ }
393
+ }
394
+
395
+ const debug = globalThis.createDebugger('@netpeer/swarm/client');
396
+ class Client {
397
+ #peerId;
398
+ #connections = {};
399
+ #stars = {};
400
+ #connectEvent = 'peer:connected';
401
+ id;
402
+ networkVersion;
403
+ starsConfig;
404
+ socketClient;
405
+ messageSize = 262144;
406
+ version;
407
+ #messagesToHandle = {};
408
+ get peerId() {
409
+ return this.#peerId;
410
+ }
411
+ get connections() {
412
+ return { ...this.#connections };
413
+ }
414
+ get peers() {
415
+ return Object.entries(this.#connections);
416
+ }
417
+ getPeer(peerId) {
418
+ return this.#connections[peerId];
419
+ }
420
+ /**
421
+ *
422
+ * @param options {object}
423
+ * @param options.peerId {string}
424
+ * @param options.networkVersion {string}
425
+ * @param options.version {string}
426
+ * @param options.stars {string[]}
427
+ * @param options.connectEvent {string} defaults to peer:connected, can be renamed to handle different protocols, like peer:discovered (setup peer props before fireing the connect event)
428
+ */
429
+ constructor(options) {
430
+ const { peerId, networkVersion, version, connectEvent, stars } = {
431
+ ...defaultOptions,
432
+ ...options
433
+ };
434
+ this.#peerId = peerId;
435
+ this.networkVersion = networkVersion;
436
+ this.version = version;
437
+ this.#connectEvent = connectEvent;
438
+ this.starsConfig = stars;
439
+ this._init();
440
+ }
441
+ async _init() {
442
+ // reconnectJob()
443
+ if (!globalThis.RTCPeerConnection)
444
+ globalThis.wrtc = (await import('./browser-pguCHlVu-pguCHlVu.js').then(function (n) { return n.b; })).default;
445
+ for (const star of this.starsConfig) {
446
+ try {
447
+ const client = new SocketRequestClient(star, this.networkVersion);
448
+ this.#stars[star] = await client.init();
449
+ this.setupStarListeners(this.#stars[star]);
450
+ this.#stars[star].send({
451
+ url: 'join',
452
+ params: { version: this.version, peerId: this.peerId }
453
+ });
454
+ }
455
+ catch (e) {
456
+ if (this.starsConfig.indexOf(star) === this.starsConfig.length - 1 &&
457
+ !this.socketClient)
458
+ throw new Error(`No star available to connect`);
459
+ }
460
+ }
461
+ if (globalThis.process?.versions?.node) {
462
+ process.on('SIGINT', async () => {
463
+ process.stdin.resume();
464
+ await this.close();
465
+ process.exit();
466
+ });
467
+ }
468
+ else {
469
+ globalThis.addEventListener('beforeunload', async () => this.close());
470
+ }
471
+ }
472
+ setupStarListeners(star) {
473
+ star.pubsub.subscribe('peer:joined', (id) => this.#peerJoined(id, star));
474
+ star.pubsub.subscribe('peer:left', (id) => this.#peerLeft(id, star));
475
+ star.pubsub.subscribe('star:joined', this.#starJoined);
476
+ star.pubsub.subscribe('star:left', this.#starLeft);
477
+ star.pubsub.subscribe('signal', (message) => this.#inComingSignal(message, star));
478
+ }
479
+ #starJoined = (id) => {
480
+ if (this.#stars[id]) {
481
+ this.#stars[id].close(0);
482
+ delete this.#stars[id];
483
+ }
484
+ console.log(`star ${id} joined`);
485
+ };
486
+ #starLeft = async (id) => {
487
+ if (this.#stars[id]) {
488
+ this.#stars[id].close(0);
489
+ delete this.#stars[id];
490
+ }
491
+ if (Object.keys(this.#stars).length === 0) {
492
+ for (const star of this.starsConfig) {
493
+ try {
494
+ const socketClient = await new SocketRequestClient(star, this.networkVersion).init();
495
+ if (!socketClient?.client?.OPEN)
496
+ return;
497
+ this.#stars[star] = socketClient;
498
+ this.#stars[star].send({
499
+ url: 'join',
500
+ params: { peerId: this.peerId, version: this.version }
501
+ });
502
+ this.setupStarListeners(socketClient);
503
+ }
504
+ catch (e) {
505
+ if (this.starsConfig.indexOf(star) === this.starsConfig.length - 1)
506
+ throw new Error(`No star available to connect`);
507
+ }
508
+ }
509
+ }
510
+ debug(`star ${id} left`);
511
+ };
512
+ #peerLeft = (peer, star) => {
513
+ const id = peer.peerId || peer;
514
+ if (this.#connections[id]) {
515
+ this.#connections[id].destroy();
516
+ delete this.#connections[id];
517
+ }
518
+ debug(`peer ${id} left`);
519
+ };
520
+ #createRTCPeerConnection = (peerId, star, version, initiator = false) => {
521
+ const peer = new Peer({
522
+ initiator: initiator,
523
+ from: this.peerId,
524
+ to: peerId,
525
+ version
526
+ });
527
+ peer.on('signal', (signal) => this.#peerSignal(peer, signal, star, this.version));
528
+ peer.on('connect', () => this.#peerConnect(peer));
529
+ peer.on('close', () => this.#peerClose(peer));
530
+ peer.on('data', (data) => this.#peerData(peer, data));
531
+ peer.on('error', (error) => this.#peerError(peer, error));
532
+ this.#connections[peerId] = peer;
533
+ };
534
+ #peerJoined = async ({ peerId, version }, star) => {
535
+ // check if peer rejoined before the previous connection closed
536
+ if (this.#connections[peerId]) {
537
+ this.#connections[peerId].destroy();
538
+ delete this.#connections[peerId];
539
+ }
540
+ // RTCPeerConnection
541
+ this.#createRTCPeerConnection(peerId, star, version, true);
542
+ debug(`peer ${peerId} joined`);
543
+ };
544
+ #inComingSignal = async ({ from, signal, channelName, version }, star) => {
545
+ if (version !== this.version) {
546
+ console.warn(`${from} joined using the wrong version.\nexpected: ${this.version} but got:${version}`);
547
+ return;
548
+ }
549
+ let peer = this.#connections[from];
550
+ if (!peer) {
551
+ this.#createRTCPeerConnection(from, star, version);
552
+ peer = this.#connections[from];
553
+ }
554
+ if (String(peer.channelName) !== String(channelName))
555
+ console.warn(`channelNames don't match: got ${peer.channelName}, expected: ${channelName}`);
556
+ peer.signal(signal);
557
+ };
558
+ #peerSignal = (peer, signal, star, version) => {
559
+ let client = this.#stars[star];
560
+ if (!client)
561
+ client = this.#stars[Object.keys(this.#stars)[0]];
562
+ client.send({
563
+ url: 'signal',
564
+ params: {
565
+ from: this.peerId,
566
+ to: peer.peerId,
567
+ channelName: peer.channelName,
568
+ version,
569
+ signal
570
+ }
571
+ });
572
+ };
573
+ #peerClose = (peer) => {
574
+ if (this.#connections[peer.peerId]) {
575
+ peer.destroy();
576
+ delete this.#connections[peer.peerId];
577
+ }
578
+ debug(`closed ${peer.peerId}'s connection`);
579
+ };
580
+ #peerConnect = (peer) => {
581
+ debug(`${peer.peerId} connected`);
582
+ globalThis.pubsub.publishVerbose(this.#connectEvent, peer.peerId);
583
+ };
584
+ #noticeMessage = (message, id, from, peer) => {
585
+ if (globalThis.pubsub.subscribers[id]) {
586
+ globalThis.pubsub.publish(id, {
587
+ data: new Uint8Array(Object.values(message)),
588
+ id,
589
+ from,
590
+ peer
591
+ });
592
+ }
593
+ else {
594
+ globalThis.pubsub.publish('peer:data', {
595
+ data: new Uint8Array(Object.values(message)),
596
+ id,
597
+ from,
598
+ peer
599
+ });
600
+ }
601
+ };
602
+ #peerData = (peer, data) => {
603
+ const { id, size, chunk } = JSON.parse(new TextDecoder().decode(data));
604
+ peer.bw.down += size;
605
+ if (size <= MAX_MESSAGE_SIZE) {
606
+ this.#noticeMessage(chunk, id, peer.peerId, peer);
607
+ }
608
+ else {
609
+ if (!this.#messagesToHandle[id])
610
+ this.#messagesToHandle[id] = [];
611
+ this.#messagesToHandle[id] = [
612
+ ...this.#messagesToHandle[id],
613
+ ...Object.values(chunk)
614
+ ];
615
+ if (this.#messagesToHandle[id].length === Number(size)) {
616
+ this.#noticeMessage(this.#messagesToHandle[id], id, peer.peerId, peer);
617
+ delete this.#messagesToHandle[id];
618
+ }
619
+ }
620
+ };
621
+ #peerError = (peer, error) => {
622
+ console.warn(`Connection error: ${error.message}`);
623
+ peer.destroy();
624
+ };
625
+ async close() {
626
+ for (const star in this.#stars) {
627
+ if (this.#stars[star].connectionState() === 'open')
628
+ await this.#stars[star].send({ url: 'leave', params: this.peerId });
629
+ }
630
+ const promises = [
631
+ Object.values(this.#connections).map((connection) => connection.destroy()),
632
+ Object.values(this.#stars).map((connection) => connection.close(0))
633
+ ];
634
+ return Promise.allSettled(promises);
635
+ }
636
+ }
637
+
638
+ export { Client as default };
@@ -0,0 +1,37 @@
1
+ import { M as MultiWallet, e as encrypt, b as base58$1 } from './node-browser-DewO13hB.js';
2
+ import './index-CM4QYC3g.js';
3
+
4
+ /**
5
+ * @params {String} network
6
+ * @return {object} { identity, accounts, config }
7
+ */
8
+ var index = async (password, network) => {
9
+ if (!password)
10
+ throw new Error('wallets need to be password protected.');
11
+ let wallet = new MultiWallet(network);
12
+ /**
13
+ * @type {string}
14
+ */
15
+ let mnemonic = await wallet.generate(password);
16
+ wallet = new MultiWallet(network);
17
+ await wallet.recover(mnemonic, password, network);
18
+ mnemonic = new Uint8Array(await encrypt(password, mnemonic));
19
+ const multiWIF = new Uint8Array(await encrypt(password, await wallet.multiWIF));
20
+ /**
21
+ * @type {object}
22
+ */
23
+ const external = await wallet.account(1).external(1);
24
+ const externalAddress = await external.address;
25
+ const internal = await wallet.account(1).internal(1);
26
+ const internalAddress = await internal.address;
27
+ return {
28
+ identity: {
29
+ mnemonic: base58$1.encode(mnemonic),
30
+ multiWIF: base58$1.encode(multiWIF),
31
+ walletId: await external.id
32
+ },
33
+ accounts: [['main account', externalAddress, internalAddress]]
34
+ };
35
+ };
36
+
37
+ export { index as default };