@leofcoin/peernet 0.9.8 → 0.9.11

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.
@@ -35,6 +35,7 @@ var MultiWallet__default = /*#__PURE__*/_interopDefaultLegacy(MultiWallet);
35
35
 
36
36
  class PeernetPeer {
37
37
  constructor(id, connection) {
38
+ this._events = {};
38
39
  this.id = id;
39
40
  this.connection = connection;
40
41
 
@@ -68,13 +69,27 @@ class PeernetPeer {
68
69
  }
69
70
 
70
71
  on(event = 'peernet.data', cb) {
72
+ this._events[event] = cb;
71
73
  pubsub.subscribe(event, cb);
72
74
  // this.connection.on(event, cb)
73
75
  }
74
76
 
75
77
  removeListener(event = 'data', cb) {
78
+ delete this._events[event];
76
79
  pubsub.unsubscribe(event, cb);
77
80
  }
81
+
82
+ close() {
83
+ for (const event of Object.keys(this._events)) {
84
+ pubsub.unsubscribe(event, this._events[event]);
85
+ }
86
+ this._events = [];
87
+
88
+ for (const event of this.connection._events.data) {
89
+ this.connection.removeListener('data', event);
90
+ }
91
+ this.connection.destroy();
92
+ }
78
93
  }
79
94
 
80
95
  /**
@@ -109,6 +124,10 @@ class PeernetClient {
109
124
 
110
125
  this.p2p.on('peerclose', (peer) => {
111
126
  // TODO: close peernetPeer
127
+ const peernetPeer = connections.get(peer.id);
128
+ if (peernetPeer) {
129
+ peernetPeer.close();
130
+ }
112
131
  connections.delete(peer.id);
113
132
  pubsub.publish('peer:disconnected', peer);
114
133
  });
@@ -264,7 +283,7 @@ class LeofcoinStorage$1 {
264
283
 
265
284
  }
266
285
 
267
- var version = "0.9.7";
286
+ var version = "0.9.10";
268
287
 
269
288
  var api$1 = {
270
289
  version: ({send}) => send({client: '@peernet/api/http', version}),
@@ -1124,7 +1143,7 @@ class PeerDiscovery {
1124
1143
  const connections = peernet.peerMap.get(id);
1125
1144
  if (connections.indexOf(peer.id) === -1) {
1126
1145
  connections.push(peer.id);
1127
- peernet.peerMap.set(from, connections);
1146
+ peernet.peerMap.set(peer.id, connections);
1128
1147
  }
1129
1148
  }
1130
1149
  return id
@@ -1387,656 +1406,659 @@ const nothingFoundError = (hash) => {
1387
1406
  return new Error(`nothing found for ${hash}`)
1388
1407
  };
1389
1408
 
1390
- globalThis.leofcoin = globalThis.leofcoin || {};
1391
- globalThis.globalSub = globalThis.globalSub || new PubSub__default['default']({verbose: true});
1392
-
1393
- /**
1394
- * @access public
1395
- * @example
1396
- * const peernet = new Peernet();
1397
- */
1398
- class Peernet {
1399
- /**
1400
- * @access public
1401
- * @param {Object} options
1402
- * @param {String} options.network - desired network
1403
- * @param {String} options.root - path to root directory
1404
- * @param {String} options.storePrefix - prefix for datatores (lfc)
1405
- *
1406
- * @return {Promise} instance of Peernet
1407
- *
1408
- * @example
1409
- * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
1410
- */
1411
- constructor(options = {}) {
1412
- this._discovered = [];
1413
- /**
1414
- * @property {String} network - current network
1415
- */
1416
- this.network = options.network || 'leofcoin';
1417
- const parts = this.network.split(':');
1418
-
1419
- if (!options.storePrefix) options.storePrefix = 'lfc';
1420
- if (!options.port) options.port = 2000;
1421
- if (!options.root) {
1422
- if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
1423
- else options.root = `.${this.network}/peernet`;
1424
- }
1425
- globalThis.peernet = this;
1426
- return this._init(options)
1427
- }
1428
-
1429
- get defaultStores() {
1430
- return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
1431
- }
1432
-
1433
- addProto(name, proto) {
1434
- if (!this.protos[name]) this.protos[name] = proto;
1435
- }
1436
-
1437
- addCodec(name, codec) {
1438
- if (!this.codecs[name]) this.codecs[name] = codec;
1439
- }
1440
-
1441
- async addStore(name, prefix, root, isPrivate = true) {
1442
- if (name === 'block' || name === 'transaction' || name === 'chain' ||
1443
- name === 'data' || name === 'message') isPrivate = false;
1444
-
1445
- let Storage;
1446
- if (this.hasDaemon) {
1447
- Storage = LeofcoinStorageClient;
1448
- } else {
1449
- Storage = LeofcoinStorage$1;
1450
- }
1451
- globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
1452
- await new Storage(`${prefix}-${name}`, root);
1453
-
1454
- globalThis[`${name}Store`].private = isPrivate;
1455
- if (!isPrivate) this.stores.push(name);
1456
- }
1457
-
1458
-
1459
- /**
1460
- * @see MessageHandler
1461
- */
1462
- prepareMessage(to, data) {
1463
- return this._messageHandler.prepareMessage(this.id, to, data)
1464
- }
1465
-
1466
- /**
1467
- * @access public
1468
- *
1469
- * @return {Array} peerId
1470
- */
1471
- get peers() {
1472
- return [...connections.values()]
1473
- }
1474
-
1475
- /**
1476
- * @private
1477
- *
1478
- * @param {Object} options
1479
- * @param {String} options.root - path to root directory
1480
- *
1481
- * @return {Promise} instance of Peernet
1482
- */
1483
- async _init(options) {
1484
- // peernetDHT aka closesPeer by coordinates
1485
- /**
1486
- * @type {Object}
1487
- * @property {Object} peer Instance of Peer
1488
- */
1489
- this.dht = new DhtEarth();
1490
- /**
1491
- * @type {Map}
1492
- * @property {Object} peer Instance of Peer
1493
- */
1494
- this.peerMap = new Map();
1495
- this.stores = [];
1496
- this.requestProtos = {};
1497
- this.storePrefix = options.storePrefix;
1498
- this.root = options.root;
1499
-
1500
- /**
1501
- * proto Object containing protos
1502
- * @type {Object}
1503
- * @property {PeernetMessage} protos[peernet-message] messageNode
1504
- * @property {DHTMessage} protos[peernet-dht] messageNode
1505
- * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
1506
- * @property {DataMessage} protos[peernet-data] messageNode
1507
- * @property {DataMessageResponse} protos[peernet-data-response] messageNode
1508
- */
1509
- globalThis.peernet.protos = {
1510
- 'peernet-request': request,
1511
- 'peernet-response': response,
1512
- 'peernet-peer': PeerMessage,
1513
- 'peernet-peer-response': PeerMessageResponse,
1514
- 'peernet-message': peernetMessage,
1515
- 'peernet-dht': dht,
1516
- 'peernet-dht-response': dhtResponse,
1517
- 'peernet-data': DataMessage,
1518
- 'peernet-data-response': DataMessageResponse,
1519
- 'peernet-ps': PsMessage,
1520
- 'chat-message': ChatMessage,
1521
- };
1522
-
1523
- this.protos = globalThis.peernet.protos;
1524
- this.codecs = codec.codecs;
1525
-
1526
- this._messageHandler = new MessageHandler(this.network);
1527
-
1528
- const {daemon, environment} = await target();
1529
- this.hasDaemon = daemon;
1530
-
1531
- if (this.hasDaemon) {
1532
- globalThis.peernet.client = await httpClient({
1533
- protocol: 'peernet-v0.1.0', host: '127.0.0.1', port: options.port,
1534
- });
1535
- } else {
1536
- if (environment !== 'browser') http(options);
1537
- }
1538
-
1539
- for (const store of this.defaultStores) {
1540
- await this.addStore(store, options.storePrefix, options.root);
1541
- }
1542
-
1543
- try {
1544
- const pub = await accountStore.get('public');
1545
- this.id = pub.walletId;
1546
- } catch (e) {
1547
- if (e.code === 'ERR_NOT_FOUND') {
1548
- const wallet = {};
1549
- const {identity, accounts, config} = await generateAccount(this.network);
1550
- wallet.identity = identity;
1551
- wallet.accounts = accounts;
1552
- wallet.version = 1;
1553
- walletStore.put(wallet);
1554
- await accountStore.put('config', config);
1555
- await accountStore.put('public', {walletId: wallet.identity.walletId});
1556
-
1557
- this.id = wallet.identity.walletId;
1558
- } else {
1559
- throw e
1560
- }
1561
- }
1562
- this._peerHandler = new PeerDiscovery(this.id);
1563
- // peernet id
1564
- const id = Buffer.from(this.id.slice(0, 32));
1565
- this.peerId = id;
1566
-
1567
- pubsub.subscribe('peer:discovered', async (peer) => {
1568
- this._peerHandler.discover(peer);
1569
- peer.on('peernet.data', async (message) => {
1570
- const id = message.id;
1571
- message = new peernetMessage(Buffer.from(message.data.data));
1572
- const proto = protoFor(message.decoded.data);
1573
- await this._protoHandler({id, proto}, peer);
1574
- const fulldId = this._getPeerId(peer.id);
1575
- if (fulldId && this._discovered.indexOf(peer.id) === -1) {
1576
- this._discovered.push(peer.id);
1577
- pubsub.publish('peer:connected', peer);
1578
- }
1579
- });
1580
- });
1581
- pubsub.subscribe('peer:disconnected', async (peer) => {
1582
- let index = this._discovered.indexOf(peer.id);
1583
- if (index !== -1) this._discovered.splice(index, 1);
1584
- const id = this._getPeerId(peer.id);
1585
- let peerIds = this.peerMap.get(id);
1586
-
1587
- if (peerIds) {
1588
- index = peerIds.indexOf(peer.id);
1589
- if (index !== -1) peerIds.splice(index, 1);
1590
- } else {
1591
- peerIds = [];
1592
- }
1593
-
1594
- if (peerIds.length === 0) this.peerMap.delete(id);
1595
- else this.peerMap.set(id, peerIds);
1596
- });
1597
- pubsub.subscribe('peer:connected', async (peer) => {
1598
- console.log({connected: peer.id, as: this._getPeerId(peer.id) });
1599
- // peer.on('peernet.data', async (message) => {
1600
- // const id = message.id
1601
- // message = new PeernetMessage(Buffer.from(message.data.data))
1602
- // const proto = protoFor(message.decoded.data)
1603
- // this._protoHandler({id, proto}, peer)
1604
- // })
1605
- });
1606
-
1607
- /**
1608
- * @access public
1609
- * @type {PeernetClient}
1610
- */
1611
- this.client = new PeernetClient({...options, id});
1612
- return this
1613
- }
1614
-
1615
- _getPeerId(id) {
1616
- for (const entry of [...this.peerMap.entries()]) {
1617
- for (const _id of entry[1]) {
1618
- if (_id === id) return entry[0]
1619
- }
1620
- }
1621
- }
1622
-
1623
- addRequestHandler(name, method) {
1624
- this.requestProtos[name] = method;
1625
- }
1626
-
1627
- /**
1628
- * @private
1629
- *
1630
- * @param {Buffer} message - peernet message
1631
- * @param {PeernetPeer} peer - peernet peer
1632
- */
1633
- async _protoHandler(message, peer) {
1634
- const {id, proto} = message;
1635
- if (proto.name === 'peernet-peer') {
1636
- const from = proto.decoded.id;
1637
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1638
- else {
1639
- const connections = this.peerMap.get(from);
1640
- if (connections.indexOf(peer.id) === -1) {
1641
- connections.push(peer.id);
1642
- this.peerMap.set(from, connections);
1643
- }
1644
- }
1645
- const data = new PeerMessageResponse({id: this.id});
1646
- const node = await this.prepareMessage(from, data.encoded);
1647
-
1648
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1649
- } else if (proto.name === 'peernet-peer-response') {
1650
- const from = proto.decoded.id;
1651
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1652
- else {
1653
- const connections = this.peerMap.get(from);
1654
- if (connections.indexOf(peer.id) === -1) {
1655
- connections.push(peer.id);
1656
- this.peerMap.set(from, connections);
1657
- }
1658
- }
1659
- } else {
1660
- let from = this._getPeerId(peer.id);
1661
- if (!from) {
1662
- const data = new PeerMessage({id: this.id});
1663
- const node = await this.prepareMessage(peer.id, data.encoded);
1664
-
1665
- let response = await peer.request(node.encoded);
1666
- response = protoFor(response);
1667
- response = new PeerMessageResponse(response.decoded.data);
1668
-
1669
- from = response.decoded.id;
1670
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1671
- else {
1672
- const connections = this.peerMap.get(from);
1673
- if (connections.indexOf(peer.id) === -1) {
1674
- connections.push(peer.id);
1675
- this.peerMap.set(from, connections);
1676
- }
1677
- }
1678
- }
1679
- if (proto.name === 'peernet-dht') {
1680
- let { hash, store } = proto.decoded;
1681
- let has;
1682
-
1683
- if (!store) {
1684
- has = await this.has(hash);
1685
- } else {
1686
- store = globalThis[`${store}Store`];
1687
- if (store.private) has = false;
1688
- else has = await store.has(hash);
1689
- }
1690
- const data = new dhtResponse({hash, has});
1691
- const node = await this.prepareMessage(from, data.encoded);
1692
-
1693
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1694
- } else if (proto.name === 'peernet-data') {
1695
- let { hash, store } = proto.decoded;
1696
- let data;
1697
-
1698
- if (!store) {
1699
- data = await this.get(hash);
1700
- } else {
1701
- store = globalThis[`${store}Store`];
1702
- if (store.private) {
1703
- // TODO: ban
1704
- return
1705
- } else data = await store.get(hash);
1706
- }
1707
-
1708
- if (data) {
1709
- data = new DataMessageResponse({hash, data: Buffer.from(data)});
1710
-
1711
- const node = await this.prepareMessage(from, data.encoded);
1712
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1713
- }
1714
- } else if (proto.name === 'peernet-peer') {
1715
- const from = proto.decoded.id;
1716
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1717
- else {
1718
- const connections = this.peerMap.get(from);
1719
- connections.push(peer.id);
1720
- this.peerMap.set(from, connections);
1721
- }
1722
- const data = new PeerMessage({id: this.id});
1723
- const node = await this.prepareMessage(from, data.encoded);
1724
-
1725
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1726
- } else if (proto.name === 'peernet-request') {
1727
- // TODO: make dynamic
1728
- // exposeddevapi[proto.decoded.request](proto.decoded.params)
1729
- const method = this.requestProtos[proto.decoded.request];
1730
- if (method) {
1731
- const data = await method();
1732
- const node = await this.prepareMessage(from, data.encoded);
1733
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1734
- }
1735
- } else if (proto.name === 'peernet-ps' &&
1736
- this._getPeerId(peer.id) !== this.id.toString()) {
1737
- globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
1738
- }
1739
- }
1740
- }
1741
-
1742
- /**
1743
- * performs a walk and resolves first encounter
1744
- *
1745
- * @param {String} hash
1746
- */
1747
- async walk(hash) {
1748
- if (!hash) throw new Error('hash expected, received undefined')
1749
- const data = new dht({hash});
1750
- this.client.id;
1751
- for (const peer of this.peers) {
1752
- const node = await this.prepareMessage(peer.id, data.encoded);
1753
-
1754
- const result = await peer.request(node.encoded);
1755
-
1756
- let proto = protoFor(result.data);
1757
-
1758
- if (proto.name !== 'peernet-message') throw encapsulatedError()
1759
- const from = proto.decoded.from;
1760
- proto = protoFor(proto.decoded.data);
1761
-
1762
- if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
1763
-
1764
- // TODO: give ip and port (just used for location)
1765
- if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
1766
- peer.connection.remoteFamily = 'ipv4';
1767
- peer.connection.remoteAddress = '127.0.0.1';
1768
- peer.connection.remotePort = '0000';
1769
- }
1770
-
1771
- const peerInfo = {
1772
- family: peer.connection.remoteFamily || peer.connection.localFamily,
1773
- address: peer.connection.remoteAddress || peer.connection.localAddress,
1774
- port: peer.connection.remotePort || peer.connection.localPort,
1775
- id: from,
1776
- };
1777
-
1778
- if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
1779
- }
1780
- return
1781
- }
1782
-
1783
- /**
1784
- * Override DHT behavior, try's finding the content three times
1785
- *
1786
- * @param {String} hash
1787
- */
1788
- async providersFor(hash) {
1789
- let providers = await this.dht.providersFor(hash);
1790
- // walk the network to find a provider
1791
- if (!providers || providers.length === 0) {
1792
- await this.walk(hash);
1793
- providers = await this.dht.providersFor(hash);
1794
- // second walk the network to find a provider
1795
- if (!providers || providers.length === 0) {
1796
- await this.walk(hash);
1797
- providers = await this.dht.providersFor(hash);
1798
- }
1799
- // last walk
1800
- if (!providers || providers.length === 0) {
1801
- await this.walk(hash);
1802
- providers = await this.dht.providersFor(hash);
1803
- }
1804
- }
1805
- // undefined if no providers given
1806
- return providers
1807
- }
1808
-
1809
- get block() {
1810
- return {
1811
- get: async (hash) => {
1812
- const data = await blockStore.has(hash);
1813
- if (data) return await blockStore.get(hash)
1814
- return this.requestData(hash)
1815
- },
1816
- put: async (hash, data) => {
1817
- if (await blockStore.has(hash)) return
1818
- return await blockStore.put(hash, data)
1819
- },
1820
- has: async (hash) => await blockStore.has(hash, 'block'),
1821
- }
1822
- }
1823
-
1824
- get transaction() {
1825
- return {
1826
- get: async (hash) => {
1827
- const data = await transactionStore.has(hash);
1828
- if (data) return await transactionStore.get(hash)
1829
- return this.requestData(hash, 'transaction')
1830
- },
1831
- put: async (hash, data) => {
1832
- if (await transactionStore.has(hash)) return
1833
- return await transactionStore.put(hash, data)
1834
- },
1835
- has: async (hash) => await transactionStore.has(hash),
1836
- }
1837
- }
1838
-
1839
- async requestData(hash, store) {
1840
- const providers = await this.providersFor(hash);
1841
- if (!providers || providers.size === 0) throw nothingFoundError(hash)
1842
- debug(`found ${providers.size} provider(s) for ${hash}`);
1843
- // get closest peer on earth
1844
- const closestPeer = await this.dht.closestPeer(providers);
1845
- // get peer instance by id
1846
- if (!closestPeer || !closestPeer.id) return this.requestData(hash, store)
1847
-
1848
- const id = closestPeer.id.toString();
1849
- if (this.peers) {
1850
- let closest = this.peers.filter((peer) => {
1851
- if (this._getPeerId(peer.id) === id) return peer
1852
- });
1853
-
1854
- let data = new DataMessage({hash, store});
1855
-
1856
- const node = await this.prepareMessage(id, data.encoded);
1857
- if (closest[0]) data = await closest[0].request(node.encoded);
1858
- else {
1859
- closest = this.peers.filter((peer) => {
1860
- if (peer.id.toString() === id) return peer
1861
- });
1862
- if (closest[0]) data = await closest[0].request(node.encoded);
1863
- }
1864
- if (data.data) {
1865
- let proto = protoFor(Buffer.from(data.data));
1866
- proto = protoFor(proto.decoded.data);
1867
- return proto.decoded.data
1868
- }
1869
-
1870
- // this.put(hash, proto.decoded.data)
1871
- }
1872
- return null
1873
- }
1874
-
1875
-
1876
- get message() {
1877
- return {
1878
- /**
1879
- * Get content for given message hash
1880
- *
1881
- * @param {String} hash
1882
- */
1883
- get: async (hash) => {
1884
- debug(`get message ${hash}`);
1885
- const message = await messageStore.has(hash);
1886
- if (message) return await messageStore.get(hash)
1887
- return this.requestData(hash, 'message')
1888
- },
1889
- /**
1890
- * put message content
1891
- *
1892
- * @param {String} hash
1893
- * @param {Buffer} message
1894
- */
1895
- put: async (hash, message) => await messageStore.put(hash, message),
1896
- /**
1897
- * @param {String} hash
1898
- * @return {Boolean}
1899
- */
1900
- has: async (hash) => await messageStore.has(hash),
1901
- }
1902
- }
1903
-
1904
- get data() {
1905
- return {
1906
- /**
1907
- * Get content for given data hash
1908
- *
1909
- * @param {String} hash
1910
- */
1911
- get: async (hash) => {
1912
- debug(`get data ${hash}`);
1913
- const data = await dataStore.has(hash);
1914
- if (data) return await dataStore.get(hash)
1915
- return this.requestData(hash, 'data')
1916
- },
1917
- /**
1918
- * put data content
1919
- *
1920
- * @param {String} hash
1921
- * @param {Buffer} data
1922
- */
1923
- put: async (hash, data) => await dataStore.put(hash, data),
1924
- /**
1925
- * @param {String} hash
1926
- * @return {Boolean}
1927
- */
1928
- has: async (hash) => await dataStore.has(hash),
1929
- }
1930
- }
1931
-
1932
- /**
1933
- * goes trough given stores and tries to find data for given hash
1934
- * @param {Array} stores
1935
- * @param {string} hash
1936
- */
1937
- async whichStore(stores, hash) {
1938
- let store = stores.pop();
1939
- store = globalThis[`${store}Store`];
1940
- if (store) {
1941
- const has = await store.has(hash);
1942
- if (has) return store
1943
- if (stores.length > 0) return this.whichStore(stores, hash)
1944
- } else return null
1945
- }
1946
-
1947
- /**
1948
- * Get content for given hash
1949
- *
1950
- * @param {String} hash
1951
- */
1952
- async get(hash, store) {
1953
- debug(`get ${hash}`);
1954
- let data;
1955
- if (store) store = globalThis[`${store}Store`];
1956
- if (!store) store = await this.whichStore([...this.stores], hash);
1957
- if (store && await store.has(hash)) data = await store.get(hash);
1958
- if (data) return data
1959
-
1960
- return this.requestData(hash, 'data')
1961
- }
1962
-
1963
- /**
1964
- * put content
1965
- *
1966
- * @param {String} hash
1967
- * @param {Buffer} data
1968
- */
1969
- async put(hash, data, store = 'data') {
1970
- store = globalThis[`${store}Store`];
1971
- return await store.put(hash, data)
1972
- }
1973
-
1974
- /**
1975
- * @param {String} hash
1976
- * @return {Boolean}
1977
- */
1978
- async has(hash) {
1979
- const store = await this.whichStore([...this.stores], hash);
1980
- if (store) {
1981
- if (store.private) return false
1982
- else return true
1983
- }
1984
- return false
1985
- }
1986
-
1987
- /**
1988
- *
1989
- * @param {String} topic
1990
- * @param {String|Object|Array|Boolean|Buffer} data
1991
- */
1992
- async publish(topic, data) {
1993
- // globalSub.publish(topic, data)
1994
- if (!Buffer.isBuffer(topic)) topic = Buffer.from(topic);
1995
- if (!Buffer.isBuffer(data)) data = Buffer.from(data);
1996
- const id = Math.random().toString(36).slice(-12);
1997
- data = new PsMessage({data, topic});
1998
- for (const peer of this.peers) {
1999
- if (peer.connection._connected) {
2000
- if (peer.id.toString() !== this.peerId.toString()) {
2001
- const node = await this.prepareMessage(peer.id, data.encoded);
2002
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2003
- }
2004
- } else {
2005
- this.removePeer(peer);
2006
- }
2007
- // TODO: if peer subscribed
2008
- }
2009
- }
2010
-
2011
- createHash(data, name) {
2012
- return new hash(data, {name})
2013
- }
2014
-
2015
- /**
2016
- *
2017
- * @param {String} topic
2018
- * @param {Method} cb
2019
- */
2020
- async subscribe(topic, cb) {
2021
- // TODO: if peer subscribed
2022
- globalSub.subscribe(topic, cb);
2023
- }
2024
-
2025
- async removePeer(peer) {
2026
- connections.delete(peer.id);
2027
- }
2028
-
2029
- get Buffer() {
2030
- return Buffer
2031
- }
2032
- // async block(index) {
2033
- // const _values = []
2034
- // for (const peer of this.peers) {
2035
- // const value = await peer.request({type: 'block', index})
2036
- // console.log(value);
2037
- // }
2038
- //
2039
- // }
1409
+ globalThis.leofcoin = globalThis.leofcoin || {};
1410
+ globalThis.globalSub = globalThis.globalSub || new PubSub__default['default']({verbose: true});
1411
+
1412
+ /**
1413
+ * @access public
1414
+ * @example
1415
+ * const peernet = new Peernet();
1416
+ */
1417
+ class Peernet {
1418
+ /**
1419
+ * @access public
1420
+ * @param {Object} options
1421
+ * @param {String} options.network - desired network
1422
+ * @param {String} options.root - path to root directory
1423
+ * @param {String} options.storePrefix - prefix for datatores (lfc)
1424
+ *
1425
+ * @return {Promise} instance of Peernet
1426
+ *
1427
+ * @example
1428
+ * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
1429
+ */
1430
+ constructor(options = {}) {
1431
+ this._discovered = [];
1432
+ /**
1433
+ * @property {String} network - current network
1434
+ */
1435
+ this.network = options.network || 'leofcoin';
1436
+ const parts = this.network.split(':');
1437
+
1438
+ if (!options.storePrefix) options.storePrefix = 'lfc';
1439
+ if (!options.port) options.port = 2000;
1440
+ if (!options.root) {
1441
+ if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
1442
+ else options.root = `.${this.network}/peernet`;
1443
+ }
1444
+ globalThis.peernet = this;
1445
+ return this._init(options)
1446
+ }
1447
+
1448
+ get defaultStores() {
1449
+ return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
1450
+ }
1451
+
1452
+ addProto(name, proto) {
1453
+ if (!this.protos[name]) this.protos[name] = proto;
1454
+ }
1455
+
1456
+ addCodec(name, codec) {
1457
+ if (!this.codecs[name]) this.codecs[name] = codec;
1458
+ }
1459
+
1460
+ async addStore(name, prefix, root, isPrivate = true) {
1461
+ if (name === 'block' || name === 'transaction' || name === 'chain' ||
1462
+ name === 'data' || name === 'message') isPrivate = false;
1463
+
1464
+ let Storage;
1465
+ if (this.hasDaemon) {
1466
+ Storage = LeofcoinStorageClient;
1467
+ } else {
1468
+ Storage = LeofcoinStorage$1;
1469
+ }
1470
+ globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
1471
+ await new Storage(`${prefix}-${name}`, root);
1472
+
1473
+ globalThis[`${name}Store`].private = isPrivate;
1474
+ if (!isPrivate) this.stores.push(name);
1475
+ }
1476
+
1477
+
1478
+ /**
1479
+ * @see MessageHandler
1480
+ */
1481
+ prepareMessage(to, data) {
1482
+ return this._messageHandler.prepareMessage(this.id, to, data)
1483
+ }
1484
+
1485
+ /**
1486
+ * @access public
1487
+ *
1488
+ * @return {Array} peerId
1489
+ */
1490
+ get peers() {
1491
+ return [...connections.values()]
1492
+ }
1493
+
1494
+ /**
1495
+ * @private
1496
+ *
1497
+ * @param {Object} options
1498
+ * @param {String} options.root - path to root directory
1499
+ *
1500
+ * @return {Promise} instance of Peernet
1501
+ */
1502
+ async _init(options) {
1503
+ // peernetDHT aka closesPeer by coordinates
1504
+ /**
1505
+ * @type {Object}
1506
+ * @property {Object} peer Instance of Peer
1507
+ */
1508
+ this.dht = new DhtEarth();
1509
+ /**
1510
+ * @type {Map}
1511
+ * @property {Object} peer Instance of Peer
1512
+ */
1513
+ this.peerMap = new Map();
1514
+ this.stores = [];
1515
+ this.requestProtos = {};
1516
+ this.storePrefix = options.storePrefix;
1517
+ this.root = options.root;
1518
+
1519
+ /**
1520
+ * proto Object containing protos
1521
+ * @type {Object}
1522
+ * @property {PeernetMessage} protos[peernet-message] messageNode
1523
+ * @property {DHTMessage} protos[peernet-dht] messageNode
1524
+ * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
1525
+ * @property {DataMessage} protos[peernet-data] messageNode
1526
+ * @property {DataMessageResponse} protos[peernet-data-response] messageNode
1527
+ */
1528
+ globalThis.peernet.protos = {
1529
+ 'peernet-request': request,
1530
+ 'peernet-response': response,
1531
+ 'peernet-peer': PeerMessage,
1532
+ 'peernet-peer-response': PeerMessageResponse,
1533
+ 'peernet-message': peernetMessage,
1534
+ 'peernet-dht': dht,
1535
+ 'peernet-dht-response': dhtResponse,
1536
+ 'peernet-data': DataMessage,
1537
+ 'peernet-data-response': DataMessageResponse,
1538
+ 'peernet-ps': PsMessage,
1539
+ 'chat-message': ChatMessage,
1540
+ };
1541
+
1542
+ this.protos = globalThis.peernet.protos;
1543
+ this.codecs = codec.codecs;
1544
+
1545
+ this._messageHandler = new MessageHandler(this.network);
1546
+
1547
+ const {daemon, environment} = await target();
1548
+ this.hasDaemon = daemon;
1549
+
1550
+ if (this.hasDaemon) {
1551
+ globalThis.peernet.client = await httpClient({
1552
+ protocol: 'peernet-v0.1.0', host: '127.0.0.1', port: options.port,
1553
+ });
1554
+ } else {
1555
+ if (environment !== 'browser') http(options);
1556
+ }
1557
+
1558
+ for (const store of this.defaultStores) {
1559
+ await this.addStore(store, options.storePrefix, options.root);
1560
+ }
1561
+
1562
+ try {
1563
+ const pub = await accountStore.get('public');
1564
+ this.id = pub.walletId;
1565
+ } catch (e) {
1566
+ if (e.code === 'ERR_NOT_FOUND') {
1567
+ const wallet = {};
1568
+ const {identity, accounts, config} = await generateAccount(this.network);
1569
+ wallet.identity = identity;
1570
+ wallet.accounts = accounts;
1571
+ wallet.version = 1;
1572
+ walletStore.put(wallet);
1573
+ await accountStore.put('config', config);
1574
+ await accountStore.put('public', {walletId: wallet.identity.walletId});
1575
+
1576
+ this.id = wallet.identity.walletId;
1577
+ } else {
1578
+ throw e
1579
+ }
1580
+ }
1581
+ this._peerHandler = new PeerDiscovery(this.id);
1582
+ // peernet id
1583
+ const id = Buffer.from(this.id.slice(0, 32));
1584
+ this.peerId = id;
1585
+
1586
+ pubsub.subscribe('peer:discovered', async (peer) => {
1587
+ peer.on('peernet.data', async (message) => {
1588
+ const id = message.id;
1589
+ message = new peernetMessage(Buffer.from(message.data.data));
1590
+ const proto = protoFor(message.decoded.data);
1591
+ await this._protoHandler({id, proto}, peer);
1592
+ });
1593
+ await this._peerHandler.discover(peer);
1594
+ const fulldId = this._getPeerId(peer.id);
1595
+ if (fulldId && this._discovered.indexOf(peer.id) === -1) {
1596
+ this._discovered.push(peer.id);
1597
+ pubsub.publish('peer:connected', peer);
1598
+ }
1599
+ });
1600
+ pubsub.subscribe('peer:disconnected', async (peer) => {
1601
+ let index = this._discovered.indexOf(peer.id);
1602
+ if (index !== -1) this._discovered.splice(index, 1);
1603
+ const id = this._getPeerId(peer.id);
1604
+ let peerIds = this.peerMap.get(id);
1605
+
1606
+ if (peerIds) {
1607
+ index = peerIds.indexOf(peer.id);
1608
+ if (index !== -1) peerIds.splice(index, 1);
1609
+ } else {
1610
+ peerIds = [];
1611
+ }
1612
+
1613
+ if (peerIds.length === 0) this.peerMap.delete(id);
1614
+ else this.peerMap.set(id, peerIds);
1615
+ });
1616
+ pubsub.subscribe('peer:connected', async (peer) => {
1617
+ console.log({connected: peer.id, as: this._getPeerId(peer.id) });
1618
+ // peer.on('peernet.data', async (message) => {
1619
+ // const id = message.id
1620
+ // message = new PeernetMessage(Buffer.from(message.data.data))
1621
+ // const proto = protoFor(message.decoded.data)
1622
+ // this._protoHandler({id, proto}, peer)
1623
+ // })
1624
+ });
1625
+
1626
+ /**
1627
+ * @access public
1628
+ * @type {PeernetClient}
1629
+ */
1630
+ this.client = new PeernetClient({...options, id});
1631
+ if (globalThis.onbeforeunload) {
1632
+ globalThisaddEventListener("beforeunload", async () => this.client.close());
1633
+ }
1634
+ return this
1635
+ }
1636
+
1637
+ _getPeerId(id) {
1638
+ for (const entry of [...this.peerMap.entries()]) {
1639
+ for (const _id of entry[1]) {
1640
+ if (_id === id) return entry[0]
1641
+ }
1642
+ }
1643
+ }
1644
+
1645
+ addRequestHandler(name, method) {
1646
+ this.requestProtos[name] = method;
1647
+ }
1648
+
1649
+ /**
1650
+ * @private
1651
+ *
1652
+ * @param {Buffer} message - peernet message
1653
+ * @param {PeernetPeer} peer - peernet peer
1654
+ */
1655
+ async _protoHandler(message, peer) {
1656
+ const {id, proto} = message;
1657
+ if (proto.name === 'peernet-peer') {
1658
+ const from = proto.decoded.id;
1659
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1660
+ else {
1661
+ const connections = this.peerMap.get(from);
1662
+ if (connections.indexOf(peer.id) === -1) {
1663
+ connections.push(peer.id);
1664
+ this.peerMap.set(from, connections);
1665
+ }
1666
+ }
1667
+ const data = new PeerMessageResponse({id: this.id});
1668
+ const node = await this.prepareMessage(from, data.encoded);
1669
+
1670
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1671
+ } else if (proto.name === 'peernet-peer-response') {
1672
+ const from = proto.decoded.id;
1673
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1674
+ else {
1675
+ const connections = this.peerMap.get(from);
1676
+ if (connections.indexOf(peer.id) === -1) {
1677
+ connections.push(peer.id);
1678
+ this.peerMap.set(from, connections);
1679
+ }
1680
+ }
1681
+ } else {
1682
+ let from = this._getPeerId(peer.id);
1683
+ if (!from) {
1684
+ const data = new PeerMessage({id: this.id});
1685
+ const node = await this.prepareMessage(peer.id, data.encoded);
1686
+
1687
+ let response = await peer.request(node.encoded);
1688
+ response = protoFor(response);
1689
+ response = new PeerMessageResponse(response.decoded.data);
1690
+
1691
+ from = response.decoded.id;
1692
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1693
+ else {
1694
+ const connections = this.peerMap.get(from);
1695
+ if (connections.indexOf(peer.id) === -1) {
1696
+ connections.push(peer.id);
1697
+ this.peerMap.set(from, connections);
1698
+ }
1699
+ }
1700
+ }
1701
+ if (proto.name === 'peernet-dht') {
1702
+ let { hash, store } = proto.decoded;
1703
+ let has;
1704
+
1705
+ if (!store) {
1706
+ has = await this.has(hash);
1707
+ } else {
1708
+ store = globalThis[`${store}Store`];
1709
+ if (store.private) has = false;
1710
+ else has = await store.has(hash);
1711
+ }
1712
+ const data = new dhtResponse({hash, has});
1713
+ const node = await this.prepareMessage(from, data.encoded);
1714
+
1715
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1716
+ } else if (proto.name === 'peernet-data') {
1717
+ let { hash, store } = proto.decoded;
1718
+ let data;
1719
+
1720
+ if (!store) {
1721
+ data = await this.get(hash);
1722
+ } else {
1723
+ store = globalThis[`${store}Store`];
1724
+ if (store.private) {
1725
+ // TODO: ban
1726
+ return
1727
+ } else data = await store.get(hash);
1728
+ }
1729
+
1730
+ if (data) {
1731
+ data = new DataMessageResponse({hash, data: data.decoded ? Buffer.from(JSON.stringify(data)) : Buffer.from(data)});
1732
+
1733
+ const node = await this.prepareMessage(from, data.encoded);
1734
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1735
+ }
1736
+ } else if (proto.name === 'peernet-peer') {
1737
+ const from = proto.decoded.id;
1738
+ if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1739
+ else {
1740
+ const connections = this.peerMap.get(from);
1741
+ connections.push(peer.id);
1742
+ this.peerMap.set(from, connections);
1743
+ }
1744
+ const data = new PeerMessage({id: this.id});
1745
+ const node = await this.prepareMessage(from, data.encoded);
1746
+
1747
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1748
+ } else if (proto.name === 'peernet-request') {
1749
+ // TODO: make dynamic
1750
+ // exposeddevapi[proto.decoded.request](proto.decoded.params)
1751
+ const method = this.requestProtos[proto.decoded.request];
1752
+ if (method) {
1753
+ const data = await method();
1754
+ const node = await this.prepareMessage(from, data.encoded);
1755
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
1756
+ }
1757
+ } else if (proto.name === 'peernet-ps' &&
1758
+ this._getPeerId(peer.id) !== this.id.toString()) {
1759
+ globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
1760
+ }
1761
+ }
1762
+ }
1763
+
1764
+ /**
1765
+ * performs a walk and resolves first encounter
1766
+ *
1767
+ * @param {String} hash
1768
+ */
1769
+ async walk(hash) {
1770
+ if (!hash) throw new Error('hash expected, received undefined')
1771
+ const data = new dht({hash});
1772
+ this.client.id;
1773
+ for (const peer of this.peers) {
1774
+ const node = await this.prepareMessage(peer.id, data.encoded);
1775
+
1776
+ const result = await peer.request(node.encoded);
1777
+
1778
+ let proto = protoFor(result.data);
1779
+
1780
+ if (proto.name !== 'peernet-message') throw encapsulatedError()
1781
+ const from = proto.decoded.from;
1782
+ proto = protoFor(proto.decoded.data);
1783
+
1784
+ if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
1785
+
1786
+ // TODO: give ip and port (just used for location)
1787
+ if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
1788
+ peer.connection.remoteFamily = 'ipv4';
1789
+ peer.connection.remoteAddress = '127.0.0.1';
1790
+ peer.connection.remotePort = '0000';
1791
+ }
1792
+
1793
+ const peerInfo = {
1794
+ family: peer.connection.remoteFamily || peer.connection.localFamily,
1795
+ address: peer.connection.remoteAddress || peer.connection.localAddress,
1796
+ port: peer.connection.remotePort || peer.connection.localPort,
1797
+ id: from,
1798
+ };
1799
+
1800
+ if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
1801
+ }
1802
+ return
1803
+ }
1804
+
1805
+ /**
1806
+ * Override DHT behavior, try's finding the content three times
1807
+ *
1808
+ * @param {String} hash
1809
+ */
1810
+ async providersFor(hash) {
1811
+ let providers = await this.dht.providersFor(hash);
1812
+ // walk the network to find a provider
1813
+ if (!providers || providers.length === 0) {
1814
+ await this.walk(hash);
1815
+ providers = await this.dht.providersFor(hash);
1816
+ // second walk the network to find a provider
1817
+ if (!providers || providers.length === 0) {
1818
+ await this.walk(hash);
1819
+ providers = await this.dht.providersFor(hash);
1820
+ }
1821
+ // last walk
1822
+ if (!providers || providers.length === 0) {
1823
+ await this.walk(hash);
1824
+ providers = await this.dht.providersFor(hash);
1825
+ }
1826
+ }
1827
+ // undefined if no providers given
1828
+ return providers
1829
+ }
1830
+
1831
+ get block() {
1832
+ return {
1833
+ get: async (hash) => {
1834
+ const data = await blockStore.has(hash);
1835
+ if (data) return await blockStore.get(hash)
1836
+ return this.requestData(hash)
1837
+ },
1838
+ put: async (hash, data) => {
1839
+ if (await blockStore.has(hash)) return
1840
+ return await blockStore.put(hash, data)
1841
+ },
1842
+ has: async (hash) => await blockStore.has(hash, 'block'),
1843
+ }
1844
+ }
1845
+
1846
+ get transaction() {
1847
+ return {
1848
+ get: async (hash) => {
1849
+ const data = await transactionStore.has(hash);
1850
+ if (data) return await transactionStore.get(hash)
1851
+ return this.requestData(hash, 'transaction')
1852
+ },
1853
+ put: async (hash, data) => {
1854
+ if (await transactionStore.has(hash)) return
1855
+ return await transactionStore.put(hash, data)
1856
+ },
1857
+ has: async (hash) => await transactionStore.has(hash),
1858
+ }
1859
+ }
1860
+
1861
+ async requestData(hash, store) {
1862
+ const providers = await this.providersFor(hash);
1863
+ if (!providers || providers.size === 0) throw nothingFoundError(hash)
1864
+ debug(`found ${providers.size} provider(s) for ${hash}`);
1865
+ // get closest peer on earth
1866
+ const closestPeer = await this.dht.closestPeer(providers);
1867
+ // get peer instance by id
1868
+ if (!closestPeer || !closestPeer.id) return this.requestData(hash, store)
1869
+
1870
+ const id = closestPeer.id.toString();
1871
+ if (this.peers) {
1872
+ let closest = this.peers.filter((peer) => {
1873
+ if (this._getPeerId(peer.id) === id) return peer
1874
+ });
1875
+
1876
+ let data = new DataMessage({hash, store});
1877
+
1878
+ const node = await this.prepareMessage(id, data.encoded);
1879
+ if (closest[0]) data = await closest[0].request(node.encoded);
1880
+ else {
1881
+ closest = this.peers.filter((peer) => {
1882
+ if (peer.id.toString() === id) return peer
1883
+ });
1884
+ if (closest[0]) data = await closest[0].request(node.encoded);
1885
+ }
1886
+ if (data.data) {
1887
+ let proto = protoFor(Buffer.from(data.data));
1888
+ proto = protoFor(proto.decoded.data);
1889
+ return proto.decoded.data
1890
+ }
1891
+
1892
+ // this.put(hash, proto.decoded.data)
1893
+ }
1894
+ return null
1895
+ }
1896
+
1897
+
1898
+ get message() {
1899
+ return {
1900
+ /**
1901
+ * Get content for given message hash
1902
+ *
1903
+ * @param {String} hash
1904
+ */
1905
+ get: async (hash) => {
1906
+ debug(`get message ${hash}`);
1907
+ const message = await messageStore.has(hash);
1908
+ if (message) return await messageStore.get(hash)
1909
+ return this.requestData(hash, 'message')
1910
+ },
1911
+ /**
1912
+ * put message content
1913
+ *
1914
+ * @param {String} hash
1915
+ * @param {Buffer} message
1916
+ */
1917
+ put: async (hash, message) => await messageStore.put(hash, message),
1918
+ /**
1919
+ * @param {String} hash
1920
+ * @return {Boolean}
1921
+ */
1922
+ has: async (hash) => await messageStore.has(hash),
1923
+ }
1924
+ }
1925
+
1926
+ get data() {
1927
+ return {
1928
+ /**
1929
+ * Get content for given data hash
1930
+ *
1931
+ * @param {String} hash
1932
+ */
1933
+ get: async (hash) => {
1934
+ debug(`get data ${hash}`);
1935
+ const data = await dataStore.has(hash);
1936
+ if (data) return await dataStore.get(hash)
1937
+ return this.requestData(hash, 'data')
1938
+ },
1939
+ /**
1940
+ * put data content
1941
+ *
1942
+ * @param {String} hash
1943
+ * @param {Buffer} data
1944
+ */
1945
+ put: async (hash, data) => await dataStore.put(hash, data),
1946
+ /**
1947
+ * @param {String} hash
1948
+ * @return {Boolean}
1949
+ */
1950
+ has: async (hash) => await dataStore.has(hash),
1951
+ }
1952
+ }
1953
+
1954
+ /**
1955
+ * goes trough given stores and tries to find data for given hash
1956
+ * @param {Array} stores
1957
+ * @param {string} hash
1958
+ */
1959
+ async whichStore(stores, hash) {
1960
+ let store = stores.pop();
1961
+ store = globalThis[`${store}Store`];
1962
+ if (store) {
1963
+ const has = await store.has(hash);
1964
+ if (has) return store
1965
+ if (stores.length > 0) return this.whichStore(stores, hash)
1966
+ } else return null
1967
+ }
1968
+
1969
+ /**
1970
+ * Get content for given hash
1971
+ *
1972
+ * @param {String} hash
1973
+ */
1974
+ async get(hash, store) {
1975
+ debug(`get ${hash}`);
1976
+ let data;
1977
+ if (store) store = globalThis[`${store}Store`];
1978
+ if (!store) store = await this.whichStore([...this.stores], hash);
1979
+ if (store && await store.has(hash)) data = await store.get(hash);
1980
+ if (data) return data
1981
+
1982
+ return this.requestData(hash, 'data')
1983
+ }
1984
+
1985
+ /**
1986
+ * put content
1987
+ *
1988
+ * @param {String} hash
1989
+ * @param {Buffer} data
1990
+ */
1991
+ async put(hash, data, store = 'data') {
1992
+ store = globalThis[`${store}Store`];
1993
+ return await store.put(hash, data)
1994
+ }
1995
+
1996
+ /**
1997
+ * @param {String} hash
1998
+ * @return {Boolean}
1999
+ */
2000
+ async has(hash) {
2001
+ const store = await this.whichStore([...this.stores], hash);
2002
+ if (store) {
2003
+ if (store.private) return false
2004
+ else return true
2005
+ }
2006
+ return false
2007
+ }
2008
+
2009
+ /**
2010
+ *
2011
+ * @param {String} topic
2012
+ * @param {String|Object|Array|Boolean|Buffer} data
2013
+ */
2014
+ async publish(topic, data) {
2015
+ // globalSub.publish(topic, data)
2016
+ if (!Buffer.isBuffer(topic)) topic = Buffer.from(topic);
2017
+ if (!Buffer.isBuffer(data)) data = Buffer.from(data);
2018
+ const id = Math.random().toString(36).slice(-12);
2019
+ data = new PsMessage({data, topic});
2020
+ for (const peer of this.peers) {
2021
+ if (peer.connection._connected) {
2022
+ if (peer.id.toString() !== this.peerId.toString()) {
2023
+ const node = await this.prepareMessage(peer.id, data.encoded);
2024
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
2025
+ }
2026
+ } else {
2027
+ this.removePeer(peer);
2028
+ }
2029
+ // TODO: if peer subscribed
2030
+ }
2031
+ }
2032
+
2033
+ createHash(data, name) {
2034
+ return new hash(data, {name})
2035
+ }
2036
+
2037
+ /**
2038
+ *
2039
+ * @param {String} topic
2040
+ * @param {Method} cb
2041
+ */
2042
+ async subscribe(topic, cb) {
2043
+ // TODO: if peer subscribed
2044
+ globalSub.subscribe(topic, cb);
2045
+ }
2046
+
2047
+ async removePeer(peer) {
2048
+ connections.delete(peer.id);
2049
+ }
2050
+
2051
+ get Buffer() {
2052
+ return Buffer
2053
+ }
2054
+ // async block(index) {
2055
+ // const _values = []
2056
+ // for (const peer of this.peers) {
2057
+ // const value = await peer.request({type: 'block', index})
2058
+ // console.log(value);
2059
+ // }
2060
+ //
2061
+ // }
2040
2062
  }
2041
2063
 
2042
2064
  module.exports = Peernet;