@leofcoin/peernet 0.11.0 → 0.11.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.
Files changed (38) hide show
  1. package/coverage/lcov-report/base.css +224 -0
  2. package/coverage/lcov-report/block-navigation.js +87 -0
  3. package/coverage/lcov-report/codec-format-interface.js.html +637 -0
  4. package/coverage/lcov-report/dht-response.js.html +193 -0
  5. package/coverage/lcov-report/favicon.png +0 -0
  6. package/coverage/lcov-report/index.html +131 -0
  7. package/coverage/lcov-report/prettify.css +1 -0
  8. package/coverage/lcov-report/prettify.js +2 -0
  9. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  10. package/coverage/lcov-report/sorter.js +196 -0
  11. package/coverage/lcov.info +199 -0
  12. package/dist/browser/peernet.js +1288 -1385
  13. package/dist/commonjs/{client-bd0caeb7.js → client-1a1f75e6.js} +41 -41
  14. package/dist/commonjs/{codec-4a768e5e.js → codec-8c8c652f.js} +118 -118
  15. package/dist/commonjs/codec-format-interface.js +167 -167
  16. package/dist/commonjs/codec.js +2 -2
  17. package/dist/commonjs/dht-response.js +11 -11
  18. package/dist/commonjs/dht.js +2 -2
  19. package/dist/commonjs/hash.js +149 -149
  20. package/dist/commonjs/{http-2b0735ef.js → http-7bbac90a.js} +1 -1
  21. package/dist/commonjs/peernet-message.js +2 -2
  22. package/dist/commonjs/peernet.js +843 -934
  23. package/dist/commonjs/request.js +2 -2
  24. package/dist/commonjs/response.js +2 -2
  25. package/dist/module/peernet.js +1357 -1448
  26. package/package.json +2 -18
  27. package/src/client.js +75 -75
  28. package/src/codec/codec-format-interface.js +172 -172
  29. package/src/codec/codec.js +124 -124
  30. package/src/dht/dht.js +121 -121
  31. package/src/discovery/peer-discovery.js +75 -75
  32. package/src/hash/hash.js +155 -155
  33. package/src/http/client/http-client.js +44 -44
  34. package/src/messages/dht-response.js +14 -14
  35. package/src/peer.js +67 -67
  36. package/src/peernet.js +612 -612
  37. package/src/proto/chat-message.proto.js +7 -7
  38. package/src/utils/utils.js +78 -78
@@ -9,7 +9,7 @@ var codecFormatInterface = require('./codec-format-interface.js');
9
9
  var request = require('./request.js');
10
10
  var response = require('./response.js');
11
11
  var fetch = require('node-fetch');
12
- var codec = require('./codec-4a768e5e.js');
12
+ var codec = require('./codec-8c8c652f.js');
13
13
  var hash = require('./hash.js');
14
14
  var generateAccount = require('@leofcoin/generate-account');
15
15
  var bs58check = require('bs58check');
@@ -25,7 +25,7 @@ require('crypto-js/sha512.js');
25
25
  var ENC = require('crypto-js/enc-utf8.js');
26
26
  require('@vandeurenglenn/base32');
27
27
  require('@vandeurenglenn/base58');
28
- require('is-hex');
28
+ require('@vandeurenglenn/is-hex');
29
29
 
30
30
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
31
31
 
@@ -755,12 +755,12 @@ class DataMessageResponse extends codecFormatInterface {
755
755
  }
756
756
  }
757
757
 
