@leofcoin/peernet 0.9.11 → 0.10.1

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.
@@ -33,10 +33,17 @@ var MultiWallet__default = /*#__PURE__*/_interopDefaultLegacy(MultiWallet);
33
33
  class PeernetPeer {
34
34
  constructor(id, connection) {
35
35
  this._events = {};
36
+ this.bw = {
37
+ up: 0,
38
+ down: 0,
39
+ };
36
40
  this.id = id;
37
41
  this.connection = connection;
38
42
 
39
- this.connection.on('data', (message) => pubsub.publish('peernet.data', JSON.parse(message.toString())));
43
+ this.connection.on('data', (message) => {
44
+ this.bw.down += message.length;
45
+ pubsub.publish('peernet.data', JSON.parse(message.toString()));
46
+ });
40
47
  }
41
48
 
42
49
  request(data) {
@@ -62,6 +69,8 @@ class PeernetPeer {
62
69
 
63
70
  write(data) {
64
71
  if (!Buffer.isBuffer(data)) data = Buffer.from(data);
72
+
73
+ this.bw.up += data.length;
65
74
  this.connection.write(data);
66
75
  }
67
76
 
@@ -280,7 +289,7 @@ class LeofcoinStorage$1 {
280
289
 
281
290
  }
282
291
 
283
- var version = "0.9.10";
292
+ var version = "0.10.0";
284
293
 
285
294
  var api$1 = {
286
295
  version: ({send}) => send({client: '@peernet/api/http', version}),
@@ -1971,659 +1980,659 @@ const nothingFoundError = (hash) => {
1971
1980
  return new Error(`nothing found for ${hash}`)
1972
1981
  };
1973
1982
 
1974
- globalThis.leofcoin = globalThis.leofcoin || {};
1975
- globalThis.globalSub = globalThis.globalSub || new PubSub__default['default']({verbose: true});
1976
-
1977
- /**
1978
- * @access public
1979
- * @example
1980
- * const peernet = new Peernet();
1981
- */
1982
- class Peernet {
1983
- /**
1984
- * @access public
1985
- * @param {Object} options
1986
- * @param {String} options.network - desired network
1987
- * @param {String} options.root - path to root directory
1988
- * @param {String} options.storePrefix - prefix for datatores (lfc)
1989
- *
1990
- * @return {Promise} instance of Peernet
1991
- *
1992
- * @example
1993
- * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
1994
- */
1995
- constructor(options = {}) {
1996
- this._discovered = [];
1997
- /**
1998
- * @property {String} network - current network
1999
- */
2000
- this.network = options.network || 'leofcoin';
2001
- const parts = this.network.split(':');
2002
-
2003
- if (!options.storePrefix) options.storePrefix = 'lfc';
2004
- if (!options.port) options.port = 2000;
2005
- if (!options.root) {
2006
- if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
2007
- else options.root = `.${this.network}/peernet`;
2008
- }
2009
- globalThis.peernet = this;
2010
- return this._init(options)
2011
- }
2012
-
2013
- get defaultStores() {
2014
- return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
2015
- }
2016
-
2017
- addProto(name, proto) {
2018
- if (!this.protos[name]) this.protos[name] = proto;
2019
- }
2020
-
2021
- addCodec(name, codec) {
2022
- if (!this.codecs[name]) this.codecs[name] = codec;
2023
- }
2024
-
2025
- async addStore(name, prefix, root, isPrivate = true) {
2026
- if (name === 'block' || name === 'transaction' || name === 'chain' ||
2027
- name === 'data' || name === 'message') isPrivate = false;
2028
-
2029
- let Storage;
2030
- if (this.hasDaemon) {
2031
- Storage = LeofcoinStorageClient;
2032
- } else {
2033
- Storage = LeofcoinStorage$1;
2034
- }
2035
- globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
2036
- await new Storage(`${prefix}-${name}`, root);
2037
-
2038
- globalThis[`${name}Store`].private = isPrivate;
2039
- if (!isPrivate) this.stores.push(name);
2040
- }
2041
-
2042
-
2043
- /**
2044
- * @see MessageHandler
2045
- */
2046
- prepareMessage(to, data) {
2047
- return this._messageHandler.prepareMessage(this.id, to, data)
2048
- }
2049
-
2050
- /**
2051
- * @access public
2052
- *
2053
- * @return {Array} peerId
2054
- */
2055
- get peers() {
2056
- return [...connections.values()]
2057
- }
2058
-
2059
- /**
2060
- * @private
2061
- *
2062
- * @param {Object} options
2063
- * @param {String} options.root - path to root directory
2064
- *
2065
- * @return {Promise} instance of Peernet
2066
- */
2067
- async _init(options) {
2068
- // peernetDHT aka closesPeer by coordinates
2069
- /**
2070
- * @type {Object}
2071
- * @property {Object} peer Instance of Peer
2072
- */
2073
- this.dht = new DhtEarth();
2074
- /**
2075
- * @type {Map}
2076
- * @property {Object} peer Instance of Peer
2077
- */
2078
- this.peerMap = new Map();
2079
- this.stores = [];
2080
- this.requestProtos = {};
2081
- this.storePrefix = options.storePrefix;
2082
- this.root = options.root;
2083
-
2084
- /**
2085
- * proto Object containing protos
2086
- * @type {Object}
2087
- * @property {PeernetMessage} protos[peernet-message] messageNode
2088
- * @property {DHTMessage} protos[peernet-dht] messageNode
2089
- * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
2090
- * @property {DataMessage} protos[peernet-data] messageNode
2091
- * @property {DataMessageResponse} protos[peernet-data-response] messageNode
2092
- */
2093
- globalThis.peernet.protos = {
2094
- 'peernet-request': RequestMessage,
2095
- 'peernet-response': ResponseMessage,
2096
- 'peernet-peer': PeerMessage,
2097
- 'peernet-peer-response': PeerMessageResponse,
2098
- 'peernet-message': PeernetMessage,
2099
- 'peernet-dht': DHTMessage,
2100
- 'peernet-dht-response': DHTMessageResponse,
2101
- 'peernet-data': DataMessage,
2102
- 'peernet-data-response': DataMessageResponse,
2103
- 'peernet-ps': PsMessage,
2104
- 'chat-message': ChatMessage,
2105
- };
2106
-
2107
- this.protos = globalThis.peernet.protos;
2108
- this.codecs = codecs;
2109
-
2110
- this._messageHandler = new MessageHandler(this.network);
2111
-
2112
- const {daemon, environment} = await target();
2113
- this.hasDaemon = daemon;
2114
-
2115
- if (this.hasDaemon) {
2116
- globalThis.peernet.client = await httpClient({
2117
- protocol: 'peernet-v0.1.0', host: '127.0.0.1', port: options.port,
2118
- });
2119
- } else {
2120
- if (environment !== 'browser') http(options);
2121
- }
2122
-
2123
- for (const store of this.defaultStores) {
2124
- await this.addStore(store, options.storePrefix, options.root);
2125
- }
2126
-
2127
- try {
2128
- const pub = await accountStore.get('public');
2129
- this.id = pub.walletId;
2130
- } catch (e) {
2131
- if (e.code === 'ERR_NOT_FOUND') {
2132
- const wallet = {};
2133
- const {identity, accounts, config} = await generateAccount(this.network);
2134
- wallet.identity = identity;
2135
- wallet.accounts = accounts;
2136
- wallet.version = 1;
2137
- walletStore.put(wallet);
2138
- await accountStore.put('config', config);
2139
- await accountStore.put('public', {walletId: wallet.identity.walletId});
2140
-
2141
- this.id = wallet.identity.walletId;
2142
- } else {
2143
- throw e
2144
- }
2145
- }
2146
- this._peerHandler = new PeerDiscovery(this.id);
2147
- // peernet id
2148
- const id = Buffer.from(this.id.slice(0, 32));
2149
- this.peerId = id;
2150
-
2151
- pubsub.subscribe('peer:discovered', async (peer) => {
2152
- peer.on('peernet.data', async (message) => {
2153
- const id = message.id;
2154
- message = new PeernetMessage(Buffer.from(message.data.data));
2155
- const proto = protoFor(message.decoded.data);
2156
- await this._protoHandler({id, proto}, peer);
2157
- });
2158
- await this._peerHandler.discover(peer);
2159
- const fulldId = this._getPeerId(peer.id);
2160
- if (fulldId && this._discovered.indexOf(peer.id) === -1) {
2161
- this._discovered.push(peer.id);
2162
- pubsub.publish('peer:connected', peer);
2163
- }
2164
- });
2165
- pubsub.subscribe('peer:disconnected', async (peer) => {
2166
- let index = this._discovered.indexOf(peer.id);
2167
- if (index !== -1) this._discovered.splice(index, 1);
2168
- const id = this._getPeerId(peer.id);
2169
- let peerIds = this.peerMap.get(id);
2170
-
2171
- if (peerIds) {
2172
- index = peerIds.indexOf(peer.id);
2173
- if (index !== -1) peerIds.splice(index, 1);
2174
- } else {
2175
- peerIds = [];
2176
- }
2177
-
2178
- if (peerIds.length === 0) this.peerMap.delete(id);
2179
- else this.peerMap.set(id, peerIds);
2180
- });
2181
- pubsub.subscribe('peer:connected', async (peer) => {
2182
- console.log({connected: peer.id, as: this._getPeerId(peer.id) });
2183
- // peer.on('peernet.data', async (message) => {
2184
- // const id = message.id
2185
- // message = new PeernetMessage(Buffer.from(message.data.data))
2186
- // const proto = protoFor(message.decoded.data)
2187
- // this._protoHandler({id, proto}, peer)
2188
- // })
2189
- });
2190
-
2191
- /**
2192
- * @access public
2193
- * @type {PeernetClient}
2194
- */
2195
- this.client = new PeernetClient({...options, id});
2196
- if (globalThis.onbeforeunload) {
2197
- globalThisaddEventListener("beforeunload", async () => this.client.close());
2198
- }
2199
- return this
2200
- }
2201
-
2202
- _getPeerId(id) {
2203
- for (const entry of [...this.peerMap.entries()]) {
2204
- for (const _id of entry[1]) {
2205
- if (_id === id) return entry[0]
2206
- }
2207
- }
2208
- }
2209
-
2210
- addRequestHandler(name, method) {
2211
- this.requestProtos[name] = method;
2212
- }
2213
-
2214
- /**
2215
- * @private
2216
- *
2217
- * @param {Buffer} message - peernet message
2218
- * @param {PeernetPeer} peer - peernet peer
2219
- */
2220
- async _protoHandler(message, peer) {
2221
- const {id, proto} = message;
2222
- if (proto.name === 'peernet-peer') {
2223
- const from = proto.decoded.id;
2224
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2225
- else {
2226
- const connections = this.peerMap.get(from);
2227
- if (connections.indexOf(peer.id) === -1) {
2228
- connections.push(peer.id);
2229
- this.peerMap.set(from, connections);
2230
- }
2231
- }
2232
- const data = new PeerMessageResponse({id: this.id});
2233
- const node = await this.prepareMessage(from, data.encoded);
2234
-
2235
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2236
- } else if (proto.name === 'peernet-peer-response') {
2237
- const from = proto.decoded.id;
2238
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2239
- else {
2240
- const connections = this.peerMap.get(from);
2241
- if (connections.indexOf(peer.id) === -1) {
2242
- connections.push(peer.id);
2243
- this.peerMap.set(from, connections);
2244
- }
2245
- }
2246
- } else {
2247
- let from = this._getPeerId(peer.id);
2248
- if (!from) {
2249
- const data = new PeerMessage({id: this.id});
2250
- const node = await this.prepareMessage(peer.id, data.encoded);
2251
-
2252
- let response = await peer.request(node.encoded);
2253
- response = protoFor(response);
2254
- response = new PeerMessageResponse(response.decoded.data);
2255
-
2256
- from = response.decoded.id;
2257
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2258
- else {
2259
- const connections = this.peerMap.get(from);
2260
- if (connections.indexOf(peer.id) === -1) {
2261
- connections.push(peer.id);
2262
- this.peerMap.set(from, connections);
2263
- }
2264
- }
2265
- }
2266
- if (proto.name === 'peernet-dht') {
2267
- let { hash, store } = proto.decoded;
2268
- let has;
2269
-
2270
- if (!store) {
2271
- has = await this.has(hash);
2272
- } else {
2273
- store = globalThis[`${store}Store`];
2274
- if (store.private) has = false;
2275
- else has = await store.has(hash);
2276
- }
2277
- const data = new DHTMessageResponse({hash, has});
2278
- const node = await this.prepareMessage(from, data.encoded);
2279
-
2280
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2281
- } else if (proto.name === 'peernet-data') {
2282
- let { hash, store } = proto.decoded;
2283
- let data;
2284
-
2285
- if (!store) {
2286
- data = await this.get(hash);
2287
- } else {
2288
- store = globalThis[`${store}Store`];
2289
- if (store.private) {
2290
- // TODO: ban
2291
- return
2292
- } else data = await store.get(hash);
2293
- }
2294
-
2295
- if (data) {
2296
- data = new DataMessageResponse({hash, data: data.decoded ? Buffer.from(JSON.stringify(data)) : Buffer.from(data)});
2297
-
2298
- const node = await this.prepareMessage(from, data.encoded);
2299
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2300
- }
2301
- } else if (proto.name === 'peernet-peer') {
2302
- const from = proto.decoded.id;
2303
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2304
- else {
2305
- const connections = this.peerMap.get(from);
2306
- connections.push(peer.id);
2307
- this.peerMap.set(from, connections);
2308
- }
2309
- const data = new PeerMessage({id: this.id});
2310
- const node = await this.prepareMessage(from, data.encoded);
2311
-
2312
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2313
- } else if (proto.name === 'peernet-request') {
2314
- // TODO: make dynamic
2315
- // exposeddevapi[proto.decoded.request](proto.decoded.params)
2316
- const method = this.requestProtos[proto.decoded.request];
2317
- if (method) {
2318
- const data = await method();
2319
- const node = await this.prepareMessage(from, data.encoded);
2320
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2321
- }
2322
- } else if (proto.name === 'peernet-ps' &&
2323
- this._getPeerId(peer.id) !== this.id.toString()) {
2324
- globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
2325
- }
2326
- }
2327
- }
2328
-
2329
- /**
2330
- * performs a walk and resolves first encounter
2331
- *
2332
- * @param {String} hash
2333
- */
2334
- async walk(hash) {
2335
- if (!hash) throw new Error('hash expected, received undefined')
2336
- const data = new DHTMessage({hash});
2337
- this.client.id;
2338
- for (const peer of this.peers) {
2339
- const node = await this.prepareMessage(peer.id, data.encoded);
2340
-
2341
- const result = await peer.request(node.encoded);
2342
-
2343
- let proto = protoFor(result.data);
2344
-
2345
- if (proto.name !== 'peernet-message') throw encapsulatedError()
2346
- const from = proto.decoded.from;
2347
- proto = protoFor(proto.decoded.data);
2348
-
2349
- if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
2350
-
2351
- // TODO: give ip and port (just used for location)
2352
- if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
2353
- peer.connection.remoteFamily = 'ipv4';
2354
- peer.connection.remoteAddress = '127.0.0.1';
2355
- peer.connection.remotePort = '0000';
2356
- }
2357
-
2358
- const peerInfo = {
2359
- family: peer.connection.remoteFamily || peer.connection.localFamily,
2360
- address: peer.connection.remoteAddress || peer.connection.localAddress,
2361
- port: peer.connection.remotePort || peer.connection.localPort,
2362
- id: from,
2363
- };
2364
-
2365
- if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
2366
- }
2367
- return
2368
- }
2369
-
2370
- /**
2371
- * Override DHT behavior, try's finding the content three times
2372
- *
2373
- * @param {String} hash
2374
- */
2375
- async providersFor(hash) {
2376
- let providers = await this.dht.providersFor(hash);
2377
- // walk the network to find a provider
2378
- if (!providers || providers.length === 0) {
2379
- await this.walk(hash);
2380
- providers = await this.dht.providersFor(hash);
2381
- // second walk the network to find a provider
2382
- if (!providers || providers.length === 0) {
2383
- await this.walk(hash);
2384
- providers = await this.dht.providersFor(hash);
2385
- }
2386
- // last walk
2387
- if (!providers || providers.length === 0) {
2388
- await this.walk(hash);
2389
- providers = await this.dht.providersFor(hash);
2390
- }
2391
- }
2392
- // undefined if no providers given
2393
- return providers
2394
- }
2395
-
2396
- get block() {
2397
- return {
2398
- get: async (hash) => {
2399
- const data = await blockStore.has(hash);
2400
- if (data) return await blockStore.get(hash)
2401
- return this.requestData(hash)
2402
- },
2403
- put: async (hash, data) => {
2404
- if (await blockStore.has(hash)) return
2405
- return await blockStore.put(hash, data)
2406
- },
2407
- has: async (hash) => await blockStore.has(hash, 'block'),
2408
- }
2409
- }
2410
-
2411
- get transaction() {
2412
- return {
2413
- get: async (hash) => {
2414
- const data = await transactionStore.has(hash);
2415
- if (data) return await transactionStore.get(hash)
2416
- return this.requestData(hash, 'transaction')
2417
- },
2418
- put: async (hash, data) => {
2419
- if (await transactionStore.has(hash)) return
2420
- return await transactionStore.put(hash, data)
2421
- },
2422
- has: async (hash) => await transactionStore.has(hash),
2423
- }
2424
- }
2425
-
2426
- async requestData(hash, store) {
2427
- const providers = await this.providersFor(hash);
2428
- if (!providers || providers.size === 0) throw nothingFoundError(hash)
2429
- debug(`found ${providers.size} provider(s) for ${hash}`);
2430
- // get closest peer on earth
2431
- const closestPeer = await this.dht.closestPeer(providers);
2432
- // get peer instance by id
2433
- if (!closestPeer || !closestPeer.id) return this.requestData(hash, store)
2434
-
2435
- const id = closestPeer.id.toString();
2436
- if (this.peers) {
2437
- let closest = this.peers.filter((peer) => {
2438
- if (this._getPeerId(peer.id) === id) return peer
2439
- });
2440
-
2441
- let data = new DataMessage({hash, store});
2442
-
2443
- const node = await this.prepareMessage(id, data.encoded);
2444
- if (closest[0]) data = await closest[0].request(node.encoded);
2445
- else {
2446
- closest = this.peers.filter((peer) => {
2447
- if (peer.id.toString() === id) return peer
2448
- });
2449
- if (closest[0]) data = await closest[0].request(node.encoded);
2450
- }
2451
- if (data.data) {
2452
- let proto = protoFor(Buffer.from(data.data));
2453
- proto = protoFor(proto.decoded.data);
2454
- return proto.decoded.data
2455
- }
2456
-
2457
- // this.put(hash, proto.decoded.data)
2458
- }
2459
- return null
2460
- }
2461
-
2462
-
2463
- get message() {
2464
- return {
2465
- /**
2466
- * Get content for given message hash
2467
- *
2468
- * @param {String} hash
2469
- */
2470
- get: async (hash) => {
2471
- debug(`get message ${hash}`);
2472
- const message = await messageStore.has(hash);
2473
- if (message) return await messageStore.get(hash)
2474
- return this.requestData(hash, 'message')
2475
- },
2476
- /**
2477
- * put message content
2478
- *
2479
- * @param {String} hash
2480
- * @param {Buffer} message
2481
- */
2482
- put: async (hash, message) => await messageStore.put(hash, message),
2483
- /**
2484
- * @param {String} hash
2485
- * @return {Boolean}
2486
- */
2487
- has: async (hash) => await messageStore.has(hash),
2488
- }
2489
- }
2490
-
2491
- get data() {
2492
- return {
2493
- /**
2494
- * Get content for given data hash
2495
- *
2496
- * @param {String} hash
2497
- */
2498
- get: async (hash) => {
2499
- debug(`get data ${hash}`);
2500
- const data = await dataStore.has(hash);
2501
- if (data) return await dataStore.get(hash)
2502
- return this.requestData(hash, 'data')
2503
- },
2504
- /**
2505
- * put data content
2506
- *
2507
- * @param {String} hash
2508
- * @param {Buffer} data
2509
- */
2510
- put: async (hash, data) => await dataStore.put(hash, data),
2511
- /**
2512
- * @param {String} hash
2513
- * @return {Boolean}
2514
- */
2515
- has: async (hash) => await dataStore.has(hash),
2516
- }
2517
- }
2518
-
2519
- /**
2520
- * goes trough given stores and tries to find data for given hash
2521
- * @param {Array} stores
2522
- * @param {string} hash
2523
- */
2524
- async whichStore(stores, hash) {
2525
- let store = stores.pop();
2526
- store = globalThis[`${store}Store`];
2527
- if (store) {
2528
- const has = await store.has(hash);
2529
- if (has) return store
2530
- if (stores.length > 0) return this.whichStore(stores, hash)
2531
- } else return null
2532
- }
2533
-
2534
- /**
2535
- * Get content for given hash
2536
- *
2537
- * @param {String} hash
2538
- */
2539
- async get(hash, store) {
2540
- debug(`get ${hash}`);
2541
- let data;
2542
- if (store) store = globalThis[`${store}Store`];
2543
- if (!store) store = await this.whichStore([...this.stores], hash);
2544
- if (store && await store.has(hash)) data = await store.get(hash);
2545
- if (data) return data
2546
-
2547
- return this.requestData(hash, 'data')
2548
- }
2549
-
2550
- /**
2551
- * put content
2552
- *
2553
- * @param {String} hash
2554
- * @param {Buffer} data
2555
- */
2556
- async put(hash, data, store = 'data') {
2557
- store = globalThis[`${store}Store`];
2558
- return await store.put(hash, data)
2559
- }
2560
-
2561
- /**
2562
- * @param {String} hash
2563
- * @return {Boolean}
2564
- */
2565
- async has(hash) {
2566
- const store = await this.whichStore([...this.stores], hash);
2567
- if (store) {
2568
- if (store.private) return false
2569
- else return true
2570
- }
2571
- return false
2572
- }
2573
-
2574
- /**
2575
- *
2576
- * @param {String} topic
2577
- * @param {String|Object|Array|Boolean|Buffer} data
2578
- */
2579
- async publish(topic, data) {
2580
- // globalSub.publish(topic, data)
2581
- if (!Buffer.isBuffer(topic)) topic = Buffer.from(topic);
2582
- if (!Buffer.isBuffer(data)) data = Buffer.from(data);
2583
- const id = Math.random().toString(36).slice(-12);
2584
- data = new PsMessage({data, topic});
2585
- for (const peer of this.peers) {
2586
- if (peer.connection._connected) {
2587
- if (peer.id.toString() !== this.peerId.toString()) {
2588
- const node = await this.prepareMessage(peer.id, data.encoded);
2589
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2590
- }
2591
- } else {
2592
- this.removePeer(peer);
2593
- }
2594
- // TODO: if peer subscribed
2595
- }
2596
- }
2597
-
2598
- createHash(data, name) {
2599
- return new PeernetHash(data, {name})
2600
- }
2601
-
2602
- /**
2603
- *
2604
- * @param {String} topic
2605
- * @param {Method} cb
2606
- */
2607
- async subscribe(topic, cb) {
2608
- // TODO: if peer subscribed
2609
- globalSub.subscribe(topic, cb);
2610
- }
2611
-
2612
- async removePeer(peer) {
2613
- connections.delete(peer.id);
2614
- }
2615
-
2616
- get Buffer() {
2617
- return Buffer
2618
- }
2619
- // async block(index) {
2620
- // const _values = []
2621
- // for (const peer of this.peers) {
2622
- // const value = await peer.request({type: 'block', index})
2623
- // console.log(value);
2624
- // }
2625
- //
2626
- // }
1983
+ globalThis.leofcoin = globalThis.leofcoin || {};
1984
+ globalThis.globalSub = globalThis.globalSub || new PubSub__default['default']({verbose: true});
1985
+
1986
+ /**
1987
+ * @access public
1988
+ * @example
1989
+ * const peernet = new Peernet();
1990
+ */
1991
+ class Peernet {
1992
+ /**
1993
+ * @access public
1994
+ * @param {Object} options
1995
+ * @param {String} options.network - desired network
1996
+ * @param {String} options.root - path to root directory
1997
+ * @param {String} options.storePrefix - prefix for datatores (lfc)
1998
+ *
1999
+ * @return {Promise} instance of Peernet
2000
+ *
2001
+ * @example
2002
+ * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
2003
+ */
2004
+ constructor(options = {}) {
2005
+ this._discovered = [];
2006
+ /**
2007
+ * @property {String} network - current network
2008
+ */
2009
+ this.network = options.network || 'leofcoin';
2010
+ const parts = this.network.split(':');
2011
+
2012
+ if (!options.storePrefix) options.storePrefix = 'lfc';
2013
+ if (!options.port) options.port = 2000;
2014
+ if (!options.root) {
2015
+ if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
2016
+ else options.root = `.${this.network}/peernet`;
2017
+ }
2018
+ globalThis.peernet = this;
2019
+ return this._init(options)
2020
+ }
2021
+
2022
+ get defaultStores() {
2023
+ return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
2024
+ }
2025
+
2026
+ addProto(name, proto) {
2027
+ if (!this.protos[name]) this.protos[name] = proto;
2028
+ }
2029
+
2030
+ addCodec(name, codec) {
2031
+ if (!this.codecs[name]) this.codecs[name] = codec;
2032
+ }
2033
+
2034
+ async addStore(name, prefix, root, isPrivate = true) {
2035
+ if (name === 'block' || name === 'transaction' || name === 'chain' ||
2036
+ name === 'data' || name === 'message') isPrivate = false;
2037
+
2038
+ let Storage;
2039
+ if (this.hasDaemon) {
2040
+ Storage = LeofcoinStorageClient;
2041
+ } else {
2042
+ Storage = LeofcoinStorage$1;
2043
+ }
2044
+ globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
2045
+ await new Storage(`${prefix}-${name}`, root);
2046
+
2047
+ globalThis[`${name}Store`].private = isPrivate;
2048
+ if (!isPrivate) this.stores.push(name);
2049
+ }
2050
+
2051
+
2052
+ /**
2053
+ * @see MessageHandler
2054
+ */
2055
+ prepareMessage(to, data) {
2056
+ return this._messageHandler.prepareMessage(this.id, to, data)
2057
+ }
2058
+
2059
+ /**
2060
+ * @access public
2061
+ *
2062
+ * @return {Array} peerId
2063
+ */
2064
+ get peers() {
2065
+ return [...connections.values()]
2066
+ }
2067
+
2068
+ /**
2069
+ * @private
2070
+ *
2071
+ * @param {Object} options
2072
+ * @param {String} options.root - path to root directory
2073
+ *
2074
+ * @return {Promise} instance of Peernet
2075
+ */
2076
+ async _init(options) {
2077
+ // peernetDHT aka closesPeer by coordinates
2078
+ /**
2079
+ * @type {Object}
2080
+ * @property {Object} peer Instance of Peer
2081
+ */
2082
+ this.dht = new DhtEarth();
2083
+ /**
2084
+ * @type {Map}
2085
+ * @property {Object} peer Instance of Peer
2086
+ */
2087
+ this.peerMap = new Map();
2088
+ this.stores = [];
2089
+ this.requestProtos = {};
2090
+ this.storePrefix = options.storePrefix;
2091
+ this.root = options.root;
2092
+
2093
+ /**
2094
+ * proto Object containing protos
2095
+ * @type {Object}
2096
+ * @property {PeernetMessage} protos[peernet-message] messageNode
2097
+ * @property {DHTMessage} protos[peernet-dht] messageNode
2098
+ * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
2099
+ * @property {DataMessage} protos[peernet-data] messageNode
2100
+ * @property {DataMessageResponse} protos[peernet-data-response] messageNode
2101
+ */
2102
+ globalThis.peernet.protos = {
2103
+ 'peernet-request': RequestMessage,
2104
+ 'peernet-response': ResponseMessage,
2105
+ 'peernet-peer': PeerMessage,
2106
+ 'peernet-peer-response': PeerMessageResponse,
2107
+ 'peernet-message': PeernetMessage,
2108
+ 'peernet-dht': DHTMessage,
2109
+ 'peernet-dht-response': DHTMessageResponse,
2110
+ 'peernet-data': DataMessage,
2111
+ 'peernet-data-response': DataMessageResponse,
2112
+ 'peernet-ps': PsMessage,
2113
+ 'chat-message': ChatMessage,
2114
+ };
2115
+
2116
+ this.protos = globalThis.peernet.protos;
2117
+ this.codecs = codecs;
2118
+
2119
+ this._messageHandler = new MessageHandler(this.network);
2120
+
2121
+ const {daemon, environment} = await target();
2122
+ this.hasDaemon = daemon;
2123
+
2124
+ if (this.hasDaemon) {
2125
+ globalThis.peernet.client = await httpClient({
2126
+ protocol: 'peernet-v0.1.0', host: '127.0.0.1', port: options.port,
2127
+ });
2128
+ } else {
2129
+ if (environment !== 'browser') http(options);
2130
+ }
2131
+
2132
+ for (const store of this.defaultStores) {
2133
+ await this.addStore(store, options.storePrefix, options.root);
2134
+ }
2135
+
2136
+ try {
2137
+ const pub = await accountStore.get('public');
2138
+ this.id = pub.walletId;
2139
+ } catch (e) {
2140
+ if (e.code === 'ERR_NOT_FOUND') {
2141
+ const wallet = {};
2142
+ const {identity, accounts, config} = await generateAccount(this.network);
2143
+ wallet.identity = identity;
2144
+ wallet.accounts = accounts;
2145
+ wallet.version = 1;
2146
+ walletStore.put(wallet);
2147
+ await accountStore.put('config', config);
2148
+ await accountStore.put('public', {walletId: wallet.identity.walletId});
2149
+
2150
+ this.id = wallet.identity.walletId;
2151
+ } else {
2152
+ throw e
2153
+ }
2154
+ }
2155
+ this._peerHandler = new PeerDiscovery(this.id);
2156
+ // peernet id
2157
+ const id = Buffer.from(this.id.slice(0, 32));
2158
+ this.peerId = id;
2159
+
2160
+ pubsub.subscribe('peer:discovered', async (peer) => {
2161
+ peer.on('peernet.data', async (message) => {
2162
+ const id = message.id;
2163
+ message = new PeernetMessage(Buffer.from(message.data.data));
2164
+ const proto = protoFor(message.decoded.data);
2165
+ await this._protoHandler({id, proto}, peer);
2166
+ });
2167
+ await this._peerHandler.discover(peer);
2168
+ const fulldId = this._getPeerId(peer.id);
2169
+ if (fulldId && this._discovered.indexOf(peer.id) === -1) {
2170
+ this._discovered.push(peer.id);
2171
+ pubsub.publish('peer:connected', peer);
2172
+ }
2173
+ });
2174
+ pubsub.subscribe('peer:disconnected', async (peer) => {
2175
+ let index = this._discovered.indexOf(peer.id);
2176
+ if (index !== -1) this._discovered.splice(index, 1);
2177
+ const id = this._getPeerId(peer.id);
2178
+ let peerIds = this.peerMap.get(id);
2179
+
2180
+ if (peerIds) {
2181
+ index = peerIds.indexOf(peer.id);
2182
+ if (index !== -1) peerIds.splice(index, 1);
2183
+ } else {
2184
+ peerIds = [];
2185
+ }
2186
+
2187
+ if (peerIds.length === 0) this.peerMap.delete(id);
2188
+ else this.peerMap.set(id, peerIds);
2189
+ });
2190
+ pubsub.subscribe('peer:connected', async (peer) => {
2191
+ console.log({connected: peer.id, as: this._getPeerId(peer.id) });
2192
+ // peer.on('peernet.data', async (message) => {
2193
+ // const id = message.id
2194
+ // message = new PeernetMessage(Buffer.from(message.data.data))
2195
+ // const proto = protoFor(message.decoded.data)
2196
+ // this._protoHandler({id, proto}, peer)
2197
+ // })
2198
+ });
2199
+
2200
+ /**
2201
+ * @access public
2202
+ * @type {PeernetClient}
2203
+ */
2204
+ this.client = new PeernetClient({...options, id});
2205
+ if (globalThis.onbeforeunload) {
2206
+ globalThis.addEventListener('beforeunload', async () => this.client.close());
2207
+ }
2208
+ return this
2209
+ }
2210
+
2211
+ _getPeerId(id) {
2212
+ for (const entry of [...this.peerMap.entries()]) {
2213
+ for (const _id of entry[1]) {
2214
+ if (_id === id) return entry[0]
2215
+ }
2216
+ }
2217
+ }
2218
+
2219
+ addRequestHandler(name, method) {
2220
+ this.requestProtos[name] = method;
2221
+ }
2222
+
2223
+ /**
2224
+ * @private
2225
+ *
2226
+ * @param {Buffer} message - peernet message
2227
+ * @param {PeernetPeer} peer - peernet peer
2228
+ */
2229
+ async _protoHandler(message, peer) {
2230
+ const {id, proto} = message;
2231
+ if (proto.name === 'peernet-peer') {
2232
+ const from = proto.decoded.id;
2233
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2234
+ else {
2235
+ const connections = this.peerMap.get(from);
2236
+ if (connections.indexOf(peer.id) === -1) {
2237
+ connections.push(peer.id);
2238
+ this.peerMap.set(from, connections);
2239
+ }
2240
+ }
2241
+ const data = new PeerMessageResponse({id: this.id});
2242
+ const node = await this.prepareMessage(from, data.encoded);
2243
+
2244
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2245
+ } else if (proto.name === 'peernet-peer-response') {
2246
+ const from = proto.decoded.id;
2247
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2248
+ else {
2249
+ const connections = this.peerMap.get(from);
2250
+ if (connections.indexOf(peer.id) === -1) {
2251
+ connections.push(peer.id);
2252
+ this.peerMap.set(from, connections);
2253
+ }
2254
+ }
2255
+ } else {
2256
+ let from = this._getPeerId(peer.id);
2257
+ if (!from) {
2258
+ const data = new PeerMessage({id: this.id});
2259
+ const node = await this.prepareMessage(peer.id, data.encoded);
2260
+
2261
+ let response = await peer.request(node.encoded);
2262
+ response = protoFor(response);
2263
+ response = new PeerMessageResponse(response.decoded.data);
2264
+
2265
+ from = response.decoded.id;
2266
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2267
+ else {
2268
+ const connections = this.peerMap.get(from);
2269
+ if (connections.indexOf(peer.id) === -1) {
2270
+ connections.push(peer.id);
2271
+ this.peerMap.set(from, connections);
2272
+ }
2273
+ }
2274
+ }
2275
+ if (proto.name === 'peernet-dht') {
2276
+ let { hash, store } = proto.decoded;
2277
+ let has;
2278
+
2279
+ if (!store) {
2280
+ has = await this.has(hash);
2281
+ } else {
2282
+ store = globalThis[`${store}Store`];
2283
+ if (store.private) has = false;
2284
+ else has = await store.has(hash);
2285
+ }
2286
+ const data = new DHTMessageResponse({hash, has});
2287
+ const node = await this.prepareMessage(from, data.encoded);
2288
+
2289
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2290
+ } else if (proto.name === 'peernet-data') {
2291
+ let { hash, store } = proto.decoded;
2292
+ let data;
2293
+
2294
+ if (!store) {
2295
+ data = await this.get(hash);
2296
+ } else {
2297
+ store = globalThis[`${store}Store`];
2298
+ if (store.private) {
2299
+ // TODO: ban
2300
+ return
2301
+ } else data = await store.get(hash);
2302
+ }
2303
+
2304
+ if (data) {
2305
+ data = new DataMessageResponse({hash, data: data.decoded ? Buffer.from(JSON.stringify(data)) : Buffer.from(data)});
2306
+
2307
+ const node = await this.prepareMessage(from, data.encoded);
2308
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2309
+ }
2310
+ } else if (proto.name === 'peernet-peer') {
2311
+ const from = proto.decoded.id;
2312
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
2313
+ else {
2314
+ const connections = this.peerMap.get(from);
2315
+ connections.push(peer.id);
2316
+ this.peerMap.set(from, connections);
2317
+ }
2318
+ const data = new PeerMessage({id: this.id});
2319
+ const node = await this.prepareMessage(from, data.encoded);
2320
+
2321
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2322
+ } else if (proto.name === 'peernet-request') {
2323
+ // TODO: make dynamic
2324
+ // exposeddevapi[proto.decoded.request](proto.decoded.params)
2325
+ const method = this.requestProtos[proto.decoded.request];
2326
+ if (method) {
2327
+ const data = await method();
2328
+ const node = await this.prepareMessage(from, data.encoded);
2329
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2330
+ }
2331
+ } else if (proto.name === 'peernet-ps' &&
2332
+ this._getPeerId(peer.id) !== this.id.toString()) {
2333
+ globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
2334
+ }
2335
+ }
2336
+ }
2337
+
2338
+ /**
2339
+ * performs a walk and resolves first encounter
2340
+ *
2341
+ * @param {String} hash
2342
+ */
2343
+ async walk(hash) {
2344
+ if (!hash) throw new Error('hash expected, received undefined')
2345
+ const data = new DHTMessage({hash});
2346
+ this.client.id;
2347
+ for (const peer of this.peers) {
2348
+ const node = await this.prepareMessage(peer.id, data.encoded);
2349
+
2350
+ const result = await peer.request(node.encoded);
2351
+
2352
+ let proto = protoFor(result.data);
2353
+
2354
+ if (proto.name !== 'peernet-message') throw encapsulatedError()
2355
+ const from = proto.decoded.from;
2356
+ proto = protoFor(proto.decoded.data);
2357
+
2358
+ if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
2359
+
2360
+ // TODO: give ip and port (just used for location)
2361
+ if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
2362
+ peer.connection.remoteFamily = 'ipv4';
2363
+ peer.connection.remoteAddress = '127.0.0.1';
2364
+ peer.connection.remotePort = '0000';
2365
+ }
2366
+
2367
+ const peerInfo = {
2368
+ family: peer.connection.remoteFamily || peer.connection.localFamily,
2369
+ address: peer.connection.remoteAddress || peer.connection.localAddress,
2370
+ port: peer.connection.remotePort || peer.connection.localPort,
2371
+ id: from,
2372
+ };
2373
+
2374
+ if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
2375
+ }
2376
+ return
2377
+ }
2378
+
2379
+ /**
2380
+ * Override DHT behavior, try's finding the content three times
2381
+ *
2382
+ * @param {String} hash
2383
+ */
2384
+ async providersFor(hash) {
2385
+ let providers = await this.dht.providersFor(hash);
2386
+ // walk the network to find a provider
2387
+ if (!providers || providers.length === 0) {
2388
+ await this.walk(hash);
2389
+ providers = await this.dht.providersFor(hash);
2390
+ // second walk the network to find a provider
2391
+ if (!providers || providers.length === 0) {
2392
+ await this.walk(hash);
2393
+ providers = await this.dht.providersFor(hash);
2394
+ }
2395
+ // last walk
2396
+ if (!providers || providers.length === 0) {
2397
+ await this.walk(hash);
2398
+ providers = await this.dht.providersFor(hash);
2399
+ }
2400
+ }
2401
+ // undefined if no providers given
2402
+ return providers
2403
+ }
2404
+
2405
+ get block() {
2406
+ return {
2407
+ get: async (hash) => {
2408
+ const data = await blockStore.has(hash);
2409
+ if (data) return await blockStore.get(hash)
2410
+ return this.requestData(hash)
2411
+ },
2412
+ put: async (hash, data) => {
2413
+ if (await blockStore.has(hash)) return
2414
+ return await blockStore.put(hash, data)
2415
+ },
2416
+ has: async (hash) => await blockStore.has(hash, 'block'),
2417
+ }
2418
+ }
2419
+
2420
+ get transaction() {
2421
+ return {
2422
+ get: async (hash) => {
2423
+ const data = await transactionStore.has(hash);
2424
+ if (data) return await transactionStore.get(hash)
2425
+ return this.requestData(hash, 'transaction')
2426
+ },
2427
+ put: async (hash, data) => {
2428
+ if (await transactionStore.has(hash)) return
2429
+ return await transactionStore.put(hash, data)
2430
+ },
2431
+ has: async (hash) => await transactionStore.has(hash),
2432
+ }
2433
+ }
2434
+
2435
+ async requestData(hash, store) {
2436
+ const providers = await this.providersFor(hash);
2437
+ if (!providers || providers.size === 0) throw nothingFoundError(hash)
2438
+ debug(`found ${providers.size} provider(s) for ${hash}`);
2439
+ // get closest peer on earth
2440
+ const closestPeer = await this.dht.closestPeer(providers);
2441
+ // get peer instance by id
2442
+ if (!closestPeer || !closestPeer.id) return this.requestData(hash, store)
2443
+
2444
+ const id = closestPeer.id.toString();
2445
+ if (this.peers) {
2446
+ let closest = this.peers.filter((peer) => {
2447
+ if (this._getPeerId(peer.id) === id) return peer
2448
+ });
2449
+
2450
+ let data = new DataMessage({hash, store});
2451
+
2452
+ const node = await this.prepareMessage(id, data.encoded);
2453
+ if (closest[0]) data = await closest[0].request(node.encoded);
2454
+ else {
2455
+ closest = this.peers.filter((peer) => {
2456
+ if (peer.id.toString() === id) return peer
2457
+ });
2458
+ if (closest[0]) data = await closest[0].request(node.encoded);
2459
+ }
2460
+ if (data.data) {
2461
+ let proto = protoFor(Buffer.from(data.data));
2462
+ proto = protoFor(proto.decoded.data);
2463
+ return proto.decoded.data
2464
+ }
2465
+
2466
+ // this.put(hash, proto.decoded.data)
2467
+ }
2468
+ return null
2469
+ }
2470
+
2471
+
2472
+ get message() {
2473
+ return {
2474
+ /**
2475
+ * Get content for given message hash
2476
+ *
2477
+ * @param {String} hash
2478
+ */
2479
+ get: async (hash) => {
2480
+ debug(`get message ${hash}`);
2481
+ const message = await messageStore.has(hash);
2482
+ if (message) return await messageStore.get(hash)
2483
+ return this.requestData(hash, 'message')
2484
+ },
2485
+ /**
2486
+ * put message content
2487
+ *
2488
+ * @param {String} hash
2489
+ * @param {Buffer} message
2490
+ */
2491
+ put: async (hash, message) => await messageStore.put(hash, message),
2492
+ /**
2493
+ * @param {String} hash
2494
+ * @return {Boolean}
2495
+ */
2496
+ has: async (hash) => await messageStore.has(hash),
2497
+ }
2498
+ }
2499
+
2500
+ get data() {
2501
+ return {
2502
+ /**
2503
+ * Get content for given data hash
2504
+ *
2505
+ * @param {String} hash
2506
+ */
2507
+ get: async (hash) => {
2508
+ debug(`get data ${hash}`);
2509
+ const data = await dataStore.has(hash);
2510
+ if (data) return await dataStore.get(hash)
2511
+ return this.requestData(hash, 'data')
2512
+ },
2513
+ /**
2514
+ * put data content
2515
+ *
2516
+ * @param {String} hash
2517
+ * @param {Buffer} data
2518
+ */
2519
+ put: async (hash, data) => await dataStore.put(hash, data),
2520
+ /**
2521
+ * @param {String} hash
2522
+ * @return {Boolean}
2523
+ */
2524
+ has: async (hash) => await dataStore.has(hash),
2525
+ }
2526
+ }
2527
+
2528
+ /**
2529
+ * goes trough given stores and tries to find data for given hash
2530
+ * @param {Array} stores
2531
+ * @param {string} hash
2532
+ */
2533
+ async whichStore(stores, hash) {
2534
+ let store = stores.pop();
2535
+ store = globalThis[`${store}Store`];
2536
+ if (store) {
2537
+ const has = await store.has(hash);
2538
+ if (has) return store
2539
+ if (stores.length > 0) return this.whichStore(stores, hash)
2540
+ } else return null
2541
+ }
2542
+
2543
+ /**
2544
+ * Get content for given hash
2545
+ *
2546
+ * @param {String} hash
2547
+ */
2548
+ async get(hash, store) {
2549
+ debug(`get ${hash}`);
2550
+ let data;
2551
+ if (store) store = globalThis[`${store}Store`];
2552
+ if (!store) store = await this.whichStore([...this.stores], hash);
2553
+ if (store && await store.has(hash)) data = await store.get(hash);
2554
+ if (data) return data
2555
+
2556
+ return this.requestData(hash, 'data')
2557
+ }
2558
+
2559
+ /**
2560
+ * put content
2561
+ *
2562
+ * @param {String} hash
2563
+ * @param {Buffer} data
2564
+ */
2565
+ async put(hash, data, store = 'data') {
2566
+ store = globalThis[`${store}Store`];
2567
+ return await store.put(hash, data)
2568
+ }
2569
+
2570
+ /**
2571
+ * @param {String} hash
2572
+ * @return {Boolean}
2573
+ */
2574
+ async has(hash) {
2575
+ const store = await this.whichStore([...this.stores], hash);
2576
+ if (store) {
2577
+ if (store.private) return false
2578
+ else return true
2579
+ }
2580
+ return false
2581
+ }
2582
+
2583
+ /**
2584
+ *
2585
+ * @param {String} topic
2586
+ * @param {String|Object|Array|Boolean|Buffer} data
2587
+ */
2588
+ async publish(topic, data) {
2589
+ // globalSub.publish(topic, data)
2590
+ if (!Buffer.isBuffer(topic)) topic = Buffer.from(topic);
2591
+ if (!Buffer.isBuffer(data)) data = Buffer.from(data);
2592
+ const id = Math.random().toString(36).slice(-12);
2593
+ data = new PsMessage({data, topic});
2594
+ for (const peer of this.peers) {
2595
+ if (peer.connection._connected) {
2596
+ if (peer.id.toString() !== this.peerId.toString()) {
2597
+ const node = await this.prepareMessage(peer.id, data.encoded);
2598
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2599
+ }
2600
+ } else {
2601
+ this.removePeer(peer);
2602
+ }
2603
+ // TODO: if peer subscribed
2604
+ }
2605
+ }
2606
+
2607
+ createHash(data, name) {
2608
+ return new PeernetHash(data, {name})
2609
+ }
2610
+
2611
+ /**
2612
+ *
2613
+ * @param {String} topic
2614
+ * @param {Method} cb
2615
+ */
2616
+ async subscribe(topic, cb) {
2617
+ // TODO: if peer subscribed
2618
+ globalSub.subscribe(topic, cb);
2619
+ }
2620
+
2621
+ async removePeer(peer) {
2622
+ connections.delete(peer.id);
2623
+ }
2624
+
2625
+ get Buffer() {
2626
+ return Buffer
2627
+ }
2628
+ // async block(index) {
2629
+ // const _values = []
2630
+ // for (const peer of this.peers) {
2631
+ // const value = await peer.request({type: 'block', index})
2632
+ // console.log(value);
2633
+ // }
2634
+ //
2635
+ // }
2627
2636
  }
2628
2637
 
2629
2638
  module.exports = Peernet;