@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.
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/codec-format-interface.js.html +637 -0
- package/coverage/lcov-report/dht-response.js.html +193 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +131 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov.info +199 -0
- package/dist/browser/peernet.js +1288 -1385
- package/dist/commonjs/{client-bd0caeb7.js → client-1a1f75e6.js} +41 -41
- package/dist/commonjs/{codec-4a768e5e.js → codec-8c8c652f.js} +118 -118
- package/dist/commonjs/codec-format-interface.js +167 -167
- package/dist/commonjs/codec.js +2 -2
- package/dist/commonjs/dht-response.js +11 -11
- package/dist/commonjs/dht.js +2 -2
- package/dist/commonjs/hash.js +149 -149
- package/dist/commonjs/{http-2b0735ef.js → http-7bbac90a.js} +1 -1
- package/dist/commonjs/peernet-message.js +2 -2
- package/dist/commonjs/peernet.js +843 -934
- package/dist/commonjs/request.js +2 -2
- package/dist/commonjs/response.js +2 -2
- package/dist/module/peernet.js +1357 -1448
- package/package.json +2 -18
- package/src/client.js +75 -75
- package/src/codec/codec-format-interface.js +172 -172
- package/src/codec/codec.js +124 -124
- package/src/dht/dht.js +121 -121
- package/src/discovery/peer-discovery.js +75 -75
- package/src/hash/hash.js +155 -155
- package/src/http/client/http-client.js +44 -44
- package/src/messages/dht-response.js +14 -14
- package/src/peer.js +67 -67
- package/src/peernet.js +612 -612
- package/src/proto/chat-message.proto.js +7 -7
- package/src/utils/utils.js +78 -78
package/dist/commonjs/peernet.js
CHANGED
|
@@ -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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
}
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
//
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
}
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
const
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
const
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
if (
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
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;
|