758
- var proto = `
759
- message ChatMessage {
760
- required string value = 1;
761
- required string author = 2;
762
- required uint64 timestamp = 3;
763
- repeated string files = 4;
758
+ var proto = `
759
+ message ChatMessage {
760
+ required string value = 1;
761
+ required string author = 2;
762
+ required uint64 timestamp = 3;
763
+ repeated string files = 4;
764
764
  }`;
765
765
 
766
766
  class ChatMessage extends codecFormatInterface {
@@ -774,259 +774,259 @@ class ChatMessage extends codecFormatInterface {
774
774
  }
775
775
  }
776
776
 
777
- const debug = (log) => {
778
- if (globalThis.DEBUG || globalThis.debug) console.log(`%c ${log}`, 'color: #0080ff;');
779
- };
780
-
781
- const protoFor = (data) => {
782
- if (!Buffer.isBuffer(data)) data = Buffer.from(data);
783
- const codec$1 = new codec.PeernetCodec(data);
784
- if (!codec$1.name) throw new Error('proto not found')
785
- const Proto = globalThis.peernet.protos[codec$1.name];
786
- if (!Proto) throw (new Error(`No proto defined for ${codec$1.name}`))
787
- return new Proto(data)
788
- };
789
-
790
- /**
791
- * wether or not a peernet daemon is active
792
- * @return {Boolean}
793
- */
794
- const hasDaemon = async () => {
795
- try {
796
- let response = await fetch__default["default"]('http://127.0.0.1:1000/api/version');
797
- response = await response.json();
798
- return Boolean(response.client === '@peernet/api/http')
799
- } catch (e) {
800
- return false
801
- }
802
- };
803
-
804
- const https = () => {
805
- if (!globalThis.location) return false;
806
- return Boolean(globalThis.location.protocol === 'https:')
807
- };
808
-
809
- /**
810
- * Get current environment
811
- * @return {String} current environment [node, electron, browser]
812
- */
813
- const environment = () => {
814
- const _navigator = globalThis.navigator;
815
- if (!_navigator) {
816
- return 'node'
817
- } else if (_navigator && /electron/i.test(_navigator.userAgent)) {
818
- return 'electron'
819
- } else {
820
- return 'browser'
821
- }
822
- };
823
-
824
- /**
825
- * * Get current environment
826
- * @return {Object} result
827
- * @property {Boolean} reult.daemon whether or not daemon is running
828
- * @property {Boolean} reult.environment Current environment
829
- */
830
- const target = async () => {
831
- let daemon = false;
832
- const env = await environment();
833
- if (!https()) daemon = await hasDaemon();
834
-
835
- return {daemon, environment: env}
777
+ const debug = (log) => {
778
+ if (globalThis.DEBUG || globalThis.debug) console.log(`%c ${log}`, 'color: #0080ff;');
779
+ };
780
+
781
+ const protoFor = (data) => {
782
+ if (!Buffer.isBuffer(data)) data = Buffer.from(data);
783
+ const codec$1 = new codec.PeernetCodec(data);
784
+ if (!codec$1.name) throw new Error('proto not found')
785
+ const Proto = globalThis.peernet.protos[codec$1.name];
786
+ if (!Proto) throw (new Error(`No proto defined for ${codec$1.name}`))
787
+ return new Proto(data)
788
+ };
789
+
790
+ /**
791
+ * wether or not a peernet daemon is active
792
+ * @return {Boolean}
793
+ */
794
+ const hasDaemon = async () => {
795
+ try {
796
+ let response = await fetch__default["default"]('http://127.0.0.1:1000/api/version');
797
+ response = await response.json();
798
+ return Boolean(response.client === '@peernet/api/http')
799
+ } catch (e) {
800
+ return false
801
+ }
802
+ };
803
+
804
+ const https = () => {
805
+ if (!globalThis.location) return false;
806
+ return Boolean(globalThis.location.protocol === 'https:')
807
+ };
808
+
809
+ /**
810
+ * Get current environment
811
+ * @return {String} current environment [node, electron, browser]
812
+ */
813
+ const environment = () => {
814
+ const _navigator = globalThis.navigator;
815
+ if (!_navigator) {
816
+ return 'node'
817
+ } else if (_navigator && /electron/i.test(_navigator.userAgent)) {
818
+ return 'electron'
819
+ } else {
820
+ return 'browser'
821
+ }
822
+ };
823
+
824
+ /**
825
+ * * Get current environment
826
+ * @return {Object} result
827
+ * @property {Boolean} reult.daemon whether or not daemon is running
828
+ * @property {Boolean} reult.environment Current environment
829
+ */
830
+ const target = async () => {
831
+ let daemon = false;
832
+ const env = await environment();
833
+ if (!https()) daemon = await hasDaemon();
834
+
835
+ return {daemon, environment: env}
836
836
  };
837
837
 
838
- class PeerDiscovery {
839
- constructor(id) {
840
- this.id = id;
841
- }
842
-
843
- _getPeerId(id) {
844
- if (!peernet.peerMap || peernet.peerMap && peernet.peerMap.size === 0) return false
845
-
846
- for (const entry of [...peernet.peerMap.entries()]) {
847
- for (const _id of entry[1]) {
848
- if (_id === id) return entry[0]
849
- }
850
- }
851
- }
852
-
853
- async discover(peer) {
854
- let id = this._getPeerId(peer.id);
855
- if (id) return id
856
- const data = new peernet.protos['peernet-peer']({id: this.id});
857
- const node = await peernet.prepareMessage(peer.id, data.encoded);
858
-
859
- let response = await peer.request(node.encoded);
860
- response = protoFor(response);
861
- response = new peernet.protos['peernet-peer-response'](response.decoded.data);
862
-
863
- id = response.decoded.id;
864
- if (id === this.id) return;
865
-
866
- if (!peernet.peerMap.has(id)) peernet.peerMap.set(id, [peer.id]);
867
- else {
868
- const connections = peernet.peerMap.get(id);
869
- if (connections.indexOf(peer.id) === -1) {
870
- connections.push(peer.id);
871
- peernet.peerMap.set(peer.id, connections);
872
- }
873
- }
874
- return id
875
- }
876
-
877
- async discoverHandler(message, peer) {
878
- const {id, proto} = message;
879
- // if (typeof message.data === 'string') message.data = Buffer.from(message.data)
880
- if (proto.name === 'peernet-peer') {
881
- const from = proto.decoded.id;
882
- if (from === this.id) return;
883
-
884
- if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
885
- else {
886
- const connections = peernet.peerMap.get(from);
887
- if (connections.indexOf(peer.id) === -1) {
888
- connections.push(peer.id);
889
- peernet.peerMap.set(from, connections);
890
- }
891
- }
892
- const data = new peernet.protos['peernet-peer-response']({id: this.id});
893
- const node = await peernet.prepareMessage(from, data.encoded);
894
-
895
- peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
896
- } else if (proto.name === 'peernet-peer-response') {
897
- const from = proto.decoded.id;
898
- if (from === this.id) return;
899
-
900
- if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
901
- else {
902
- const connections = peernet.peerMap.get(from);
903
- if (connections.indexOf(peer.id) === -1) {
904
- connections.push(peer.id);
905
- peernet.peerMap.set(from, connections);
906
- }
907
- }
908
- }
909
- }
838
+ class PeerDiscovery {
839
+ constructor(id) {
840
+ this.id = id;
841
+ }
842
+
843
+ _getPeerId(id) {
844
+ if (!peernet.peerMap || peernet.peerMap && peernet.peerMap.size === 0) return false
845
+
846
+ for (const entry of [...peernet.peerMap.entries()]) {
847
+ for (const _id of entry[1]) {
848
+ if (_id === id) return entry[0]
849
+ }
850
+ }
851
+ }
852
+
853
+ async discover(peer) {
854
+ let id = this._getPeerId(peer.id);
855
+ if (id) return id
856
+ const data = new peernet.protos['peernet-peer']({id: this.id});
857
+ const node = await peernet.prepareMessage(peer.id, data.encoded);
858
+
859
+ let response = await peer.request(node.encoded);
860
+ response = protoFor(response);
861
+ response = new peernet.protos['peernet-peer-response'](response.decoded.data);
862
+
863
+ id = response.decoded.id;
864
+ if (id === this.id) return;
865
+
866
+ if (!peernet.peerMap.has(id)) peernet.peerMap.set(id, [peer.id]);
867
+ else {
868
+ const connections = peernet.peerMap.get(id);
869
+ if (connections.indexOf(peer.id) === -1) {
870
+ connections.push(peer.id);
871
+ peernet.peerMap.set(peer.id, connections);
872
+ }
873
+ }
874
+ return id
875
+ }
876
+
877
+ async discoverHandler(message, peer) {
878
+ const {id, proto} = message;
879
+ // if (typeof message.data === 'string') message.data = Buffer.from(message.data)
880
+ if (proto.name === 'peernet-peer') {
881
+ const from = proto.decoded.id;
882
+ if (from === this.id) return;
883
+
884
+ if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
885
+ else {
886
+ const connections = peernet.peerMap.get(from);
887
+ if (connections.indexOf(peer.id) === -1) {
888
+ connections.push(peer.id);
889
+ peernet.peerMap.set(from, connections);
890
+ }
891
+ }
892
+ const data = new peernet.protos['peernet-peer-response']({id: this.id});
893
+ const node = await peernet.prepareMessage(from, data.encoded);
894
+
895
+ peer.write(Buffer.from(JSON.stringify({id, data: node.encoded})));
896
+ } else if (proto.name === 'peernet-peer-response') {
897
+ const from = proto.decoded.id;
898
+ if (from === this.id) return;
899
+
900
+ if (!peernet.peerMap.has(from)) peernet.peerMap.set(from, [peer.id]);
901
+ else {
902
+ const connections = peernet.peerMap.get(from);
903
+ if (connections.indexOf(peer.id) === -1) {
904
+ connections.push(peer.id);
905
+ peernet.peerMap.set(from, connections);
906
+ }
907
+ }
908
+ }
909
+ }
910
910
  }
911
911
 
912
- /**
913
- * Keep history of fetched address and ptr
914
- * @property {Object} address
915
- * @property {Object} ptr
916
- */
917
- const lastFetched = {
918
- address: {
919
- value: undefined,
920
- timestamp: 0,
921
- },
922
- ptr: {
923
- value: undefined,
924
- timestamp: 0,
925
- },
926
- };
927
-
928
- const getAddress = async () => {
929
- const {address} = lastFetched;
930
- const now = Math.round(new Date().getTime() / 1000);
931
- if (now - address.timestamp > 1200000) {
932
- address.value = await fetch__default["default"]('https://icanhazip.com/');
933
- address.value = await address.value.text();
934
- address.timestamp = Math.round(new Date().getTime() / 1000);
935
- lastFetched.address = address;
936
- }
937
-
938
- return address.value
939
- };
940
-
941
- const degreesToRadians = (degrees) => {
942
- return degrees * Math.PI / 180;
943
- };
944
-
945
- const distanceInKmBetweenEarthCoordinates = (lat1, lon1, lat2, lon2) => {
946
- const earthRadiusKm = 6371;
947
-
948
- const dLat = degreesToRadians(lat2-lat1);
949
- const dLon = degreesToRadians(lon2-lon1);
950
-
951
- lat1 = degreesToRadians(lat1);
952
- lat2 = degreesToRadians(lat2);
953
- const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
954
- Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
955
- const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
956
- return earthRadiusKm * c;
957
- };
958
-
959
- class DhtEarth {
960
- /**
961
- *
962
- */
963
- constructor() {
964
- this.providerMap = new Map();
965
- }
966
-
967
- /**
968
- * @param {Object} address
969
- * @return {Object} {latitude: lat, longitude: lon}
970
- */
971
- async getCoordinates(address) {
972
- // const {address} = parseAddress(provider)
973
- const request = `https://whereis.leofcoin.org/?ip=${address}`;
974
- let response = await fetch__default["default"](request);
975
- response = await response.json();
976
- const {lat, lon} = response;
977
- return {latitude: lat, longitude: lon}
978
- }
979
-
980
- /**
981
- * @param {Object} peer
982
- * @param {Object} provider
983
- * @return {Object} {provider, distance}
984
- */
985
- async getDistance(peer, provider) {
986
- const {latitude, longitude} = await this.getCoordinates(provider.address);
987
- return {provider, distance: distanceInKmBetweenEarthCoordinates(peer.latitude, peer.longitude, latitude, longitude)}
988
- }
989
-
990
- /**
991
- * @param {Array} providers
992
- * @return {Object} closestPeer
993
- */
994
- async closestPeer(providers) {
995
- let all = [];
996
- const address = await getAddress();
997
- const peerLoc = await this.getCoordinates(address);
998
-
999
- for (const provider of providers) {
1000
- if (provider.address === '127.0.0.1') all.push({provider, distance: 0});
1001
- else all.push(this.getDistance(peerLoc, provider));
1002
- }
1003
-
1004
- all = await Promise.all(all);
1005
- all = all.sort((previous, current) => previous.distance - current.distance);
1006
- return all[0].provider;
1007
- }
1008
-
1009
- /**
1010
- * @param {String} hash
1011
- * @return {Array} providers
1012
- */
1013
- providersFor(hash) {
1014
- return this.providerMap.get(hash);
1015
- }
1016
-
1017
- /**
1018
- * @param {String} address
1019
- * @param {String} hash
1020
- * @return {Array} providers
1021
- */
1022
- async addProvider(address, hash) {
1023
- let providers = [];
1024
- if (this.providerMap.has(hash)) providers = this.providerMap.get(hash);
1025
-
1026
- providers = new Set([...providers, address]);
1027
- this.providerMap.set(hash, providers);
1028
- return providers;
1029
- }
912
+ /**
913
+ * Keep history of fetched address and ptr
914
+ * @property {Object} address
915
+ * @property {Object} ptr
916
+ */
917
+ const lastFetched = {
918
+ address: {
919
+ value: undefined,
920
+ timestamp: 0,
921
+ },
922
+ ptr: {
923
+ value: undefined,
924
+ timestamp: 0,
925
+ },
926
+ };
927
+
928
+ const getAddress = async () => {
929
+ const {address} = lastFetched;
930
+ const now = Math.round(new Date().getTime() / 1000);
931
+ if (now - address.timestamp > 1200000) {
932
+ address.value = await fetch__default["default"]('https://icanhazip.com/');
933
+ address.value = await address.value.text();
934
+ address.timestamp = Math.round(new Date().getTime() / 1000);
935
+ lastFetched.address = address;
936
+ }
937
+
938
+ return address.value
939
+ };
940
+
941
+ const degreesToRadians = (degrees) => {
942
+ return degrees * Math.PI / 180;
943
+ };
944
+
945
+ const distanceInKmBetweenEarthCoordinates = (lat1, lon1, lat2, lon2) => {
946
+ const earthRadiusKm = 6371;
947
+
948
+ const dLat = degreesToRadians(lat2-lat1);
949
+ const dLon = degreesToRadians(lon2-lon1);
950
+
951
+ lat1 = degreesToRadians(lat1);
952
+ lat2 = degreesToRadians(lat2);
953
+ const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
954
+ Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
955
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
956
+ return earthRadiusKm * c;
957
+ };
958
+
959
+ class DhtEarth {
960
+ /**
961
+ *
962
+ */
963
+ constructor() {
964
+ this.providerMap = new Map();
965
+ }
966
+
967
+ /**
968
+ * @param {Object} address
969
+ * @return {Object} {latitude: lat, longitude: lon}
970
+ */
971
+ async getCoordinates(address) {
972
+ // const {address} = parseAddress(provider)
973
+ const request = `https://whereis.leofcoin.org/?ip=${address}`;
974
+ let response = await fetch__default["default"](request);
975
+ response = await response.json();
976
+ const {lat, lon} = response;
977
+ return {latitude: lat, longitude: lon}
978
+ }
979
+
980
+ /**
981
+ * @param {Object} peer
982
+ * @param {Object} provider
983
+ * @return {Object} {provider, distance}
984
+ */
985
+ async getDistance(peer, provider) {
986
+ const {latitude, longitude} = await this.getCoordinates(provider.address);
987
+ return {provider, distance: distanceInKmBetweenEarthCoordinates(peer.latitude, peer.longitude, latitude, longitude)}
988
+ }
989
+
990
+ /**
991
+ * @param {Array} providers
992
+ * @return {Object} closestPeer
993
+ */
994
+ async closestPeer(providers) {
995
+ let all = [];
996
+ const address = await getAddress();
997
+ const peerLoc = await this.getCoordinates(address);
998
+
999
+ for (const provider of providers) {
1000
+ if (provider.address === '127.0.0.1') all.push({provider, distance: 0});
1001
+ else all.push(this.getDistance(peerLoc, provider));
1002
+ }
1003
+
1004
+ all = await Promise.all(all);
1005
+ all = all.sort((previous, current) => previous.distance - current.distance);
1006
+ return all[0].provider;
1007
+ }
1008
+
1009
+ /**
1010
+ * @param {String} hash
1011
+ * @return {Array} providers
1012
+ */
1013
+ providersFor(hash) {
1014
+ return this.providerMap.get(hash);
1015
+ }
1016
+
1017
+ /**
1018
+ * @param {String} address
1019
+ * @param {String} hash
1020
+ * @return {Array} providers
1021
+ */
1022
+ async addProvider(address, hash) {
1023
+ let providers = [];
1024
+ if (this.providerMap.has(hash)) providers = this.providerMap.get(hash);
1025
+
1026
+ providers = new Set([...providers, address]);
1027
+ this.providerMap.set(hash, providers);
1028
+ return providers;
1029
+ }
1030
1030
  }
