@leofcoin/peernet 0.11.0 → 0.11.3

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 (46) 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/326.peernet.js +1 -0
  13. package/dist/browser/peernet.js +2 -108930
  14. package/dist/browser/peernet.js.LICENSE.txt +40 -0
  15. package/dist/commonjs/{client-bd0caeb7.js → client-1a1f75e6.js} +41 -41
  16. package/dist/commonjs/{codec-4a768e5e.js → codec-8c8c652f.js} +118 -118
  17. package/dist/commonjs/codec-format-interface.js +167 -167
  18. package/dist/commonjs/codec.js +2 -2
  19. package/dist/commonjs/dht-response.js +11 -11
  20. package/dist/commonjs/dht.js +2 -2
  21. package/dist/commonjs/hash.js +149 -149
  22. package/dist/commonjs/{http-2b0735ef.js → http-e088ccdb.js} +1 -1
  23. package/dist/commonjs/peernet-message.js +4 -4
  24. package/dist/commonjs/peernet.js +850 -943
  25. package/dist/commonjs/request.js +2 -2
  26. package/dist/commonjs/response.js +3 -3
  27. package/dist/module/peernet.js +1373 -1466
  28. package/index.html +2 -2
  29. package/package.json +6 -21
  30. package/src/client.js +75 -75
  31. package/src/codec/codec-format-interface.js +172 -172
  32. package/src/codec/codec.js +124 -124
  33. package/src/dht/dht.js +121 -121
  34. package/src/discovery/peer-discovery.js +75 -75
  35. package/src/handlers/message.js +2 -4
  36. package/src/hash/hash.js +155 -155
  37. package/src/http/client/http-client.js +44 -44
  38. package/src/messages/dht-response.js +14 -14
  39. package/src/peer.js +67 -67
  40. package/src/peernet.js +613 -612
  41. package/src/proto/chat-message.proto.js +7 -7
  42. package/src/proto/peernet.proto.js +2 -2
  43. package/src/proto/response.proto.js +1 -1
  44. package/src/utils/utils.js +78 -78
  45. package/test.js +1 -1
  46. package/webpack.config.js +10 -4