1031
1031
 
1032
1032
  var testnets = {
@@ -1479,689 +1479,598 @@ const nothingFoundError = (hash) => {
1479
1479
  return new Error(`nothing found for ${hash}`)
1480
1480
  };
1481
1481
 
1482
- globalThis.leofcoin = globalThis.leofcoin || {};
1483
- globalThis.globalSub = globalThis.globalSub || new PubSub({verbose: true});
1484
-
1485
- /**
1486
- * @access public
1487
- * @example
1488
- * const peernet = new Peernet();
1489
- */
1490
- class Peernet {
1491
- /**
1492
- * @access public
1493
- * @param {Object} options
1494
- * @param {String} options.network - desired network
1495
- * @param {String} options.root - path to root directory
1496
- * @param {String} options.storePrefix - prefix for datatores (lfc)
1497
- *
1498
- * @return {Promise} instance of Peernet
1499
- *
1500
- * @example
1501
- * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
1502
- */
1503
- constructor(options = {}) {
1504
- this._discovered = [];
1505
- /**
1506
- * @property {String} network - current network
1507
- */
1508
- this.network = options.network || 'leofcoin';
1509
- const parts = this.network.split(':');
1510
-
1511
- if (!options.storePrefix) options.storePrefix = 'lfc';
1512
- if (!options.port) options.port = 2000;
1513
- if (!options.root) {
1514
- if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
1515
- else options.root = `.${this.network}/peernet`;
1516
- }
1517
- globalThis.peernet = this;
1518
- this.bw = {
1519
- up: 0,
1520
- down: 0,
1521
- };
1522
- return this._init(options)
1523
- }
1524
-
1525
- get defaultStores() {
1526
- return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
1527
- }
1528
-
1529
- addProto(name, proto) {
1530
- if (!this.protos[name]) this.protos[name] = proto;
1531
- }
1532
-
1533
- addCodec(name, codec) {
1534
- if (!this.codecs[name]) this.codecs[name] = codec;
1535
- }
1536
-
1537
- async addStore(name, prefix, root, isPrivate = true) {
1538
- if (name === 'block' || name === 'transaction' || name === 'chain' ||
1539
- name === 'data' || name === 'message') isPrivate = false;
1540
-
1541
- let Storage;
1542
- if (this.hasDaemon) {
1543
- Storage = LeofcoinStorageClient;
1544
- } else {
1545
- Storage = LeofcoinStorage__default["default"];
1546
- }
1547
- globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
1548
- await new Storage(`${prefix}-${name}`, root);
1549
-
1550
- globalThis[`${name}Store`].private = isPrivate;
1551
- if (!isPrivate) this.stores.push(name);
1552
- }
1553
-
1554
-
1555
- /**
1556
- * @see MessageHandler
1557
- */
1558
- prepareMessage(to, data) {
1559
- return this._messageHandler.prepareMessage(this.id, to, data)
1560
- }
1561
-
1562
- /**
1563
- * @access public
1564
- *
1565
- * @return {Array} peerId
1566
- */
1567
- get peers() {
1568
- return [...connections.values()]
1569
- }
1570
-
1571
- /**
1572
- * @private
1573
- *
1574
- * @param {Object} options
1575
- * @param {String} options.root - path to root directory
1576
- *
1577
- * @return {Promise} instance of Peernet
1578
- */
1579
- async _init(options) {
1580
- // peernetDHT aka closesPeer by coordinates
1581
- /**
1582
- * @type {Object}
1583
- * @property {Object} peer Instance of Peer
1584
- */
1585
- this.dht = new DhtEarth();
1586
- /**
1587
- * @type {Map}
1588
- * @property {Object} peer Instance of Peer
1589
- */
1590
- this.peerMap = new Map();
1591
- this.stores = [];
1592
- this.requestProtos = {};
1593
- this.storePrefix = options.storePrefix;
1594
- this.root = options.root;
1595
-
1596
- /**
1597
- * proto Object containing protos
1598
- * @type {Object}
1599
- * @property {PeernetMessage} protos[peernet-message] messageNode
1600
- * @property {DHTMessage} protos[peernet-dht] messageNode
1601
- * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
1602
- * @property {DataMessage} protos[peernet-data] messageNode
1603
- * @property {DataMessageResponse} protos[peernet-data-response] messageNode
1604
- */
1605
- globalThis.peernet.protos = {
1606
- 'peernet-request': request,
1607
- 'peernet-response': response,
1608
- 'peernet-peer': PeerMessage,
1609
- 'peernet-peer-response': PeerMessageResponse,
1610
- 'peernet-message': peernetMessage,
1611
- 'peernet-dht': dht,
1612
- 'peernet-dht-response': dhtResponse,
1613
- 'peernet-data': DataMessage,
1614
- 'peernet-data-response': DataMessageResponse,
1615
- 'peernet-ps': PsMessage,
1616
- 'chat-message': ChatMessage,
1617
- };
1618
-
1619
- this.protos = globalThis.peernet.protos;
1620
- this.codecs = codec.codecs;
1621
-
1622
- this._messageHandler = new MessageHandler(this.network);
1623
-
1624
- const {daemon, environment} = await target();
1625
- this.hasDaemon = daemon;
1626
-
1482
+ globalThis.leofcoin = globalThis.leofcoin || {};
1483
+ globalThis.globalSub = globalThis.globalSub || new PubSub({verbose: true});
1484
+
1485
+ /**
1486
+ * @access public
1487
+ * @example
1488
+ * const peernet = new Peernet();
1489
+ */
1490
+ class Peernet {
1491
+ /**
1492
+ * @access public
1493
+ * @param {Object} options
1494
+ * @param {String} options.network - desired network
1495
+ * @param {String} options.root - path to root directory
1496
+ * @param {String} options.storePrefix - prefix for datatores (lfc)
1497
+ *
1498
+ * @return {Promise} instance of Peernet
1499
+ *
1500
+ * @example
1501
+ * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
1502
+ */
1503
+ constructor(options = {}) {
1504
+ this._discovered = [];
1505
+ /**
1506
+ * @property {String} network - current network
1507
+ */
1508
+ this.network = options.network || 'leofcoin';
1509
+ const parts = this.network.split(':');
1510
+
1511
+ if (!options.storePrefix) options.storePrefix = 'lfc';
1512
+ if (!options.port) options.port = 2000;
1513
+ if (!options.root) {
1514
+ if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
1515
+ else options.root = `.${this.network}/peernet`;
1516
+ }
1517
+ globalThis.peernet = this;
1518
+ this.bw = {
1519
+ up: 0,
1520
+ down: 0,
1521
+ };
1522
+ return this._init(options)
1523
+ }
1524
+
1525
+ get defaultStores() {
1526
+ return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
1527
+ }
1528
+
1529
+ addProto(name, proto) {
1530
+ if (!this.protos[name]) this.protos[name] = proto;
1531
+ }
1532
+
1533
+ addCodec(name, codec) {
1534
+ if (!this.codecs[name]) this.codecs[name] = codec;
1535
+ }
1536
+
1537
+ async addStore(name, prefix, root, isPrivate = true) {
1538
+ if (name === 'block' || name === 'transaction' || name === 'chain' ||
1539
+ name === 'data' || name === 'message') isPrivate = false;
1540
+
1541
+ let Storage;
1542
+ if (this.hasDaemon) {
1543
+ Storage = LeofcoinStorageClient;
1544
+ } else {
1545
+ Storage = LeofcoinStorage__default["default"];
1546
+ }
1547
+ globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
1548
+ await new Storage(`${prefix}-${name}`, root);
1549
+
1550
+ globalThis[`${name}Store`].private = isPrivate;
1551
+ if (!isPrivate) this.stores.push(name);
1552
+ }
1553
+
1554
+
1555
+ /**
1556
+ * @see MessageHandler
1557
+ */
1558
+ prepareMessage(to, data) {
1559
+ return this._messageHandler.prepareMessage(this.id, to, data)
1560
+ }
1561
+
1562
+ /**
1563
+ * @access public
1564
+ *
1565
+ * @return {Array} peerId
1566
+ */
1567
+ get peers() {
1568
+ return [...connections.values()]
1569
+ }
1570
+
1571
+ /**
1572
+ * @private
1573
+ *
1574
+ * @param {Object} options
1575
+ * @param {String} options.root - path to root directory
1576
+ *
1577
+ * @return {Promise} instance of Peernet
1578
+ */
1579
+ async _init(options) {
1580
+ // peernetDHT aka closesPeer by coordinates
1581
+ /**
1582
+ * @type {Object}
1583
+ * @property {Object} peer Instance of Peer
1584
+ */
1585
+ this.dht = new DhtEarth();
1586
+ /**
1587
+ * @type {Map}
1588
+ * @property {Object} peer Instance of Peer
1589
+ */
1590
+ this.peerMap = new Map();
1591
+ this.stores = [];
1592
+ this.requestProtos = {};
1593
+ this.storePrefix = options.storePrefix;
1594
+ this.root = options.root;
1595
+
1596
+ /**
1597
+ * proto Object containing protos
1598
+ * @type {Object}
1599
+ * @property {PeernetMessage} protos[peernet-message] messageNode
1600
+ * @property {DHTMessage} protos[peernet-dht] messageNode
1601
+ * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
1602
+ * @property {DataMessage} protos[peernet-data] messageNode
1603
+ * @property {DataMessageResponse} protos[peernet-data-response] messageNode
1604
+ */
1605
+ globalThis.peernet.protos = {
1606
+ 'peernet-request': request,
1607
+ 'peernet-response': response,
1608
+ 'peernet-peer': PeerMessage,
1609
+ 'peernet-peer-response': PeerMessageResponse,
1610
+ 'peernet-message': peernetMessage,
1611
+ 'peernet-dht': dht,
1612
+ 'peernet-dht-response': dhtResponse,
1613
+ 'peernet-data': DataMessage,
1614
+ 'peernet-data-response': DataMessageResponse,
1615
+ 'peernet-ps': PsMessage,
1616
+ 'chat-message': ChatMessage,
1617
+ };
1618
+
1619
+ this.protos = globalThis.peernet.protos;
1620
+ this.codecs = codec.codecs;
1621
+
1622
+ this._messageHandler = new MessageHandler(this.network);
1623
+
1624
+ const {daemon, environment} = await target();
1625
+ this.hasDaemon = daemon;
1626
+
1627
1627
  if (this.hasDaemon) {
1628
- const httpClient = await Promise.resolve().then(function () { return require('./client-bd0caeb7.js'); });
1628
+ const httpClient = await Promise.resolve().then(function () { return require('./client-1a1f75e6.js'); });
1629
1629
  globalThis.peernet.client = await httpClient.default({
1630
1630
  protocol: 'peernet-v0.1.0', host: '127.0.0.1', port: options.port
1631
1631
  });
1632
1632
  } else {
1633
- const http = await Promise.resolve().then(function () { return require('./http-2b0735ef.js'); });
1633
+ const http = await Promise.resolve().then(function () { return require('./http-7bbac90a.js'); });
1634
1634
  if (environment !== 'browser') http.default(options);
1635
- }
1636
-
1637
- for (const store of this.defaultStores) {
1638
- await this.addStore(store, options.storePrefix, options.root);
1639
- }
1640
-
1641
- try {
1642
- const pub = await accountStore.get('public');
1643
- this.id = pub.walletId;
1644
- } catch (e) {
1645
- if (e.code === 'ERR_NOT_FOUND') {
1646
- const wallet = {};
1647
- const {identity, accounts, config} = await generateAccount__default["default"](this.network);
1648
- wallet.identity = identity;
1649
- wallet.accounts = accounts;
1650
- wallet.version = 1;
1651
- walletStore.put(wallet);
1652
- await accountStore.put('config', config);
1653
- await accountStore.put('public', {walletId: wallet.identity.walletId});
1654
-
1655
- this.id = wallet.identity.walletId;
1656
- } else {
1657
- throw e
1658
- }
1659
- }
1660
- this._peerHandler = new PeerDiscovery(this.id);
1661
- this.peerId = this.id;
1662
-
1663
- // pubsub.subscribe('peer:discovered', async (peer) => {
1664
- // peer.on('peernet.data', async (message) => {
1665
- // const id = message.id;
1666
- // message = new PeernetMessage(Buffer.from(message.data.data));
1667
- // const proto = protoFor(message.decoded.data);
1668
- // await this._protoHandler({id, proto}, peer);
1669
- // });
1670
- // await this._peerHandler.discover(peer);
1671
- // const fulldId = this._getPeerId(peer.id);
1672
- // if (fulldId && this._discovered.indexOf(peer.id) === -1) {
1673
- // this._discovered.push(peer.id);
1674
- // pubsub.publish('peer:connected', peer);
1675
- // }
1676
- // });
1677
- // pubsub.subscribe('peer:disconnected', async (peer) => {
1678
- // let index = this._discovered.indexOf(peer.id)
1679
- // if (index !== -1) this._discovered.splice(index, 1)
1680
- // const id = this._getPeerId(peer.id)
1681
- // let peerIds = this.peerMap.get(id)
1682
- //
1683
- // if (peerIds) {
1684
- // index = peerIds.indexOf(peer.id)
1685
- // if (index !== -1) peerIds.splice(index, 1)
1686
- // } else {
1687
- // peerIds = []
1688
- // }
1689
- //
1690
- // if (peerIds.length === 0) this.peerMap.delete(id)
1691
- // else this.peerMap.set(id, peerIds)
1692
- // })
1693
- pubsub.subscribe('peer:connected', async (peer) => {
1694
- console.log(peer);
1695
- // console.log({connected: peer.id, as: this._getPeerId(peer.id) });
1696
- // peer.on('peernet.data', async (message) => {
1697
- // const id = message.id
1698
- // message = new PeernetMessage(Buffer.from(message.data.data))
1699
- // const proto = protoFor(message.decoded.data)
1700
- // this._protoHandler({id, proto}, peer)
1701
- // })
1702
- });
1703
-
1704
- pubsub.subscribe('peer:data', async message => {
1705
- console.log({message});
1706
- if (!message.data) return
1707
- const {id, data} = JSON.parse(new TextDecoder().decode(message.data));
1708
- const uint8Array = new Uint8Array(Object.keys(data).length);
1709
- for (var i = 0; i < Object.keys(data).length; i++) {
1710
- uint8Array[i] = data[i];
1711
- }
1712
- message = new peernetMessage(uint8Array);
1713
- const proto = protoFor(message.decoded.data);
1714
-
1715
- console.log(message.decoded);
1716
- const from = new TextDecoder().decode(message.decoded.from);
1717
- this._protoHandler({id, proto}, this.client.connections[from], from);
1718
- });
1719
-
1720
- /**
1721
- * @access public
1722
- * @type {PeernetClient}
1723
- */
1724
- this.client = new Client(this.id);
1725
- if (globalThis.onbeforeunload) {
1726
- globalThis.addEventListener('beforeunload', async () => this.client.close());
1727
- }
1728
- return this
1729
- }
1730
-
1731
- _getPeerId(id) {
1732
- for (const entry of [...this.peerMap.entries()]) {
1733
- for (const _id of entry[1]) {
1734
- if (_id === id) return entry[0]
1735
- }
1736
- }
1737
- }
1738
-
1739
- addRequestHandler(name, method) {
1740
- this.requestProtos[name] = method;
1741
- }
1742
-
1743
- /**
1744
- * @private
1745
- *
1746
- * @param {Buffer} message - peernet message
1747
- * @param {PeernetPeer} peer - peernet peer
1748
- */
1749
- async _protoHandler(message, peer, from) {
1750
- const {id, proto} = message;
1751
- console.log(message);
1752
- this.bw.down += proto.encoded.length;
1753
- // if (proto.name === 'peernet-peer') {
1754
- // const from = proto.decoded.id
1755
- // if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id])
1756
- // else {
1757
- // const connections = this.peerMap.get(from)
1758
- // if (connections.indexOf(peer.id) === -1) {
1759
- // connections.push(peer.id)
1760
- // this.peerMap.set(from, connections)
1761
- // }
1762
- // }
1763
- // const data = new PeerMessageResponse({id: this.id})
1764
- // const node = await this.prepareMessage(from, data.encoded)
1765
- //
1766
- // peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})))
1767
- // this.bw.up += node.encoded.length
1768
- // } else if (proto.name === 'peernet-peer-response') {
1769
- // const from = proto.decoded.id
1770
- // if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id])
1771
- // else {
1772
- // const connections = this.peerMap.get(from)
1773
- // if (connections.indexOf(peer.id) === -1) {
1774
- // connections.push(peer.id)
1775
- // this.peerMap.set(from, connections)
1776
- // }
1777
- // }
1778
- // } else {
1779
- // let from = this._getPeerId(peer.id)
1780
- // if (!from) {
1781
- // const data = new PeerMessage({id: this.id})
1782
- // const node = await this.prepareMessage(peer.id, data.encoded)
1783
- // this.bw.up += node.encoded.length
1784
- // let response = await peer.request(node.encoded)
1785
- // response = protoFor(response)
1786
- //
1787
- // response = new PeerMessageResponse(response.decoded.data)
1788
- //
1789
- // from = response.decoded.id
1790
- // if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id])
1791
- // else {
1792
- // const connections = this.peerMap.get(from)
1793
- // if (connections.indexOf(peer.id) === -1) {
1794
- // connections.push(peer.id)
1795
- // this.peerMap.set(from, connections)
1796
- // }
1797
- // }
1798
- // }
1799
- if (proto.name === 'peernet-dht') {
1800
- let { hash, store } = proto.decoded;
1801
- let has;
1802
-
1803
- if (!store) {
1804
- has = await this.has(hash);
1805
- } else {
1806
- store = globalThis[`${store}Store`];
1807
- if (store.private) has = false;
1808
- else has = await store.has(hash);
1809
- }
1810
- const data = new dhtResponse({hash, has});
1811
- const node = await this.prepareMessage(from, data.encoded);
1812
-
1813
- peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
1814
- this.bw.up += node.encoded.length;
1815
- } else if (proto.name === 'peernet-data') {
1816
- let { hash, store } = proto.decoded;
1817
- let data;
1818
- if (!store) {
1819
- store = await this.whichStore([...this.stores], hash);
1820
- } else {
1821
- store = globalThis[`${store}Store`];
1822
- }
1823
- if (store && !store.private) {
1824
- data = await store.get(hash);
1825
-
1826
- if (data) {
1827
- data = new DataMessageResponse({hash, data: data.decoded ? Buffer.from(JSON.stringify(data)) : Buffer.from(data)});
1828
-
1829
- const node = await this.prepareMessage(from, data.encoded);
1830
- peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
1831
- this.bw.up += node.encoded.length;
1832
- }
1833
- }
1834
-
1835
- } else if (proto.name === 'peernet-peer') {
1836
- const from = proto.decoded.id;
1837
- if (!this.peerMap.has(from)) this.peerMap.set(from, [peer.id]);
1838
- else {
1839
- const connections = this.peerMap.get(from);
1840
- connections.push(peer.id);
1841
- this.peerMap.set(from, connections);
1842
- }
1843
- const data = new PeerMessage({id: this.id});
1844
- const node = await this.prepareMessage(from, data.encoded);
1845
-
1846
- peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
1847
- this.bw.up += node.encoded.length;
1848
- } else if (proto.name === 'peernet-request') {
1849
- // TODO: make dynamic
1850
- // exposeddevapi[proto.decoded.request](proto.decoded.params)
1851
- const method = this.requestProtos[proto.decoded.request];
1852
- if (method) {
1853
- const data = await method();
1854
- const node = await this.prepareMessage(from, data.encoded);
1855
- peer.send(new TextEncoder().encode(JSON.stringify({id, data: node.encoded})));
1856
- this.bw.up += node.encoded.length;
1857
- }
1858
- } else if (proto.name === 'peernet-ps' &&
1859
- this._getPeerId(peer.id) !== this.id.toString()) {
1860
- globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
1861
- }
1862
- // }
1863
- }
1864
-
1865
- /**
1866
- * performs a walk and resolves first encounter
1867
- *
1868
- * @param {String} hash
1869
- */
1870
- async walk(hash) {
1871
- if (!hash) throw new Error('hash expected, received undefined')
1872
- const data = new dht({hash});
1873
- this.client.id;
1874
- for (const peer of this.peers) {
1875
- const node = await this.prepareMessage(peer.id, data.encoded);
1876
-
1877
- const result = await peer.request(node.encoded);
1878
-
1879
- let proto = protoFor(result.data);
1880
-
1881
- if (proto.name !== 'peernet-message') throw encapsulatedError()
1882
- const from = proto.decoded.from;
1883
- proto = protoFor(proto.decoded.data);
1884
-
1885
- if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
1886
-
1887
- // TODO: give ip and port (just used for location)
1888
- if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
1889
- peer.connection.remoteFamily = 'ipv4';
1890
- peer.connection.remoteAddress = '127.0.0.1';
1891
- peer.connection.remotePort = '0000';
1892
- }
1893
-
1894
- const peerInfo = {
1895
- family: peer.connection.remoteFamily || peer.connection.localFamily,
1896
- address: peer.connection.remoteAddress || peer.connection.localAddress,
1897
- port: peer.connection.remotePort || peer.connection.localPort,
1898
- id: from,
1899
- };
1900
-
1901
- if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
1902
- }
1903
- return
1904
- }
1905
-
1906
- /**
1907
- * Override DHT behavior, try's finding the content three times
1908
- *
1909
- * @param {String} hash
1910
- */
1911
- async providersFor(hash) {
1912
- let providers = await this.dht.providersFor(hash);
1913
- // walk the network to find a provider
1914
- if (!providers || providers.length === 0) {
1915
- await this.walk(hash);
1916
- providers = await this.dht.providersFor(hash);
1917
- // second walk the network to find a provider
1918
- if (!providers || providers.length === 0) {
1919
- await this.walk(hash);
1920
- providers = await this.dht.providersFor(hash);
1921
- }
1922
- // last walk
1923
- if (!providers || providers.length === 0) {
1924
- await this.walk(hash);
1925
- providers = await this.dht.providersFor(hash);
1926
- }
1927
- }
1928
- // undefined if no providers given
1929
- return providers
1930
- }
1931
-
1932
- get block() {
1933
- return {
1934
- get: async (hash) => {
1935
- const data = await blockStore.has(hash);
1936
- if (data) return await blockStore.get(hash)
1937
- return this.requestData(hash, 'block')
1938
- },
1939
- put: async (hash, data) => {
1940
- if (await blockStore.has(hash)) return
1941
- return await blockStore.put(hash, data)
1942
- },
1943
- has: async (hash) => await blockStore.has(hash, 'block'),
1944
- }
1945
- }
1946
-
1947
- get transaction() {
1948
- return {
1949
- get: async (hash) => {
1950
- const data = await transactionStore.has(hash);
1951
- if (data) return await transactionStore.get(hash)
1952
- return this.requestData(hash, 'transaction')
1953
- },
1954
- put: async (hash, data) => {
1955
- if (await transactionStore.has(hash)) return
1956
- return await transactionStore.put(hash, data)
1957
- },
1958
- has: async (hash) => await transactionStore.has(hash),
1959
- }
1960
- }
1961
-
1962
- async requestData(hash, store) {
1963
- const providers = await this.providersFor(hash);
1964
- if (!providers || providers.size === 0) throw nothingFoundError(hash)
1965
- debug(`found ${providers.size} provider(s) for ${hash}`);
1966
- // get closest peer on earth
1967
- const closestPeer = await this.dht.closestPeer(providers);
1968
- // get peer instance by id
1969
- if (!closestPeer || !closestPeer.id) return this.requestData(hash, store.name ? store.name : store)
1970
-
1971
- const id = closestPeer.id.toString();
1972
- if (this.peers) {
1973
- let closest = this.peers.filter((peer) => {
1974
- if (this._getPeerId(peer.id) === id) return peer
1975
- });
1976
-
1977
- let data = new DataMessage({hash, store: store.name ? store.name : store});
1978
-
1979
- const node = await this.prepareMessage(id, data.encoded);
1980
- if (closest[0]) data = await closest[0].request(node.encoded);
1981
- else {
1982
- closest = this.peers.filter((peer) => {
1983
- if (peer.id.toString() === id) return peer
1984
- });
1985
- if (closest[0]) data = await closest[0].request(node.encoded);
1986
- }
1987
- if (data.data) {
1988
- let proto = protoFor(Buffer.from(data.data));
1989
- proto = protoFor(proto.decoded.data);
1990
- return proto.decoded.data
1991
- }
1992
-
1993
- // this.put(hash, proto.decoded.data)
1994
- }
1995
- return null
1996
- }
1997
-
1998
-
1999
- get message() {
2000
- return {
2001
- /**
2002
- * Get content for given message hash
2003
- *
2004
- * @param {String} hash
2005
- */
2006
- get: async (hash) => {
2007
- debug(`get message ${hash}`);
2008
- const message = await messageStore.has(hash);
2009
- if (message) return await messageStore.get(hash)
2010
- return this.requestData(hash, 'message')
2011
- },
2012
- /**
2013
- * put message content
2014
- *
2015
- * @param {String} hash
2016
- * @param {Buffer} message
2017
- */
2018
- put: async (hash, message) => await messageStore.put(hash, message),
2019
- /**
2020
- * @param {String} hash
2021
- * @return {Boolean}
2022
- */
2023
- has: async (hash) => await messageStore.has(hash),
2024
- }
2025
- }
2026
-
2027
- get data() {
2028
- return {
2029
- /**
2030
- * Get content for given data hash
2031
- *
2032
- * @param {String} hash
2033
- */
2034
- get: async (hash) => {
2035
- debug(`get data ${hash}`);
2036
- const data = await dataStore.has(hash);
2037
- if (data) return await dataStore.get(hash)
2038
- return this.requestData(hash, 'data')
2039
- },
2040
- /**
2041
- * put data content
2042
- *
2043
- * @param {String} hash
2044
- * @param {Buffer} data
2045
- */
2046
- put: async (hash, data) => await dataStore.put(hash, data),
2047
- /**
2048
- * @param {String} hash
2049
- * @return {Boolean}
2050
- */
2051
- has: async (hash) => await dataStore.has(hash),
2052
- }
2053
- }
2054
-
2055
- /**
2056
- * goes trough given stores and tries to find data for given hash
2057
- * @param {Array} stores
2058
- * @param {string} hash
2059
- */
2060
- async whichStore(stores, hash) {
2061
- let store = stores.pop();
2062
- store = globalThis[`${store}Store`];
2063
- if (store) {
2064
- const has = await store.has(hash);
2065
- if (has) return store
2066
- if (stores.length > 0) return this.whichStore(stores, hash)
2067
- } else return null
2068
- }
2069
-
2070
- /**
2071
- * Get content for given hash
2072
- *
2073
- * @param {String} hash - the hash of the wanted data
2074
- * @param {String} store - storeName to access
2075
- */
2076
- async get(hash, store) {
2077
- debug(`get ${hash}`);
2078
- let data;
2079
- if (store) store = globalThis[`${store}Store`];
2080
- if (!store) store = await this.whichStore([...this.stores], hash);
2081
- if (store && await store.has(hash)) data = await store.get(hash);
2082
- if (data) return data
2083
-
2084
- return this.requestData(hash, store.name ? store.name : store)
2085
- }
2086
-
2087
- /**
2088
- * put content
2089
- *
2090
- * @param {String} hash
2091
- * @param {Buffer} data
2092
- * @param {String} store - storeName to access
2093
- */
2094
- async put(hash, data, store = 'data') {
2095
- store = globalThis[`${store}Store`];
2096
- return store.put(hash, data)
2097
- }
2098
-
2099
- /**
2100
- * @param {String} hash
2101
- * @return {Boolean}
2102
- */
2103
- async has(hash) {
2104
- const store = await this.whichStore([...this.stores], hash);
2105
- if (store) {
2106
- if (store.private) return false
2107
- else return true
2108
- }
2109
- return false
2110
- }
2111
-
2112
- /**
2113
- *
2114
- * @param {String} topic
2115
- * @param {String|Object|Array|Boolean|Buffer} data
2116
- */
2117
- async publish(topic, data) {
2118
- // globalSub.publish(topic, data)
2119
- if (!Buffer.isBuffer(topic)) topic = Buffer.from(topic);
2120
- if (!Buffer.isBuffer(data)) data = Buffer.from(data);
2121
- const id = Math.random().toString(36).slice(-12);
2122
- data = new PsMessage({data, topic});
2123
- for (const peer of this.peers) {
2124
- if (peer.connection._connected) {
2125
- if (peer.id.toString() !== this.peerId.toString()) {
2126
- const node = await this.prepareMessage(peer.id, data.encoded);
2127
- peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
2128
- }
2129
- } else {
2130
- this.removePeer(peer);
2131
- }
2132
- // TODO: if peer subscribed
2133
- }
2134
- }
2135
-
2136
- createHash(data, name) {
2137
- return new hash(data, {name})
2138
- }
2139
-
2140
- /**
2141
- *
2142
- * @param {String} topic
2143
- * @param {Method} cb
2144
- */
2145
- async subscribe(topic, cb) {
2146
- // TODO: if peer subscribed
2147
- globalSub.subscribe(topic, cb);
2148
- }
2149
-
2150
- async removePeer(peer) {
2151
- connections.delete(peer.id);
2152
- }
2153
-
2154
- get Buffer() {
2155
- return Buffer
2156
- }
2157
- // async block(index) {
2158
- // const _values = []
2159
- // for (const peer of this.peers) {
2160
- // const value = await peer.request({type: 'block', index})
2161
- // console.log(value);
2162
- // }
2163
- //
2164
- // }
1635
+ }
1636
+
1637
+ for (const store of this.defaultStores) {
1638
+ await this.addStore(store, options.storePrefix, options.root);
1639
+ }
1640
+
1641
+ try {
1642
+ const pub = await accountStore.get('public');
1643
+ this.id = pub.walletId;
1644
+ } catch (e) {
1645
+ if (e.code === 'ERR_NOT_FOUND') {
1646
+ const wallet = {};
1647
+ const {identity, accounts, config} = await generateAccount__default["default"](this.network);
1648
+ wallet.identity = identity;
1649
+ wallet.accounts = accounts;
1650
+ wallet.version = 1;
1651
+ walletStore.put(wallet);
1652
+ await accountStore.put('config', config);
1653
+ await accountStore.put('public', {walletId: wallet.identity.walletId});
1654
+
1655
+ this.id = wallet.identity.walletId;
1656
+ } else {
1657
+ throw e
1658
+ }
1659
+ }
1660
+ this._peerHandler = new PeerDiscovery(this.id);
1661
+ this.peerId = this.id;
1662
+
1663
+ pubsub.subscribe('peer:connected', async (peer) => {
1664
+ console.log(peer);
1665
+ // console.log({connected: peer.id, as: this._getPeerId(peer.id) });
1666
+ // peer.on('peernet.data', async (message) => {
1667
+ // const id = message.id
1668
+ // message = new PeernetMessage(Buffer.from(message.data.data))
1669
+ // const proto = protoFor(message.decoded.data)
1670
+ // this._protoHandler({id, proto}, peer)
1671
+ // })
1672
+ });
1673
+
1674
+ pubsub.subscribe('peer:data', async message => {
1675
+ if (!message.data) return
1676
+ const {id, data} = JSON.parse(new TextDecoder().decode(message.data));
1677
+ const uint8Array = new Uint8Array(Object.keys(data).length);
1678
+ for (var i = 0; i < Object.keys(data).length; i++) {
1679
+ uint8Array[i] = data[i];
1680
+ }
1681
+ message = new peernetMessage(uint8Array);
1682
+ const proto = protoFor(message.decoded.data);
1683
+
1684
+ const from = new TextDecoder().decode(message.decoded.from);
1685
+ this._protoHandler({id, proto}, this.client.connections[from], from);
1686
+ });
1687
+
1688
+ /**
1689
+ * @access public
1690
+ * @type {PeernetClient}
1691
+ */
1692
+ this.client = new Client(this.id);
1693
+ if (globalThis.onbeforeunload) {
1694
+ globalThis.addEventListener('beforeunload', async () => this.client.close());
1695
+ }
1696
+ return this
1697
+ }
1698
+
1699
+ _getPeerId(id) {
1700
+ for (const entry of [...this.peerMap.entries()]) {
1701
+ for (const _id of entry[1]) {
1702
+ if (_id === id) return entry[0]
1703
+ }
1704
+ }
1705
+ }
1706
+
1707
+ addRequestHandler(name, method) {
1708
+ this.requestProtos[name] = method;
1709
+ }
1710
+
1711
+ /**
1712
+ * @private
1713
+ *
1714
+ * @param {Buffer} message - peernet message
1715
+ * @param {PeernetPeer} peer - peernet peer
1716
+ */
1717
+ async _protoHandler(message, peer, from) {
1718
+ const {id, proto} = message;
1719
+ this.bw.down += proto.encoded.length;
1720
+
1721
+ if (proto.name === 'peernet-dht') {
1722
+ let { hash, store } = proto.decoded;
1723
+ let has;
1724
+
1725
+ if (!store) {
1726
+ has = await this.has(hash);
1727
+ } else {
1728
+ store = globalThis[`${store}Store`];
1729
+ if (store.private) has = false;
1730
+ else has = await store.has(hash);
1731
+ }
1732
+ const data = new dhtResponse({hash, has});
1733
+ const node = await this.prepareMessage(from, data.encoded);
1734
+
1735
+ peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
1736
+ this.bw.up += node.encoded.length;
1737
+ } else if (proto.name === 'peernet-data') {
1738
+ let { hash, store } = proto.decoded;
1739
+ let data;
1740
+ if (!store) {
1741
+ store = await this.whichStore([...this.stores], hash);
1742
+ } else {
1743
+ store = globalThis[`${store}Store`];
1744
+ }
1745
+ if (store && !store.private) {
1746
+ data = await store.get(hash);
1747
+
1748
+ if (data) {
1749
+ data = new DataMessageResponse({hash, data: data.decoded ? Buffer.from(JSON.stringify(data)) : Buffer.from(data)});
1750
+
1751
+ const node = await this.prepareMessage(from, data.encoded);
1752
+ peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
1753
+ this.bw.up += node.encoded.length;
1754
+ }
1755
+ }
1756
+
1757
+ } else if (proto.name === 'peernet-request') {
1758
+ // TODO: make dynamic
1759
+ // exposeddevapi[proto.decoded.request](proto.decoded.params)
1760
+ const method = this.requestProtos[proto.decoded.request];
1761
+ if (method) {
1762
+ const data = await method();
1763
+ const node = await this.prepareMessage(from, data.encoded);
1764
+ peer.send(new TextEncoder().encode(JSON.stringify({id, data: node.encoded})));
1765
+ this.bw.up += node.encoded.length;
1766
+ }
1767
+ } else if (proto.name === 'peernet-ps' &&
1768
+ this._getPeerId(peer.id) !== this.id.toString()) {
1769
+ globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
1770
+ }
1771
+ // }
1772
+ }
1773
+
1774
+ /**
1775
+ * performs a walk and resolves first encounter
1776
+ *
1777
+ * @param {String} hash
1778
+ */
1779
+ async walk(hash) {
1780
+ if (!hash) throw new Error('hash expected, received undefined')
1781
+ const data = new dht({hash});
1782
+ this.client.id;
1783
+ for (const peer of this.peers) {
1784
+ const node = await this.prepareMessage(peer.id, data.encoded);
1785
+
1786
+ const result = await peer.request(node.encoded);
1787
+
1788
+ let proto = protoFor(result.data);
1789
+
1790
+ if (proto.name !== 'peernet-message') throw encapsulatedError()
1791
+ const from = proto.decoded.from;
1792
+ proto = protoFor(proto.decoded.data);
1793
+
1794
+ if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
1795
+
1796
+ // TODO: give ip and port (just used for location)
1797
+ if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
1798
+ peer.connection.remoteFamily = 'ipv4';
1799
+ peer.connection.remoteAddress = '127.0.0.1';
1800
+ peer.connection.remotePort = '0000';
1801
+ }
1802
+
1803
+ const peerInfo = {
1804
+ family: peer.connection.remoteFamily || peer.connection.localFamily,
1805
+ address: peer.connection.remoteAddress || peer.connection.localAddress,
1806
+ port: peer.connection.remotePort || peer.connection.localPort,
1807
+ id: from,
1808
+ };
1809
+
1810
+ if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
1811
+ }
1812
+ return
1813
+ }
1814
+
1815
+ /**
1816
+ * Override DHT behavior, try's finding the content three times
1817
+ *
1818
+ * @param {String} hash
1819
+ */
1820
+ async providersFor(hash) {
1821
+ let providers = await this.dht.providersFor(hash);
1822
+ // walk the network to find a provider
1823
+ if (!providers || providers.length === 0) {
1824
+ await this.walk(hash);
1825
+ providers = await this.dht.providersFor(hash);
1826
+ // second walk the network to find a provider
1827
+ if (!providers || providers.length === 0) {
1828
+ await this.walk(hash);
1829
+ providers = await this.dht.providersFor(hash);
1830
+ }
1831
+ // last walk
1832
+ if (!providers || providers.length === 0) {
1833
+ await this.walk(hash);
1834
+ providers = await this.dht.providersFor(hash);
1835
+ }
1836
+ }
1837
+ // undefined if no providers given
1838
+ return providers
1839
+ }
1840
+
1841
+ get block() {
1842
+ return {
1843
+ get: async (hash) => {
1844
+ const data = await blockStore.has(hash);
1845
+ if (data) return await blockStore.get(hash)
1846
+ return this.requestData(hash, 'block')
1847
+ },
1848
+ put: async (hash, data) => {
1849
+ if (await blockStore.has(hash)) return
1850
+ return await blockStore.put(hash, data)
1851
+ },
1852
+ has: async (hash) => await blockStore.has(hash, 'block'),
1853
+ }
1854
+ }
1855
+
1856
+ get transaction() {
1857
+ return {
1858
+ get: async (hash) => {
1859
+ const data = await transactionStore.has(hash);
1860
+ if (data) return await transactionStore.get(hash)
1861
+ return this.requestData(hash, 'transaction')
1862
+ },
1863
+ put: async (hash, data) => {
1864
+ if (await transactionStore.has(hash)) return
1865
+ return await transactionStore.put(hash, data)
1866
+ },
1867
+ has: async (hash) => await transactionStore.has(hash),
1868
+ }
1869
+ }
1870
+
1871
+ async requestData(hash, store) {
1872
+ const providers = await this.providersFor(hash);
1873
+ if (!providers || providers.size === 0) throw nothingFoundError(hash)
1874
+ debug(`found ${providers.size} provider(s) for ${hash}`);
1875
+ // get closest peer on earth
1876
+ const closestPeer = await this.dht.closestPeer(providers);
1877
+ // get peer instance by id
1878
+ if (!closestPeer || !closestPeer.id) return this.requestData(hash, store.name ? store.name : store)
1879
+
1880
+ const id = closestPeer.id.toString();
1881
+ if (this.peers) {
1882
+ let closest = this.peers.filter((peer) => {
1883
+ if (this._getPeerId(peer.id) === id) return peer
1884
+ });
1885
+
1886
+ let data = new DataMessage({hash, store: store.name ? store.name : store});
1887
+
1888
+ const node = await this.prepareMessage(id, data.encoded);
1889
+ if (closest[0]) data = await closest[0].request(node.encoded);
1890
+ else {
1891
+ closest = this.peers.filter((peer) => {
1892
+ if (peer.id.toString() === id) return peer
1893
+ });
1894
+ if (closest[0]) data = await closest[0].request(node.encoded);
1895
+ }
1896
+ if (data.data) {
1897
+ let proto = protoFor(Buffer.from(data.data));
1898
+ proto = protoFor(proto.decoded.data);
1899
+ return proto.decoded.data
1900
+ }
1901
+
1902
+ // this.put(hash, proto.decoded.data)
1903
+ }
1904
+ return null
1905
+ }
1906
+
1907
+
1908
+ get message() {
1909
+ return {
1910
+ /**
1911
+ * Get content for given message hash
1912
+ *
1913
+ * @param {String} hash
1914
+ */
1915
+ get: async (hash) => {
1916
+ debug(`get message ${hash}`);
1917
+ const message = await messageStore.has(hash);
1918
+ if (message) return await messageStore.get(hash)
1919
+ return this.requestData(hash, 'message')
1920
+ },
1921
+ /**
1922
+ * put message content
1923
+ *
1924
+ * @param {String} hash
1925
+ * @param {Buffer} message
1926
+ */
1927
+ put: async (hash, message) => await messageStore.put(hash, message),
1928
+ /**
1929
+ * @param {String} hash
1930
+ * @return {Boolean}
1931
+ */
1932
+ has: async (hash) => await messageStore.has(hash),
1933
+ }
1934
+ }
1935
+
1936
+ get data() {
1937
+ return {
1938
+ /**
1939
+ * Get content for given data hash
1940
+ *
1941
+ * @param {String} hash
1942
+ */
1943
+ get: async (hash) => {
1944
+ debug(`get data ${hash}`);
1945
+ const data = await dataStore.has(hash);
1946
+ if (data) return await dataStore.get(hash)
1947
+ return this.requestData(hash, 'data')
1948
+ },
1949
+ /**
1950
+ * put data content
1951
+ *
1952
+ * @param {String} hash
1953
+ * @param {Buffer} data
1954
+ */
1955
+ put: async (hash, data) => await dataStore.put(hash, data),
1956
+ /**
1957
+ * @param {String} hash
1958
+ * @return {Boolean}
1959
+ */
1960
+ has: async (hash) => await dataStore.has(hash),
1961
+ }
1962
+ }
1963
+
1964
+ /**
1965
+ * goes trough given stores and tries to find data for given hash
1966
+ * @param {Array} stores
1967
+ * @param {string} hash
1968
+ */
1969
+ async whichStore(stores, hash) {
1970
+ let store = stores.pop();
1971
+ store = globalThis[`${store}Store`];
1972
+ if (store) {
1973
+ const has = await store.has(hash);
1974
+ if (has) return store
1975
+ if (stores.length > 0) return this.whichStore(stores, hash)
1976
+ } else return null
1977
+ }
1978
+
1979
+ /**
1980
+ * Get content for given hash
1981
+ *
1982
+ * @param {String} hash - the hash of the wanted data
1983
+ * @param {String} store - storeName to access
1984
+ */
1985
+ async get(hash, store) {
1986
+ debug(`get ${hash}`);
1987
+ let data;
1988
+ if (store) store = globalThis[`${store}Store`];
1989
+ if (!store) store = await this.whichStore([...this.stores], hash);
1990
+ if (store && await store.has(hash)) data = await store.get(hash);
1991
+ if (data) return data
1992
+
1993
+ return this.requestData(hash, store.name ? store.name : store)
1994
+ }
1995
+
1996
+ /**
1997
+ * put content
1998
+ *
1999
+ * @param {String} hash
2000
+ * @param {Buffer} data
2001
+ * @param {String} store - storeName to access
2002
+ */
2003
+ async put(hash, data, store = 'data') {
2004
+ store = globalThis[`${store}Store`];
2005
+ return store.put(hash, data)
2006
+ }
2007
+
2008
+ /**
2009
+ * @param {String} hash
2010
+ * @return {Boolean}
2011
+ */
2012
+ async has(hash) {
2013
+ const store = await this.whichStore([...this.stores], hash);
2014
+ if (store) {
2015
+ if (store.private) return false
2016
+ else return true
2017
+ }
2018
+ return false
2019
+ }
2020
+
2021
+ /**
2022
+ *
2023
+ * @param {String} topic
2024
+ * @param {String|Object|Array|Boolean|Buffer} data
2025
+ */
2026
+ async publish(topic, data) {
2027
+ // globalSub.publish(topic, data)
2028
+ if (!Buffer.isBuffer(topic)) topic = Buffer.from(topic);
2029
+ if (!Buffer.isBuffer(data)) data = Buffer.from(data);
2030
+ const id = Math.random().toString(36).slice(-12);
2031
+ data = new PsMessage({data, topic});
2032
+ for (const peer of this.peers) {
2033
+ if (peer.connection._connected) {
2034
+ if (peer.id.toString() !== this.peerId.toString()) {
2035
+ const node = await this.prepareMessage(peer.id, data.encoded);
2036
+ peer.send(Buffer.from(JSON.stringify({id, data: node.encoded})));
2037
+ }
2038
+ } else {
2039
+ this.removePeer(peer);
2040
+ }
2041
+ // TODO: if peer subscribed
2042
+ }
2043
+ }
2044
+
2045
+ createHash(data, name) {
2046
+ return new hash(data, {name})
2047
+ }
2048
+
2049
+ /**
2050
+ *
2051
+ * @param {String} topic
2052
+ * @param {Method} cb
2053
+ */
2054
+ async subscribe(topic, cb) {
2055
+ // TODO: if peer subscribed
2056
+ globalSub.subscribe(topic, cb);
2057
+ }
2058
+
2059
+ async removePeer(peer) {
2060
+ connections.delete(peer.id);
2061
+ }
2062
+
2063
+ get Buffer() {
2064
+ return Buffer
2065
+ }
2066
+ // async block(index) {
2067
+ // const _values = []
2068
+ // for (const peer of this.peers) {
2069
+ // const value = await peer.request({type: 'block', index})
2070
+ // console.log(value);
2071
+ // }
2072
+ //
2073
+ // }
2165
2074
  }
2166
2075
 
2167
2076
  module.exports = Peernet;