@@ -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 = {
@@ -1221,10 +1221,10 @@ class HDWallet {
1221
1221
  return network;
1222
1222
  }
1223
1223
 
1224
- async generate(network) {
1224
+ async generate(password, network) {
1225
1225
  network = this.validateNetwork(network);
1226
- const mnemonic = bip39.generateMnemonic();
1227
- const seed = await bip39.mnemonicToSeed(mnemonic);
1226
+ const mnemonic = bip39.generateMnemonic(256);
1227
+ const seed = await bip39.mnemonicToSeed(mnemonic, password);
1228
1228
  this.defineHDNode(bip32__namespace.fromSeed(seed, network));
1229
1229
  return mnemonic; // userpw
1230
1230
  }
@@ -1232,8 +1232,8 @@ class HDWallet {
1232
1232
  /**
1233
1233
  * recover using mnemonic (recovery word list)
1234
1234
  */
1235
- async recover(mnemonic, network) {
1236
- network = this.validateNetwork(network);
1235
+ async recover(mnemonic, password, network) {
1236
+ network = this.validateNetwork(network, password);
1237
1237
  const seed = await bip39.mnemonicToSeed(mnemonic);
1238
1238
  this.defineHDNode(bip32__namespace.fromSeed(seed, network));
1239
1239
  }
@@ -1433,8 +1433,8 @@ class MessageHandler {
1433
1433
  */
1434
1434
  async hashAndSignMessage(message) {
1435
1435
  const hasher = new hash(message, {name: 'peernet-message'});
1436
- const identity = await walletStore.get('identity');
1437
-
1436
+ let identity = await walletStore.get('identity');
1437
+ identity = JSON.parse(new TextDecoder().decode(identity));
1438
1438
  const wallet = new MultiWallet(this.network);
1439
1439
  wallet.import(identity.multiWIF);
1440
1440
  return wallet.sign(hasher.hash.slice(0, 32))
@@ -1447,8 +1447,6 @@ class MessageHandler {
1447
1447
  * or the messageNode itself
1448
1448
  */
1449
1449
  async prepareMessage(from, to, data, id) {
1450
- if (!Buffer.isBuffer(from)) from = new Buffer.from(from);
1451
- if (!Buffer.isBuffer(to)) to = new Buffer.from(to);
1452
1450
  if (data.encoded) data = data.encoded;
1453
1451
 
1454
1452
  const message = {
@@ -1479,689 +1477,598 @@ const nothingFoundError = (hash) => {
1479
1477
  return new Error(`nothing found for ${hash}`)
1480
1478
  };
1481
1479
 
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
-
1480
+ globalThis.leofcoin = globalThis.leofcoin || {};
1481
+ globalThis.globalSub = globalThis.globalSub || new PubSub({verbose: true});
1482
+
1483
+ /**
1484
+ * @access public
1485
+ * @example
1486
+ * const peernet = new Peernet();
1487
+ */
1488
+ class Peernet {
1489
+ /**
1490
+ * @access public
1491
+ * @param {Object} options
1492
+ * @param {String} options.network - desired network
1493
+ * @param {String} options.root - path to root directory
1494
+ * @param {String} options.storePrefix - prefix for datatores (lfc)
1495
+ *
1496
+ * @return {Promise} instance of Peernet
1497
+ *
1498
+ * @example
1499
+ * const peernet = new Peernet({network: 'leofcoin', root: '.leofcoin'});
1500
+ */
1501
+ constructor(options = {}) {
1502
+ this._discovered = [];
1503
+ /**
1504
+ * @property {String} network - current network
1505
+ */
1506
+ this.network = options.network || 'leofcoin';
1507
+ const parts = this.network.split(':');
1508
+
1509
+ if (!options.storePrefix) options.storePrefix = 'lfc';
1510
+ if (!options.port) options.port = 2000;
1511
+ if (!options.root) {
1512
+ if (parts[1]) options.root = `.${parts[0]}/peernet/${parts[1]}`;
1513
+ else options.root = `.${this.network}/peernet`;
1514
+ }
1515
+ globalThis.peernet = this;
1516
+ this.bw = {
1517
+ up: 0,
1518
+ down: 0,
1519
+ };
1520
+ return this._init(options)
1521
+ }
1522
+
1523
+ get defaultStores() {
1524
+ return ['account', 'wallet', 'block', 'transaction', 'chain', 'data', 'message']
1525
+ }
1526
+
1527
+ addProto(name, proto) {
1528
+ if (!this.protos[name]) this.protos[name] = proto;
1529
+ }
1530
+
1531
+ addCodec(name, codec) {
1532
+ if (!this.codecs[name]) this.codecs[name] = codec;
1533
+ }
1534
+
1535
+ async addStore(name, prefix, root, isPrivate = true) {
1536
+ if (name === 'block' || name === 'transaction' || name === 'chain' ||
1537
+ name === 'data' || name === 'message') isPrivate = false;
1538
+
1539
+ let Storage;
1540
+ if (this.hasDaemon) {
1541
+ Storage = LeofcoinStorageClient;
1542
+ } else {
1543
+ Storage = globalThis.LeofcoinStorage?.default ? globalThis.LeofcoinStorage.default : LeofcoinStorage__default["default"];
1544
+ }
1545
+ globalThis[`${name}Store`] = globalThis[`${name}Store`] ||
1546
+ await new Storage(`${prefix}-${name}`, root);
1547
+
1548
+ globalThis[`${name}Store`].private = isPrivate;
1549
+ if (!isPrivate) this.stores.push(name);
1550
+ }
1551
+
1552
+
1553
+ /**
1554
+ * @see MessageHandler
1555
+ */
1556
+ prepareMessage(to, data) {
1557
+ return this._messageHandler.prepareMessage(this.id, to, data)
1558
+ }
1559
+
1560
+ /**
1561
+ * @access public
1562
+ *
1563
+ * @return {Array} peerId
1564
+ */
1565
+ get peers() {
1566
+ return [...connections.values()]
1567
+ }
1568
+
1569
+ /**
1570
+ * @private
1571
+ *
1572
+ * @param {Object} options
1573
+ * @param {String} options.root - path to root directory
1574
+ *
1575
+ * @return {Promise} instance of Peernet
1576
+ */
1577
+ async _init(options) {
1578
+ // peernetDHT aka closesPeer by coordinates
1579
+ /**
1580
+ * @type {Object}
1581
+ * @property {Object} peer Instance of Peer
1582
+ */
1583
+ this.dht = new DhtEarth();
1584
+ /**
1585
+ * @type {Map}
1586
+ * @property {Object} peer Instance of Peer
1587
+ */
1588
+ this.peerMap = new Map();
1589
+ this.stores = [];
1590
+ this.requestProtos = {};
1591
+ this.storePrefix = options.storePrefix;
1592
+ this.root = options.root;
1593
+
1594
+ /**
1595
+ * proto Object containing protos
1596
+ * @type {Object}
1597
+ * @property {PeernetMessage} protos[peernet-message] messageNode
1598
+ * @property {DHTMessage} protos[peernet-dht] messageNode
1599
+ * @property {DHTMessageResponse} protos[peernet-dht-response] messageNode
1600
+ * @property {DataMessage} protos[peernet-data] messageNode
1601
+ * @property {DataMessageResponse} protos[peernet-data-response] messageNode
1602
+ */
1603
+ globalThis.peernet.protos = {
1604
+ 'peernet-request': request,
1605
+ 'peernet-response': response,
1606
+ 'peernet-peer': PeerMessage,
1607
+ 'peernet-peer-response': PeerMessageResponse,
1608
+ 'peernet-message': peernetMessage,
1609
+ 'peernet-dht': dht,
1610
+ 'peernet-dht-response': dhtResponse,
1611
+ 'peernet-data': DataMessage,
1612
+ 'peernet-data-response': DataMessageResponse,
1613
+ 'peernet-ps': PsMessage,
1614
+ 'chat-message': ChatMessage,
1615
+ };
1616
+
1617
+ this.protos = globalThis.peernet.protos;
1618
+ this.codecs = codec.codecs;
1619
+
1620
+ this._messageHandler = new MessageHandler(this.network);
1621
+
1622
+ const {daemon, environment} = await target();
1623
+ this.hasDaemon = daemon;
1624
+
1627
1625
  if (this.hasDaemon) {
1628
- const httpClient = await Promise.resolve().then(function () { return require('./client-bd0caeb7.js'); });
1626
+ const httpClient = await Promise.resolve().then(function () { return require('./client-1a1f75e6.js'); });
1629
1627
  globalThis.peernet.client = await httpClient.default({
1630
1628
  protocol: 'peernet-v0.1.0', host: '127.0.0.1', port: options.port
1631
1629
  });
1632
1630
  } else {
1633
- const http = await Promise.resolve().then(function () { return require('./http-2b0735ef.js'); });
1631
+ const http = await Promise.resolve().then(function () { return require('./http-e088ccdb.js'); });
1634
1632
  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
- // }
1633
+ }
1634
+
1635
+ for (const store of this.defaultStores) {
1636
+ await this.addStore(store, options.storePrefix, options.root);
1637
+ }
1638
+
1639
+ try {
1640
+ const pub = await accountStore.get('public');
1641
+ this.id = JSON.parse(new TextDecoder().decode(pub)).walletId;
1642
+ } catch (e) {
1643
+ if (e.code === 'ERR_NOT_FOUND') {
1644
+ const {identity, accounts, config} = await generateAccount__default["default"](this.network);
1645
+ walletStore.put('version', new TextEncoder().encode(1));
1646
+ walletStore.put('accounts', new TextEncoder().encode(accounts));
1647
+ walletStore.put('identity', new TextEncoder().encode(JSON.stringify(identity)));
1648
+ await accountStore.put('config', new TextEncoder().encode(JSON.stringify(config)));
1649
+ await accountStore.put('public', new TextEncoder().encode(JSON.stringify({walletId: identity.walletId})));
1650
+
1651
+ this.id = identity.walletId;
1652
+ } else {
1653
+ throw e
1654
+ }
1655
+ }
1656
+ this._peerHandler = new PeerDiscovery(this.id);
1657
+ this.peerId = this.id;
1658
+
1659
+ pubsub.subscribe('peer:connected', async (peer) => {
1660
+ console.log(peer);
1661
+ // console.log({connected: peer.id, as: this._getPeerId(peer.id) });
1662
+ // peer.on('peernet.data', async (message) => {
1663
+ // const id = message.id
1664
+ // message = new PeernetMessage(Buffer.from(message.data.data))
1665
+ // const proto = protoFor(message.decoded.data)
1666
+ // this._protoHandler({id, proto}, peer)
1667
+ // })
1668
+ });
1669
+
1670
+ pubsub.subscribe('peer:data', async message => {
1671
+ if (!message.data) return
1672
+ const {id, data} = JSON.parse(new TextDecoder().decode(message.data));
1673
+ const uint8Array = new Uint8Array(Object.keys(data).length);
1674
+ for (var i = 0; i < Object.keys(data).length; i++) {
1675
+ uint8Array[i] = data[i];
1676
+ }
1677
+ message = new peernetMessage(uint8Array);
1678
+ const proto = protoFor(message.decoded.data);
1679
+
1680
+ const from = message.decoded.from;
1681
+ this._protoHandler({id, proto}, this.client.connections[from], from);
1682
+ });
1683
+
1684
+ /**
1685
+ * @access public
1686
+ * @type {PeernetClient}
1687
+ */
1688
+ this.client = new Client(this.id);
1689
+ if (globalThis.onbeforeunload) {
1690
+ globalThis.addEventListener('beforeunload', async () => this.client.close());
1691
+ }
1692
+ return this
1693
+ }
1694
+
1695
+ _getPeerId(id) {
1696
+ for (const entry of [...this.peerMap.entries()]) {
1697
+ for (const _id of entry[1]) {
1698
+ if (_id === id) return entry[0]
1699
+ }
1700
+ }
1701
+ }
1702
+
1703
+ addRequestHandler(name, method) {
1704
+ this.requestProtos[name] = method;
1705
+ }
1706
+
1707
+ /**
1708
+ * @private
1709
+ *
1710
+ * @param {Buffer} message - peernet message
1711
+ * @param {PeernetPeer} peer - peernet peer
1712
+ */
1713
+ async _protoHandler(message, peer, from) {
1714
+ const {id, proto} = message;
1715
+ this.bw.down += proto.encoded.length;
1716
+
1717
+ if (proto.name === 'peernet-dht') {
1718
+ let { hash, store } = proto.decoded;
1719
+ let has;
1720
+
1721
+ if (!store) {
1722
+ has = await this.has(hash);
1723
+ } else {
1724
+ store = globalThis[`${store}Store`];
1725
+ if (store.private) has = false;
1726
+ else has = await store.has(hash);
1727
+ }
1728
+ const data = new dhtResponse({hash, has});
1729
+ const node = await this.prepareMessage(from, data.encoded);
1730
+
1731
+ peer.send(new TextEncoder().encode(JSON.stringify({id, data: node.encoded})));
1732
+ this.bw.up += node.encoded.length;
1733
+ } else if (proto.name === 'peernet-data') {
1734
+ let { hash, store } = proto.decoded;
1735
+ let data;
1736
+ if (!store) {
1737
+ store = await this.whichStore([...this.stores], hash);
1738
+ } else {
1739
+ store = globalThis[`${store}Store`];
1740
+ }
1741
+ if (store && !store.private) {
1742
+ data = await store.get(hash);
1743
+
1744
+ if (data) {
1745
+ data = new DataMessageResponse({hash, data: data.decoded ? new TextEncoder().encode(JSON.stringify(data.decoded)) : data});
1746
+
1747
+ const node = await this.prepareMessage(from, data.encoded);
1748
+ peer.send(new TextEncoder().encode(JSON.stringify({id, data: node.encoded})));
1749
+ this.bw.up += node.encoded.length;
1750
+ }
1751
+ }
1752
+
1753
+ } else if (proto.name === 'peernet-request') {
1754
+ // TODO: make dynamic
1755
+ // exposeddevapi[proto.decoded.request](proto.decoded.params)
1756
+ const method = this.requestProtos[proto.decoded.request];
1757
+ if (method) {
1758
+ const data = await method();
1759
+ const node = await this.prepareMessage(from, data.encoded);
1760
+ peer.send(new TextEncoder().encode(JSON.stringify({id, data: node.encoded})));
1761
+
1762
+ this.bw.up += node.encoded.length;
1763
+ }
1764
+ } else if (proto.name === 'peernet-ps' &&
1765
+ this._getPeerId(peer.id) !== this.id.toString()) {
1766
+ globalSub.publish(proto.decoded.topic.toString(), proto.decoded.data.toString());
1767
+ }
1768
+ // }
1769
+ }
1770
+
1771
+ /**
1772
+ * performs a walk and resolves first encounter
1773
+ *
1774
+ * @param {String} hash
1775
+ */
1776
+ async walk(hash) {
1777
+ if (!hash) throw new Error('hash expected, received undefined')
1778
+ const data = new dht({hash});
1779
+ this.client.id;
1780
+ for (const peer of this.peers) {
1781
+ const node = await this.prepareMessage(peer.id, data.encoded);
1782
+
1783
+ const result = await peer.request(node.encoded);
1784
+
1785
+ let proto = protoFor(result.data);
1786
+
1787
+ if (proto.name !== 'peernet-message') throw encapsulatedError()
1788
+ const from = proto.decoded.from;
1789
+ proto = protoFor(proto.decoded.data);
1790
+
1791
+ if (proto.name !== 'peernet-dht-response') throw dhtError(proto.name)
1792
+
1793
+ // TODO: give ip and port (just used for location)
1794
+ if (!peer.connection.remoteAddress || !peer.connection.localAddress) {
1795
+ peer.connection.remoteFamily = 'ipv4';
1796
+ peer.connection.remoteAddress = '127.0.0.1';
1797
+ peer.connection.remotePort = '0000';
1798
+ }
1799
+
1800
+ const peerInfo = {
1801
+ family: peer.connection.remoteFamily || peer.connection.localFamily,
1802
+ address: peer.connection.remoteAddress || peer.connection.localAddress,
1803
+ port: peer.connection.remotePort || peer.connection.localPort,
1804
+ id: from,
1805
+ };
1806
+
1807
+ if (proto.decoded.has) this.dht.addProvider(peerInfo, proto.decoded.hash);
1808
+ }
1809
+ return
1810
+ }
1811
+
1812
+ /**
1813
+ * Override DHT behavior, try's finding the content three times
1814
+ *
1815
+ * @param {String} hash
1816
+ */
1817
+ async providersFor(hash) {
1818
+ let providers = await this.dht.providersFor(hash);
1819
+ // walk the network to find a provider
1820
+ if (!providers || providers.length === 0) {
1821
+ await this.walk(hash);
1822
+ providers = await this.dht.providersFor(hash);
1823
+ // second walk the network to find a provider
1824
+ if (!providers || providers.length === 0) {
1825
+ await this.walk(hash);
1826
+ providers = await this.dht.providersFor(hash);
1827
+ }
1828
+ // last walk
1829
+ if (!providers || providers.length === 0) {
1830
+ await this.walk(hash);
1831
+ providers = await this.dht.providersFor(hash);
1832
+ }
1833
+ }
1834
+ // undefined if no providers given
1835
+ return providers
1836
+ }
1837
+
1838
+ get block() {
1839
+ return {
1840
+ get: async (hash) => {
1841
+ const data = await blockStore.has(hash);
1842
+ if (data) return await blockStore.get(hash)
1843
+ return this.requestData(hash, 'block')
1844
+ },
1845
+ put: async (hash, data) => {
1846
+ if (await blockStore.has(hash)) return
1847
+ return await blockStore.put(hash, data)
1848
+ },
1849
+ has: async (hash) => await blockStore.has(hash, 'block'),
1850
+ }
1851
+ }
1852
+
1853
+ get transaction() {
1854
+ return {
1855
+ get: async (hash) => {
1856
+ const data = await transactionStore.has(hash);
1857
+ if (data) return await transactionStore.get(hash)
1858
+ return this.requestData(hash, 'transaction')
1859
+ },
1860
+ put: async (hash, data) => {
1861
+ if (await transactionStore.has(hash)) return
1862
+ return await transactionStore.put(hash, data)
1863
+ },
1864
+ has: async (hash) => await transactionStore.has(hash),
1865
+ }
1866
+ }
1867
+
1868
+ async requestData(hash, store) {
1869
+ const providers = await this.providersFor(hash);
1870
+ if (!providers || providers.size === 0) throw nothingFoundError(hash)
1871
+ debug(`found ${providers.size} provider(s) for ${hash}`);
1872
+ // get closest peer on earth
1873
+ const closestPeer = await this.dht.closestPeer(providers);
1874
+ // get peer instance by id
1875
+ if (!closestPeer || !closestPeer.id) return this.requestData(hash, store.name ? store.name : store)
1876
+
1877
+ const id = closestPeer.id.toString();
1878
+ if (this.peers) {
1879
+ let closest = this.peers.filter((peer) => {
1880
+ if (this._getPeerId(peer.id) === id) return peer
1881
+ });
1882
+
1883
+ let data = new DataMessage({hash, store: store.name ? store.name : store});
1884
+
1885
+ const node = await this.prepareMessage(id, data.encoded);
1886
+ if (closest[0]) data = await closest[0].request(node.encoded);
1887
+ else {
1888
+ closest = this.peers.filter((peer) => {
1889
+ if (peer.id.toString() === id) return peer
1890
+ });
1891
+ if (closest[0]) data = await closest[0].request(node.encoded);
1892
+ }
1893
+ if (data.data) {
1894
+ console.log(data.data);
1895
+ let proto = protoFor(data.data);
1896
+ proto = protoFor(proto.decoded.data);
1897
+ return proto.decoded.data
1898
+ }
1899
+
1900
+ // this.put(hash, proto.decoded.data)
1901
+ }
1902
+ return null
1903
+ }
1904
+
1905
+
1906
+ get message() {
1907
+ return {
1908
+ /**
1909
+ * Get content for given message hash
1910
+ *
1911
+ * @param {String} hash
1912
+ */
1913
+ get: async (hash) => {
1914
+ debug(`get message ${hash}`);
1915
+ const message = await messageStore.has(hash);
1916
+ if (message) return await messageStore.get(hash)
1917
+ return this.requestData(hash, 'message')
1918
+ },
1919
+ /**
1920
+ * put message content
1921
+ *
1922
+ * @param {String} hash
1923
+ * @param {Buffer} message
1924
+ */
1925
+ put: async (hash, message) => await messageStore.put(hash, message),
1926
+ /**
1927
+ * @param {String} hash
1928
+ * @return {Boolean}
1929
+ */
1930
+ has: async (hash) => await messageStore.has(hash),
1931
+ }
1932
+ }
1933
+
1934
+ get data() {
1935
+ return {
1936
+ /**
1937
+ * Get content for given data hash
1938
+ *
1939
+ * @param {String} hash
1940
+ */
1941
+ get: async (hash) => {
1942
+ debug(`get data ${hash}`);
1943
+ const data = await dataStore.has(hash);
1944
+ if (data) return await dataStore.get(hash)
1945
+ return this.requestData(hash, 'data')
1946
+ },
1947
+ /**
1948
+ * put data content
1949
+ *
1950
+ * @param {String} hash
1951
+ * @param {Buffer} data
1952
+ */
1953
+ put: async (hash, data) => await dataStore.put(hash, data),
1954
+ /**
1955
+ * @param {String} hash
1956
+ * @return {Boolean}
1957
+ */
1958
+ has: async (hash) => await dataStore.has(hash),
1959
+ }
1960
+ }
1961
+
1962
+ /**
1963
+ * goes trough given stores and tries to find data for given hash
1964
+ * @param {Array} stores
1965
+ * @param {string} hash
1966
+ */
1967
+ async whichStore(stores, hash) {
1968
+ let store = stores.pop();
1969
+ store = globalThis[`${store}Store`];
1970
+ if (store) {
1971
+ const has = await store.has(hash);
1972
+ if (has) return store
1973
+ if (stores.length > 0) return this.whichStore(stores, hash)
1974
+ } else return null
1975
+ }
1976
+
1977
+ /**
1978
+ * Get content for given hash
1979
+ *
1980
+ * @param {String} hash - the hash of the wanted data
1981
+ * @param {String} store - storeName to access
1982
+ */
1983
+ async get(hash, store) {
1984
+ debug(`get ${hash}`);
1985
+ let data;
1986
+ if (store) store = globalThis[`${store}Store`];
1987
+ if (!store) store = await this.whichStore([...this.stores], hash);
1988
+ if (store && await store.has(hash)) data = await store.get(hash);
1989
+ if (data) return data
1990
+
1991
+ return this.requestData(hash, store.name ? store.name : store)
1992
+ }
1993
+
1994
+ /**
1995
+ * put content
1996
+ *
1997
+ * @param {String} hash
1998
+ * @param {Buffer} data
1999
+ * @param {String} store - storeName to access
2000
+ */
2001
+ async put(hash, data, store = 'data') {
2002
+ store = globalThis[`${store}Store`];
2003
+ return store.put(hash, data)
2004
+ }
2005
+
2006
+ /**
2007
+ * @param {String} hash
2008
+ * @return {Boolean}
2009
+ */
2010
+ async has(hash) {
2011
+ const store = await this.whichStore([...this.stores], hash);
2012
+ if (store) {
2013
+ if (store.private) return false
2014
+ else return true
2015
+ }
2016
+ return false
2017
+ }
2018
+
2019
+ /**
2020
+ *
2021
+ * @param {String} topic
2022
+ * @param {String|Object|Array|Boolean|Buffer} data
2023
+ */
2024
+ async publish(topic, data) {
2025
+ // globalSub.publish(topic, data)
2026
+ if (topic instanceof Uint8Array === false) topic = new TextEncoder().encode(topic);
2027
+ if (data instanceof Uint8Array === false) data = new TextEncoder().encode(JSON.stringify(data));
2028
+ const id = Math.random().toString(36).slice(-12);
2029
+ data = new PsMessage({data, topic});
2030
+ for (const peer of this.peers) {
2031
+ if (peer.connection._connected) {
2032
+ if (peer.id.toString() !== this.peerId.toString()) {
2033
+ const node = await this.prepareMessage(peer.id, data.encoded);
2034
+ peer.send(new TextEncoder().encode(JSON.stringify({id, data: node.encoded})));
2035
+ }
2036
+ } else {
2037
+ this.removePeer(peer);
2038
+ }
2039
+ // TODO: if peer subscribed
2040
+ }
2041
+ }
2042
+
2043
+ createHash(data, name) {
2044
+ return new hash(data, {name})
2045
+ }
2046
+
2047
+ /**
2048
+ *
2049
+ * @param {String} topic
2050
+ * @param {Method} cb
2051
+ */
2052
+ async subscribe(topic, cb) {
2053
+ // TODO: if peer subscribed
2054
+ globalSub.subscribe(topic, cb);
2055
+ }
2056
+
2057
+ async removePeer(peer) {
2058
+ connections.delete(peer.id);
2059
+ }
2060
+
2061
+ get Buffer() {
2062
+ return Buffer
2063
+ }
2064
+ // async block(index) {
2065
+ // const _values = []
2066
+ // for (const peer of this.peers) {
2067
+ // const value = await peer.request({type: 'block', index})
2068
+ // console.log(value);
2069
+ // }
2070
+ //
2071
+ // }
2165
2072
  }
2166
2073
 
2167
2074
  module.exports = Peernet;